我有这个C#程序永远不会关闭Excel进程。基本上,它查找字符串在Excel中的范围中出现的实例数。我尝试了各种各样的东西,但它没有用。有一个Form调用此方法,但这不应该更改进程未关闭的原因。我看过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();
}
*/
}
}
}
答案 0 :(得分:3)
这是一个有趣的知识库,关于办公室应用程序在.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;
}
答案 1 :(得分:2)
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;
}
答案 2 :(得分:1)
我终于把它关闭了。您需要为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;
}
}