Interop Excel不closures进程

我一直在这个问题上挣扎了好几天,我已经做了研究和应用了我在各种论坛上发现的所有build议,但是我仍然无法解决这个问题。

我的问题是与Excel使用互操作库,我有一个Excel文件用作模板,所以我打开它,并保存在一个新的名称与一个新的位置。 除了在创build并closures文件之后,Excel进程始终运行之外,所有工作都很好。

这是我的代码

protected string CreateExcel(string strProjectID, string strFileMapPath) { string strCurrentDir = HttpContext.Current.Server.MapPath("~/Reports/Templates/"); string strFile = "Not_Created"; Application oXL; Workbook oWB; oXL = new Application(); oXL.Visible = false; Workbooks wbks = oXL.Workbooks; //opening template file oWB = wbks.Open(strFileMapPath); oXL.Visible = false; oXL.UserControl = false; strFile = strProjectID + "_" + DateTime.Now.Ticks.ToString() + ".xlsx"; //Saving file with new name oWB.SaveAs(strCurrentDir + strFile, XlFileFormat.xlWorkbookDefault, null, null, false, false, XlSaveAsAccessMode.xlExclusive, false, false, null, null); oWB.Close(false, strCurrentDir + strFile, Type.Missing); wbks.Close(); oXL.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(oXL); System.Runtime.InteropServices.Marshal.ReleaseComObject(wbks); System.Runtime.InteropServices.Marshal.ReleaseComObject(oWB); oWB = null; oXL = null; wbks = null; GC.Collect(); return strFile; } 

正如你所看到的,我正在closures并释放所有对象,但应用程序不会退出。

我正在使用IIS7在32位Windows Server 2008(产品)和Windows 7(开发)中进行testing。

尝试

 Process excelProcess = Process.GetProcessesByName("EXCEL")[0]; if (!excelProcess.CloseMainWindow()) { excelProcess.Kill(); } 

这是我解决这个问题的方法:

 // Store the Excel processes before opening. Process[] processesBefore = Process.GetProcessesByName("excel"); // Open the file in Excel. Application excelApplication = new Application(); Workbook excelWorkbook = excelApplication.Workbooks.Open(Filename); // Get Excel processes after opening the file. Process[] processesAfter = Process.GetProcessesByName("excel"); // Now find the process id that was created, and store it. int processID = 0; foreach (Process process in processesAfter) { if (!processesBefore.Select(p => p.Id).Contains(process.Id)) { processID = process.Id; } } // Do the Excel stuff // Now close the file with the COM object. excelWorkbook.Close(); excelApplication.Workbooks.Close(); excelApplication.Quit(); // And now kill the process. if (processID != 0) { Process process = Process.GetProcessById(processID); process.Kill(); } 

我为它创build了这个方法,在我的testing中它工作。

 private void ClearMemory(Application excelApp) { excelApp.DisplayAlerts = false; excelApp.ActiveWorkbook.Close(0); excelApp.Quit(); Marshal.ReleaseComObject(excelApp); } 

尝试使用Open XML SDK 2.0 for Microsoft Office库来创buildExcel文档,而不是使用interop程序集。 它的运行速度快了很多,而且使用起来也很方便。

这里是VB版本 – 我有一个大项目,使用这个,而不是时间来转换到一个更好的系统,所以这里是相同的答案…在vb.NET

使用它来获取进程ID(在打开Excel表之前)

 Dim excelProcess(0) As Process excelProcess = Process.GetProcessesByName("excel") 

完成工作表后:

 xlWorkBook.Close(SaveChanges:=False) xlApp.Workbooks.Close() xlApp.Quit() 'Kill the process If Not excelProcess(0).CloseMainWindow() Then excelProcess(0).Kill() End If 

看看这里: 我怎样才能得到一个隐藏的Excel应用程序实例的ProcessID(PID)

您可以通过GetWindowThreadProcessId API跟踪您的ProcessID,并杀死与您的Excel Application对象实例特别匹配的进程。

 [DllImport("user32.dll")] static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId); Process GetExcelProcess(Microsoft.Office.Interop.Excel.Application excelApp) { int id; GetWindowThreadProcessId(excelApp.Hwnd, out id); return Process.GetProcessById(id); } void TerminateExcelProcess(Microsoft.Office.Interop.Excel.Application excelApp) { var process = GetExcelProcess(excelApp); if (process != null) { process.Kill(); } } 
 oWB.Close(false, strCurrentDir + strFile, Type.Missing); oWB.Dispose(); wbks.Close(); wbks.Dispose(); oXL.Quit(); oXL.Dispose(); System.Runtime.InteropServices.Marshal.ReleaseComObject(oXL); System.Runtime.InteropServices.Marshal.ReleaseComObject(wbks); System.Runtime.InteropServices.Marshal.ReleaseComObject(oWB);