Excel进程未关闭[重复]
Posted
技术标签:
【中文标题】Excel进程未关闭[重复]【英文标题】:Excel process not closing [duplicate] 【发布时间】:2013-08-09 19:33:50 【问题描述】:我有一个永远不会关闭 Excel 进程的 C# 程序。基本上,它会找到字符串出现在 Excel 范围内的实例数。我已经尝试了各种各样的东西,但它不起作用。有一个表单正在调用此方法,但这不应改变进程未关闭的原因。我查看了 Hans Passant 的建议,但没有一个有效。
编辑:我尝试了提到的东西,但它仍然不会关闭。这是我更新的代码。 编辑:尝试了整个 Process.Kill() 并且它可以工作,但是对于应该可以工作的东西来说似乎有点破解。
public class CompareHelper
// Define Variables
Excel.Application excelApp = null;
Excel.Workbooks wkbks = null;
Excel.Workbook wkbk = null;
Excel.Worksheet wksht = null;
Dictionary<String, int> map = new Dictionary<String, int>();
// Compare columns
public void GetCounts(string startrow, string endrow, string columnsin, System.Windows.Forms.TextBox results, string excelFile)
results.Text = "";
try
// Create an instance of Microsoft Excel and make it invisible
excelApp = new Excel.Application();
excelApp.Visible = false;
// open a Workbook and get the active Worksheet
wkbks = excelApp.Workbooks;
wkbk = wkbks.Open(excelFile, Type.Missing, true);
wksht = wkbk.ActiveSheet;
...
catch
throw;
finally
GC.Collect();
GC.WaitForPendingFinalizers();
if (wksht != null)
//wksht.Delete();
Marshal.FinalReleaseComObject(wksht);
wksht = null;
if (wkbks != null)
//wkbks.Close();
Marshal.FinalReleaseComObject(wkbks);
wkbks = null;
if (wkbk != null)
excelApp.DisplayAlerts = false;
wkbk.Close(false, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(wkbk);
wkbk = null;
if (excelApp != null)
excelApp.Quit();
Marshal.FinalReleaseComObject(excelApp);
excelApp = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
/*
Process[] processes = Process.GetProcessesByName("EXCEL");
foreach (Process p in processes)
p.Kill();
*/
【问题讨论】:
较小的复制品会有所帮助。无论如何,我在我的机器上运行了这个并且 Excel 关闭得很好。您是否安装了任何表现不佳的 Excel 加载项?尝试一一删除,看看是否会影响 Excel 干净关闭的能力。 我尝试了一个普通的 Excel 进程,但它仍然没有关闭。我正在使用表单作为调用此类的接口,这是否可以使 Excel 保持打开状态? 这实际上是我认为您希望从上述链接获得的第三个答案。 仅供参考,千万不要“catch throw;”。这与没有“捕获”相同。 【参考方案1】:这是一个有趣的知识库,主题是 Office 应用程序在 .NET 应用程序与它们断开连接后保持打开状态。
Office application does not quit after automation from Visual Studio .NET client
代码示例都在链接中(vb.net 抱歉)。基本上,它向您展示了如何正确设置和拆除办公应用程序,以便在您完成后关闭它。
System.Runtime.InteropServices.Marshal.FinalReleaseComObject
是魔法发生的地方。
编辑:您需要为您创建的每个 excel 对象调用 FinalReleaseComObject。
if (excelWorkSheet1 != null)
Marshal.FinalReleaseComObject(excelWorkSheet1);
excelWorkSheet1 = null;
if (excelWorkbook != null)
Marshal.FinalReleaseComObject(excelWorkbook);
excelWorkbook = null;
if (excelApp != null)
Marshal.FinalReleaseComObject(excelApp);
excelApp = null;
【讨论】:
这个方法我试过了,不行。是否有未释放的资源使 Excel 保持打开状态? 是的,有一个 RCW“运行时可调用包装器”,如果它没有在 .NET 应用程序中发布,它会导致进程保持活动状态。 这个方法我也试过了,也没用。 将 Workbooks 集合添加到您正在调用 FinalReleaseComObject 的对象列表中,它将起作用。【参考方案2】:我终于把它关闭了。您需要为 Workbooks 集合添加一个变量,然后按照其他答案中的说明使用 FinalReleaseComObject。我猜您使用的每一个可能的 Excel COM 对象都必须以这种方式处理。
try
// Create an instance of Microsoft Excel and make it invisible
excelApp = new Excel.Application();
excelApp.DisplayAlerts = false;
excelApp.Visible = false;
// open a Workbook and get the active Worksheet
excelWorkbooks = excelApp.Workbooks;
excelWorkbook = excelWorkbooks.Open(excelFile, Type.Missing, true);
excelWorkSheet1 = excelWorkbook.ActiveSheet;
catch
throw;
finally
NAR( excelWorkSheet1 );
excelWorkbook.Close(false, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
NAR(excelWorkbook);
NAR(excelWorkbooks);
excelApp.Quit();
NAR(excelApp);
private void NAR(object o)
try
System.Runtime.InteropServices.Marshal.FinalReleaseComObject( o );
catch
finally
o = null;
【讨论】:
我试过了,还是不行。有没有办法找到 excelApp 的进程 ID 并杀死它? 您可以在调试/崩溃时停止 Excel 的情况下添加它。但不建议正常使用。注释掉部分并解决问题所在的部分。 我使用了您的确切代码示例,出现了同样的问题,一旦我将步骤添加到 NAR 工作簿,它就解决了问题。【参考方案3】:DotNet 仅在释放所有句柄后才释放 COM 对象。我所做的是将所有内容都注释掉,然后再添加一部分。看看它是否发布了 Excel。如果它不遵循以下规则。当它发布时,添加更多代码,直到它不再发布。
1) 创建 Excel 变量时,将所有值设置为 null(这样可以避免未启动的错误)
2) 不先释放变量不要重用Marshal.FinalReleaseComObject
3) 不要双点(a.b = z)
。 dotNet 创建一个临时变量,不会被释放。
c = a.b;
c = z;
Marshal.FinalReleaseComObject(c);
4) 释放所有 excel 变量。越快越好。
5) 将其设置回 NULL。
将文化设置为“en-US”。有一个错误会使 Excel 在某些文化中崩溃。这确保它不会。
以下是您的代码应该如何构建的想法:
thisThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
InteropExcel.Application excelApp = null;
InteropExcel.Workbooks wkbks = null;
InteropExcel.Workbook wkbk = null;
try
excelApp = new InteropExcel.Application();
wkbks = excelApp.Workbooks;
wkbk = wkbks.Open(fileName);
...
catch (Exception ex)
if (wkbk != null)
excelApp.DisplayAlerts = false;
wkbk.Close(false);
Marshal.FinalReleaseComObject(wkbk);
wkbk = null;
if (wkbks != null)
wkbks.Close();
Marshal.FinalReleaseComObject(wkbks);
wkbks = null;
if (excelApp != null)
// Close Excel.
excelApp.Quit();
Marshal.FinalReleaseComObject(excelApp);
excelApp = null;
// Change culture back from en-us to the original culture.
thisThread.CurrentCulture = originalCulture;
【讨论】:
以上是关于Excel进程未关闭[重复]的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 python 通过子进程与 Excel 文件进行通信? [关闭]