如何在C#中正确closures/处理Excel COM?(Excel进程不closures)

是的,我知道,这是在互联网上,也可能在这里,我也跟着很多例子,但仍然没有closures,我真的厌倦了这个问题,如果有人可以find一个解决scheme,而不是杀死Excel过程中,请通过分享来帮助我!

我的代码:

#region ////////// Declarations and initialisations ////////// string[] sFilesPath = System.IO.Directory.GetFiles(Path); // Get all files from current Path MSExcel.Application xlApp = null; MSExcel.Workbook xlWorkBook = null; MSExcel.Workbooks xlWorkBooks = null; MSExcel.Sheets xlSheets = null; MSExcel.Shapes xlShapes = null; MSExcel.Worksheet xlWorkSheet = null; MSExcel.Worksheets xlWorkSheets = null; xlApp = new MSExcel.Application(); xlApp.Visible = false; xlApp.DisplayAlerts = false; xlWorkBooks = xlApp.Workbooks; xlWorkBook = xlWorkBooks.Open(Path + _xlNamesList[i] + ".xlsx"); xlSheets = xlWorkBook.Sheets; #endregion \\\\\\\\\\ Declarations and initialisations \\\\\\\\\\ #region ////////// Clear all previous WorkSheets ////////// foreach (MSExcel.Worksheet Worksheet in xlSheets) { Worksheet.Cells.Clear(); foreach (MSExcel.Shape sh in Worksheet.Shapes) { sh.Delete(); Marshal.ReleaseComObject(sh); } } if (xlSheets != null) Marshal.ReleaseComObject(xlSheets); #endregion \\\\\\\\\\ Clear all previous WorkSheets \\\\\\\\\\ #region ////////// Insert each screenshot at it's respective location ////////// foreach (string File in sFilesPath) { string sFileExtension = System.IO.Path.GetExtension(File); if (sFileExtension == ".jpg") // Insert each jpg file in it's coresponding place { //---> Declarations and initialisations string sFileNameWitouthExtension = System.IO.Path.GetFileNameWithoutExtension(File), sShiftName = sFileNameWitouthExtension.Substring(sFileNameWitouthExtension.Length - 7), sLineName = sFileNameWitouthExtension.Substring(0, sFileNameWitouthExtension.Length - 8); xlWorkSheet = xlWorkBook.Worksheets[sLineName]; // Get the coresponding worksheet to edit based on LineName //---> Place the screenshot in the Excel file based on sShiftName if (sShiftName == "Shift 1") { xlWorkSheet.Cells[1, 4] = sFileNameWitouthExtension; xlWorkSheet.Cells[1, 4].Font.Size = 30; xlWorkSheet.Cells[1, 4].Rows.AutoFit(); xlWorkSheet.Cells[1, 4].Columns.AutoFit(); xlWorkSheet.Shapes.AddPicture(File, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoCTrue, 50, 40, 800, 500); } else if (sShiftName == "Shift 2") { xlWorkSheet.Cells[40, 4] = sFileNameWitouthExtension; xlWorkSheet.Cells[40, 4].Font.Size = 30; xlWorkSheet.Cells[40, 4].Rows.AutoFit(); xlWorkSheet.Cells[40, 4].Columns.AutoFit(); xlWorkSheet.Shapes.AddPicture(File, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoCTrue, 50, 650, 800, 500); } else if (sShiftName == "Shift 3") { xlWorkSheet.Cells[78, 4] = sFileNameWitouthExtension; xlWorkSheet.Cells[78, 4].Font.Size = 30; xlWorkSheet.Cells[78, 4].Rows.AutoFit(); xlWorkSheet.Cells[78, 4].Columns.AutoFit(); xlWorkSheet.Shapes.AddPicture(File, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoCTrue, 50, 1245, 800, 500); } } } #endregion \\\\\\\\\\ Insert each screenshot at it's respective location \\\\\\\\\\ #region ////////// Save EXCEL file and release/close objects ////////// xlWorkBook.SaveAs(Path + _xlNamesList[i++] + ".xlsx", MSExcel.XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing, false, false, MSExcel.XlSaveAsAccessMode.xlNoChange, MSExcel.XlSaveConflictResolution.xlLocalSessionChanges, Type.Missing, Type.Missing); xlWorkBook.Close(); xlApp.Quit(); if (xlShapes != null) { Marshal.ReleaseComObject(xlShapes); xlShapes = null; } if (xlWorkSheet != null) { Marshal.ReleaseComObject(xlWorkSheet); xlWorkSheet = null; } if (xlWorkSheets != null) { Marshal.ReleaseComObject(xlWorkSheets); xlWorkSheets = null; } if (xlWorkBook != null) { Marshal.ReleaseComObject(xlWorkBook); xlWorkBook = null; } if (xlWorkBooks != null) { Marshal.ReleaseComObject(xlWorkBooks); xlWorkBooks = null; } if (xlApp != null) { Marshal.ReleaseComObject(xlApp); xlApp = null; } GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); #endregion \\\\\\\\\\ Save EXCEL file and release/close objects \\\\\\\\\\ #region ////////// Kill EXCEL proccess ---> DON'T WANT THIS!!! ////////// foreach (Process Proc in Process.GetProcesses()) if (Proc.ProcessName.Equals("EXCEL")) Proc.Kill(); #endregion \\\\\\\\\\ Kill EXCEL proccess \\\\\\\\\\ 

在通过GC之后,Excel过程仍然存在:/已经让我疯狂了。 请帮忙!!!

/ /编辑:感谢汉斯标记为重复,其他职位FINALY回答我的问题,所有的Tumb规则和点和对象发布是一块废话,你只需要把GC的外部方法不在里面…

问题是你必须获取每个(中间)对象,并调用ReleaseComObject 。 否则,你有什么悬念不会被释放,Excel不会closures。

下面是导致这些问题的代码的一些不好的例子:

  xlWorkSheet = xlWorkBook.Worksheets[sLineName]; 

有了这个,你有一个悬而未决的参考Worksheets 。 最好这样写:

  xlWorkSheets = xlWorkBook.Worksheets; xlWorkSheet = xlWorkSheets[sLineName]; 

还有一个:

 xlWorkSheet.Cells[40, 4].Rows.AutoFit(); 

这应该是更好的:

 var cells = xlWorkSheet.Cells[40,4]; var rows = cells.Rows; rows.AutoFit(); 

所有这些中间对象将被放入一个HashSet<object> 。 最后,我会遍历这个列表,并调用所有的释放方法。

经验法则是: 如果你的命令中有多个点是错误的。

要find这样的问题,我开始我的包装只创build和closuresExcel实例。 然后我testing了excel打开并立即closures。 然后我开始慢慢地访问一些对象并进行testing。 在每一个新的两行之间我添加了我testing如果excel仍然closures,当我调用quit方法。 到目前为止,这是一个非常困难和令人沮丧的方式,但是唯一可靠地清理所有对象。