Excel进程不会closures

一旦完成使用,我无法使EXCEL(32)进程closures。

正如你可以在下面的代码中看到的,一旦ProcessRFAFData函数完成其执行,EXCEL进程不会closures(我仍然可以在任务pipe理器中看到EXCEL.EXE*32 )。

由于这个原因,当SaveErrors开始执行时,我得到以下exception:

 System.Runtime.InteropServices.COMException (0x800A03EC): Microsoft Office Excel cannot open or save any more documents because there is not enough available memory or disk space. • To make more memory available, close workbooks or programs you no longer need. • To free disk space, delete files you no longer need from the disk you are saving to. at Microsoft.Office.Interop.Excel.Workbooks.Add(Object Template) at NextG.RFAFImport.Layouts.NextG.RFAFImport.RFAFDataImporter.<>c__DisplayClass9.b__6() at Microsoft.SharePoint.SPSecurity.<>c__DisplayClass4.b__2() at Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated secureCode) at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback secureCode, Object param) at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode) at NextG.RFAFImport.Layouts.NextG.RFAFImport.RFAFDataImporter.SaveErrors() 

这是执行Excel进程的代码:

 try { ProcessRFAFData(FileName); } catch (Exception ex) { Status = "ERROR: " + ex.ToString(); } if (Errors.Count() > 0) { SaveErrors(); } 

