উপস্থাপনা: আমার উত্তরে দুটি সমাধান রয়েছে, সুতরাং পড়ার সময় সতর্ক থাকুন এবং কোনও কিছুই মিস করবেন না।
কীভাবে এক্সেল উদাহরণ আনলোড করা যায় তার বিভিন্ন উপায় এবং পরামর্শ রয়েছে যেমন:
মার্শালের সাথে স্পষ্টভাবে প্রতিটি কম অবজেক্ট প্রকাশ করা F ফিনালআরেলিজ কমঅবজেক্ট () (স্পষ্টভাবে তৈরি কম-অবজেক্টগুলি সম্পর্কে ভুলে যাবেন না)। প্রতিটি নির্মিত কম কম অবজেক্ট প্রকাশ করার জন্য, আপনি এখানে উল্লিখিত 2 টি বিন্দুর বিধি ব্যবহার করতে পারেন:
আমি কীভাবে এক্সেল ইন্টারপ অবজেক্টগুলি সঠিকভাবে পরিষ্কার করব?
সিএলআর রিলিজকে অব্যবহৃত কম-অবজেক্টগুলি তৈরি করার জন্য জিসি.কলেক্ট () এবং জিসি.ওয়েটফরপেন্ডিং ফিনালাইজারস () কে কল করা হচ্ছে (আসলে এটি কাজ করে, বিশদের জন্য আমার দ্বিতীয় সমাধান দেখুন)
কম-সার্ভার-অ্যাপ্লিকেশনটি সম্ভবত কোনও উত্তর দেওয়ার অপেক্ষায় একটি বার্তা বাক্স দেখায় কিনা তা পরীক্ষা করা (যদিও আমি নিশ্চিত নই যে এটি এক্সেলটি বন্ধ হতে বাধা দিতে পারে তবে আমি এটি সম্পর্কে কয়েকবার শুনেছি)
মূল এক্সেল উইন্ডোতে WM_CLOSE বার্তা প্রেরণ
এক্সেলের সাথে পৃথক অ্যাপডোমায়নে কাজ করে এমন ক্রিয়াকলাপ সম্পাদন করা হচ্ছে। কিছু লোক বিশ্বাস করে যে অ্যাপ্লোমেনটি লোড করা হলে এক্সেল উদাহরণটি বন্ধ হয়ে যাবে।
আমাদের এক্সেল-আন্তঃবিদ্যুত কোডটি শুরুর পরে তাত্ক্ষণিকভাবে কার্যকর হওয়া সমস্ত এক্সেল দৃষ্টান্ত হত্যা করা।
কিন্ত! কখনও কখনও এই সমস্ত বিকল্পগুলি কেবল সহায়তা করে না বা উপযুক্ত হতে পারে না!
উদাহরণস্বরূপ, গতকাল আমি জানতে পেরেছিলাম যে আমার একটি ফাংশনে (যা এক্সেলের সাথে কাজ করে) এক্সেলটি ফাংশন শেষ হওয়ার পরে চলতে থাকে। আমি সব চেষ্টা করেছিলাম! আমি পুরো ফাংশনটি 10 বার পুঙ্খানুপুঙ্খভাবে পরীক্ষা করে দেখেছি এবং মার্শাল.ফিনাল রিলিজকোমজেক্ট () সব কিছুর জন্য যুক্ত করেছি! আমারও ছিল জিসি.ক্লোকটেক্ট () এবং জিসি.ওয়েটফোরপেন্ডিং ফিনালাইজারস ()। আমি লুকানো বার্তার বাক্সগুলি পরীক্ষা করেছিলাম। আমি ডাব্লুএম_সিএলএসই বার্তাটি প্রধান এক্সেল উইন্ডোতে প্রেরণ করার চেষ্টা করেছি। আমি আমার ফাংশনটি একটি পৃথক অ্যাপডোমেনে সম্পাদন করেছি এবং সেই ডোমেনটি লোড করেছি। কিছুই সাহায্য করেনি! সমস্ত এক্সেল দৃষ্টান্ত বন্ধ করার বিকল্পটি অনুপযুক্ত, কারণ যদি ব্যবহারকারী আমার অন্য ক্রিয়াকলাপটি ম্যানুয়ালি শুরু করে, যখন আমার ক্রিয়াকলাপটি এক্সেলের সাথেও কাজ করে, তারপরে সেই উদাহরণটিও আমার ফাংশন দ্বারা বন্ধ হয়ে যাবে। আমি বাজি ধরছি ব্যবহারকারী খুশি হবে না! সুতরাং, সত্যি বলতে, এটি একটি খোঁড়া বিকল্প (কোনও অপরাধের লোক নয়)।সমাধান : এর মূল উইন্ডোটির hWnd দ্বারা এক্সেল প্রক্রিয়াটি হত্যা করুন (এটি প্রথম সমাধান)।
এখানে সহজ কোডটি রয়েছে:
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
/// <summary> Tries to find and kill process by hWnd to the main window of the process.</summary>
/// <param name="hWnd">Handle to the main window of the process.</param>
/// <returns>True if process was found and killed. False if process was not found by hWnd or if it could not be killed.</returns>
public static bool TryKillProcessByMainWindowHwnd(int hWnd)
{
uint processID;
GetWindowThreadProcessId((IntPtr)hWnd, out processID);
if(processID == 0) return false;
try
{
Process.GetProcessById((int)processID).Kill();
}
catch (ArgumentException)
{
return false;
}
catch (Win32Exception)
{
return false;
}
catch (NotSupportedException)
{
return false;
}
catch (InvalidOperationException)
{
return false;
}
return true;
}
/// <summary> Finds and kills process by hWnd to the main window of the process.</summary>
/// <param name="hWnd">Handle to the main window of the process.</param>
/// <exception cref="ArgumentException">
/// Thrown when process is not found by the hWnd parameter (the process is not running).
/// The identifier of the process might be expired.
/// </exception>
/// <exception cref="Win32Exception">See Process.Kill() exceptions documentation.</exception>
/// <exception cref="NotSupportedException">See Process.Kill() exceptions documentation.</exception>
/// <exception cref="InvalidOperationException">See Process.Kill() exceptions documentation.</exception>
public static void KillProcessByMainWindowHwnd(int hWnd)
{
uint processID;
GetWindowThreadProcessId((IntPtr)hWnd, out processID);
if (processID == 0)
throw new ArgumentException("Process has not been found by the given main window handle.", "hWnd");
Process.GetProcessById((int)processID).Kill();
}
আপনি দেখতে পাচ্ছেন যে ট্রায় পার্স-প্যাটার্ন অনুসারে আমি দুটি পদ্ধতি সরবরাহ করেছি (আমি মনে করি এটি এখানে যথাযথ): প্রক্রিয়াটি হত্যা না করতে পারলে একটি পদ্ধতি ব্যতিক্রম ঘটায় না (উদাহরণস্বরূপ প্রক্রিয়াটির আর অস্তিত্ব নেই) , এবং অন্য পদ্ধতিটি যদি ব্যর্থ হয় তবে প্রক্রিয়াটি হত্যা না করা হয়। এই কোডের একমাত্র দুর্বল জায়গা হ'ল সুরক্ষা অনুমতি। তাত্ত্বিকভাবে, ব্যবহারকারীর প্রক্রিয়াটি মারার অনুমতি নাও থাকতে পারে, তবে সব ক্ষেত্রে 99.99% এ ব্যবহারকারীর কাছে এই জাতীয় অনুমতি রয়েছে। আমি এটি একটি অতিথি অ্যাকাউন্টের সাথেও পরীক্ষা করেছি - এটি পুরোপুরি কার্যকর করে works
সুতরাং, আপনার কোড, এক্সেলের সাথে কাজ করা, এটি দেখতে দেখতে দেখতে পারে:
int hWnd = xl.Application.Hwnd;
// ...
// here we try to close Excel as usual, with xl.Quit(),
// Marshal.FinalReleaseComObject(xl) and so on
// ...
TryKillProcessByMainWindowHwnd(hWnd);
ভাল খবর! এক্সেল সমাপ্ত! :)
ঠিক আছে, আসুন দ্বিতীয় সমাধানটিতে ফিরে যাই, যেমন আমি পোস্টের শুরুতে প্রতিশ্রুতি দিয়েছিলাম।
দ্বিতীয় সমাধানটি হ'ল জিসি.কলেক্ট্রেট () এবং জিসি.ওয়েটফোরপেন্ডিংফাইনালাইজার ()। হ্যাঁ, এগুলি আসলে কাজ করে তবে আপনার এখানে যত্নবান হওয়া দরকার!
অনেক লোক বলে (এবং আমি বলেছি) যে সিসি কলেক্ট () কল করে কোনও লাভ হয় না। তবে এটি সাহায্য না করার কারণটি যদি এখনও COM অবজেক্টের উল্লেখ থাকে! জিসি.কলেক্ট () সহায়ক না হওয়ার অন্যতম জনপ্রিয় কারণ হ'ল প্রকল্পটি ডিবাগ-মোডে চালানো। ডিবাগ-মোড অবজেক্টগুলিতে যা প্রকৃতপক্ষে রেফারেন্স হয় না সেগুলি পদ্ধতিটির শেষ না হওয়া অবধি আবর্জনা সংগ্রহ করা হবে না।
সুতরাং, আপনি যদি জিসি.কলেক্টর () এবং জিসি.ওয়েটফরপেন্ডিংফাইনালাইজারস () চেষ্টা করে থাকেন এবং এটি কোনও উপকার না করে, তবে নিম্নলিখিতগুলি করার চেষ্টা করুন:
1) আপনার প্রকল্পটি রিলিজ মোডে চালানোর চেষ্টা করুন এবং এক্সেলটি সঠিকভাবে বন্ধ হয়েছে কিনা তা দেখুন
2) এক্সেলের সাথে কাজ করার পদ্ধতিটি একটি পৃথক পদ্ধতিতে মোড়ানো। সুতরাং এর পরিবর্তে এই জাতীয় কিছু:
void GenerateWorkbook(...)
{
ApplicationClass xl;
Workbook xlWB;
try
{
xl = ...
xlWB = xl.Workbooks.Add(...);
...
}
finally
{
...
Marshal.ReleaseComObject(xlWB)
...
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
তুমি লেখ:
void GenerateWorkbook(...)
{
try
{
GenerateWorkbookInternal(...);
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
private void GenerateWorkbookInternal(...)
{
ApplicationClass xl;
Workbook xlWB;
try
{
xl = ...
xlWB = xl.Workbooks.Add(...);
...
}
finally
{
...
Marshal.ReleaseComObject(xlWB)
...
}
}
এখন, এক্সেল বন্ধ হবে =)