使用C#操作Excel的COM組件的過程中,最後把EXCEL進程關閉掉是十分重要的。網上有一些方法,我總結了其中兩條,並測試通過。
首先第一種是利用.net的GC,即記憶體回收行程。代碼如下:
Code
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Runtime.InteropServices;
5
6 namespace ExcelTest
7 {
8 class DataOutput
9 {
10 static void Main(string[] args)
11 {
12 Excel.Application app = new Excel.ApplicationClass();
13 Excel.Workbook wBook = app.Workbooks.Add(true);
14 Excel.Worksheet wSheet = wBook.Worksheets[1] as Excel.Worksheet;
15 app.Visible = true;
16
17 System.Runtime.InteropServices.Marshal.ReleaseComObject(wSheet);
18 System.Runtime.InteropServices.Marshal.ReleaseComObject(wBook);
19 System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
20 GC.Collect(); //顯式調用GC
21
22 Console.Read();
23 }
24 }
25 }
關注後面四行,System.Runtime.InteropServices.Marshal類主要提供對非受託管記憶體的操作。對於函數ReleaseComObject,在MSDN上的解釋是“該運行庫可調用封裝具有引用計數,每次將 COM 介面指標映射到該運行庫可調用封裝時,此引用計數都將遞增。ReleaseComObject 方法遞減運行庫可調用封裝的引用計數。當引用計數達到零時,運行庫將釋放非託管 COM 物件上的所有引用。”即斷開對對象的引用,這樣GC發現對象不會再被使用,那麼就會回收它。
第二種方法是通過進程的ID號把進程kill掉。但第一種方法有網友說有時候不靈,因為本人只是簡單地用控制台來測試,可能在其它情況下不一定行,所以推薦使用第二種方法。
Code
1 namespace ExcelTest
2 {
3 class DataOutput
4 {
5 static void Main(string[] args)
6 {
7 Excel.Application app = new Excel.ApplicationClass();
8 Excel.Workbook wBook = app.Workbooks.Add(true);
9 Excel.Worksheet wSheet = wBook.Worksheets[1] as Excel.Worksheet;
10 app.Visible = true;
11
12 Kill(app);
13
14 Console.Read();
15 }
16
17 [DllImport("User32.dll", CharSet = CharSet.Auto)]
18 public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
19
20 public static void Kill(Excel.Application excel)
21 {
22 IntPtr t = new IntPtr(excel.Hwnd); //得到這個控制代碼,具體作用是得到這塊記憶體入口
23
24 int k = 0;
25 GetWindowThreadProcessId(t, out k); //得到本進程唯一標誌k
26 System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k); //得到對進程k的引用
27 p.Kill(); //關閉進程k
28
29 }
30 }
31 }
GetWindowThreadProcessId函數是User32.dll中函數,作用是通過對象的控制代碼得到對象的進程ID。extern 修飾符用於聲明在外部實現的方法。明白這點後,整個過程就很簡單了:其實就是先獲得Excel.Application執行個體app的控制代碼,再通過控制代碼得到進程ID,最後把該ID的進程Kill掉。