以下是与Excel交互的所有function:

 private void ReleaseObject(object obj) { try { System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); obj = null; } catch (Exception) { } finally { GC.Collect(); } } private void ProcessRFAFData(string FileName) { Microsoft.Office.Interop.Excel.Application XLA = null; Microsoft.Office.Interop.Excel.Workbook XLW = null; Microsoft.Office.Interop.Excel.Worksheet XLS = null; bool error = false; try { SPSecurity.RunWithElevatedPrivileges(delegate() { XLA = new Microsoft.Office.Interop.Excel.Application(); XLW = XLA.Workbooks.Open(FileName, 0, true, Type.Missing, null, null, true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, Type.Missing, false, false, Type.Missing, false, Type.Missing, Type.Missing); int index = RFAFTabExists(ref XLW); if (index == 0) return; XLS = (Microsoft.Office.Interop.Excel.Worksheet)XLW.Worksheets.get_Item(index); if (!ValidProjectID(ref XLS)) return; ParseData(ref XLS); XLW.Close(true, Type.Missing, Type.Missing); XLA.Quit(); ReleaseObject(XLS); ReleaseObject(XLW); ReleaseObject(XLA); }); } catch (SP.ServerException ex) { // output error } catch (Exception ex) { // output error } } private int RFAFTabExists(ref Microsoft.Office.Interop.Excel.Workbook XLW) { int index = 0; foreach (Microsoft.Office.Interop.Excel.Worksheet w in XLW.Worksheets) { if (w.Name.Equals(settings.Collection["RFAFTabName"])) index++; } return index; } private bool ValidProjectID(ref Microsoft.Office.Interop.Excel.Worksheet XLS) { using (SP.ClientContext CTX = new SP.ClientContext(SiteURL)) { var projectId = XLS.Cells.get_Range(settings.Collection["ProjectIDCell"], Type.Missing).Text.ToString(); var project = // getting list of projects from SharePoint if (project.Count() > 0) { ProjectID = XLS.Cells.get_Range(settings.Collection["ProjectIDCell"], Type.Missing).Text.ToString(); return true; } } return false; } private void ParseData(ref Microsoft.Office.Interop.Excel.Worksheet XLS) { ListData.Add("HID", GetHID(XLS.Cells.get_Range(settings.Collection["HIDCell"], Type.Missing).Text.ToString())); if (ListData["HID"].Equals("0")) Errors.Add(new ImportError { Reason = "Hub ID does not exist in this project workspace.", Reference = string.Format("Hub ID: {0}", XLS.Cells.get_Range(settings.Collection["HIDCell"], Type.Missing).Text.ToString()) }); int row = Int32.Parse(settings.Collection["StartRow"]); while (!NoMoreData(ref XLS, row)) { string PRSIN = XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["PRSIN"], row), Type.Missing).Text.ToString(); string NOC = ValidateNumber(XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["NOC"], row), Type.Missing).Text.ToString()); string UEIRP = ValidateNumber(XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["UEIRP"], row), Type.Missing).Text.ToString()); string LAT = ValidateLatLon(XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["LAT"], row), Type.Missing).Text.ToString()); string LON = ValidateLatLon(XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["LON"], row), Type.Missing).Text.ToString()); string PJ = GetPJ(XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["JurisdictionCol"], row), Type.Missing).Text.ToString(), XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["StateCol"], row), Type.Missing).Text.ToString()); string ST = GetState(XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["JurisdictionCol"], row), Type.Missing).Text.ToString(), XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["StateCol"], row), Type.Missing).Text.ToString()); ListItemData.Add(new ListItem { ProposedRemoteSiteItemNumber = PRSIN, NumberOfCarriers = NOC, UsableEIRP = UEIRP, Latitude = LAT, Longitude = LON, PrimaryJurisdiction = PJ, State = ST }); row++; } } private bool NoMoreData(ref Microsoft.Office.Interop.Excel.Worksheet XLS, int row) { return string.IsNullOrEmpty(XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["ProposedRemoteSiteItemNumberCol"], row), Type.Missing).Text.ToString()); } private void SaveErrors() { Microsoft.Office.Interop.Excel.Application XLA = null; Microsoft.Office.Interop.Excel.Workbook XLW = null; Microsoft.Office.Interop.Excel.Worksheet XLS = null; object MissingValue = System.Reflection.Missing.Value; try { try { SPSecurity.RunWithElevatedPrivileges(delegate() { XLA = new Microsoft.Office.Interop.Excel.Application(); XLW = XLA.Workbooks.Add(MissingValue); XLS = (Microsoft.Office.Interop.Excel.Worksheet)XLW.Worksheets.get_Item(1); XLS.Cells[1, 1] = "Reason for error"; XLS.Cells[1, 2] = "Reference"; XLS.get_Range("A1").Font.Bold = true; XLS.get_Range("B1").Font.Bold = true; int row = 2; foreach (ImportError e in Errors) { XLS.Cells[row, 1] = e.Reason; XLS.Cells[row, 2] = e.Reference; row++; } XLW.SaveAs(ErrorLogFileName, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookNormal, MissingValue, MissingValue, MissingValue, MissingValue, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, MissingValue, MissingValue, MissingValue, MissingValue, MissingValue); XLW.Close(true, MissingValue, MissingValue); XLA.Quit(); ReleaseObject(XLS); ReleaseObject(XLW); ReleaseObject(XLA); }); } catch (Exception ex) { Status = "ERROR: " + ex.ToString(); } // Uploading excel file to SharePoint document library } catch (Exception) { } } 

你可能不得不去明确地说 :

 excelWorkbook.Close (false, System.Reflection.Missing.Value,System.Reflection.Missing.Value) ; excelWorkbooks.Close(); excelApp.Quit(); Marshal.ReleaseComObject(excelWorksheet); Marshal.ReleaseComObject(excelSheets); Marshal.ReleaseComObject(excelWorkbooks); Marshal.ReleaseComObject(excelWorkbook); Marshal.ReleaseComObject(excelApp); excelWorksheet = null; excelSheets = null; excelWorkbooks = null; excelWorkbook = null; excelApp = null; GC.GetTotalMemory(false); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.GetTotalMemory(true); 

我遇到过这种情况,即使那样做也没有。 我采取了追捕Excel的过程,并把它叫做Kill()。

如果出现exception,请在finally块中释放Excel对象。

 try { ... } catch { ... } finally { ReleaseObject(XLS); ReleaseObject(XLW); ReleaseObject(XLA); } 

第一个build议: http : //code.google.com/p/excellibrary这是一个伟大的图书馆,我用了很多成功。

第二个build议:如果你绝对必须closuresExcel

 /// <summary> /// Gets all currently running instances of Excel, so we don't kill active windows. /// </summary> private void GetInstancesToSave() { if (_instancesToSaveList != null) { _instancesToSaveList.Clear(); } _instancesToSaveList = Process.GetProcesses().ToList<Process>(); _instancesToSaveList = _instancesToSaveList.FindAll(proc => proc.ProcessName == "EXCEL"); } /// <summary> /// Kills any instances of Excel that were created by the program. /// </summary> /// <param name="zInstancesToSave">Instances that were not </param> private static void KillExcel(List<Process> zInstancesToSave) { List<Process> xProcesslist = Process.GetProcesses().ToList<Process>(); xProcesslist = xProcesslist.FindAll(proc => proc.ProcessName == "EXCEL"); foreach (Process xTheprocess in xProcesslist)//read through all running programs { bool killit = true; foreach (Process proc in zInstancesToSave)//read through all running programs { if (xTheprocess.Id == proc.Id) { killit = false; } } if (killit) { xTheprocess.Kill(); } } } 

您可以使用这两种方法来跟踪启动时运行哪些excel实例,然后find应用程序打开的任何Excel实例,然后将其杀死。 这当然不是一个很好的解决scheme,但有时你只能咬紧牙关。

如果你不关心以前的情况,你也可以这样做:

 /// <summary> /// Kills any instances of Excel that were created by the program. /// </summary> /// <param name="zInstancesToSave">Instances that were not </param> private static void KillExcel(List<Process> zInstancesToSave) { List<Process> xProcesslist = Process.GetProcesses().ToList<Process>(); xProcesslist = xProcesslist.FindAll(proc => proc.ProcessName == "EXCEL"); foreach(Proc process in xProcesslist) { process.Kill(); } } 

我会考虑使用Code Plex中的EPPlus 。
这个例子展示了如何读取数据。 如果你需要调用公式,那么你在这条路线上的服务器总是更好 – 只有问题是,这种方法是行不通的。
你的大部分代码与你当前的代码非常相似,所以我估计转移到这个库需要几个小时。

在我的情况下,Excel加载项居住在我之前创build的单独的AppDomain中,但是当加载项被卸载时,我从来没有调用过:

 childDomain.Unload(); 

一旦被调用,Excel僵尸进程不再存在…

除了上面的解决scheme,这里是我的LOGICAL解决scheme。 我在想为什么我有这么多的EXCEL.EXE应用程序,并以这种方式处理。 在这里,我正在检查条件,同时创build新的Excel应用程序。 if(_masterApp == null)_masterApp = new EXCEL.Application(); 如果要创build的variables是Null,则只创buildExcel应用程序的新实例,否则重新分配现有variables。

并使用本博客中提到的解决scheme来closures_masterApp。

优点:这种方式只能closures通过解决scheme打开的EXCEL应用程序,而不能closures手动打开的Excel应用程序。