Visual C# Office自動化Excel進程殘留問題

       在進行客戶端編程時,經常需要進行office自動化操作,其中對於Excel使用大概又是其中最爲頻繁的。不過,讓大家頗爲鬱悶的是,經常會有excel進程不能被正常關閉。不論大家怎樣小心或者是單步跟蹤來找問題,總是會有未被釋放的com object 。我個人感覺這不能不說是office自動化的一個瑕疵,功能已經很傻瓜了,而其使用卻又需要這麼謹小慎微。

       以前在使用VC++6.0時,就經常會遇到這個問題,最近升級到VS2010,改玩C#了,本以爲由於自帶的GC功能而能自動解決這個問題,沒想到,還是會出現。看來是com設計的問題了。

       從google的搜索結果來看,主要的解決方法無外乎兩種:一種是謹小慎微,對於每個變量都予以保存,到最後記得釋放;另一種則是比較野蠻了,直接kill掉殘留excel進程。

       方法1從理論上固然可取,我想各位肯定想正確的使用並最終完全釋放掉所有涉及資源,但是由於實際操作中涉及的對象衆多,難免掛一漏萬,所以實際上還是會出問題。有人甚至對excel中的主要對象進行了再封裝,可以自動釋放對於com object的引用。

       方法2看起來野蠻,但是操作簡單。我在網上也看到了有些kill進程的方法,這些方法對excel進程不加區分,格殺勿論,會導致用戶體驗問題。但是隻要提前保存自己所調用excel進程的句柄則可以不必濫殺無辜。具體實施方案如下:

 


using System.Runtime.InteropServices;
using System.Diagnostics;


[ 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;
}

使用示例:
int hWnd = xl.Application.Hwnd;

// ...
// here we try to close Excel as usual, with xl.Quit(),
// Marshal.FinalReleaseComObject(xl) and so on
// ...

TryKillProcessByMainWindowHwnd(hWnd);


      最後,給出上述解決方案的原鏈接: http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章