啊,另一个“Excel不发布”帖子就这样.....
我有一个Excel工作簿,我通过Excel(2010)加载,调用Excel应用程序的Run方法在工作簿中启动宏,保存更新的工作簿并退出Excel。
即使在通话应用程序关闭后,Excel仍然落后。
我没有陷入“双点”陷阱,我关闭所有可以关闭的东西,退出所有可以退出的东西并释放对每个使用的COM对象的每个引用,并给予GC一脚。
如果我没有调用运行宏,一切都很顺利。因此,关于这个特定宏的一些问题是错误的,因为其他工作簿没有显示这种行为。
宏本身加载了Solver加载项,并在非.NET win32 dll中对C ++函数进行了一些调用。它调用Solver加载项,并且不做任何其他异常(数学,设置范围,设置单元格值等)。
我应该知道任何解决者或与宏相关的陷阱吗?我甚至尝试从C#卸载加载项 - 没有快乐。
static void NAR(object o) // MSDN article suggestion.
{
try
{
while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0)
{
}
}
catch
{
// swallow
}
finally
{
o = null;
}
}
static void Excel(string FilePath, string SaveAsPath)
{
Application excelApplication = null;
Workbooks workbooks = null;
Workbook workbook = null;
try
{
excelApplication = new Application { DisplayAlerts = false, Visible = false };
workbooks = excelApplication.Workbooks;
workbook = workbooks.Open(FilePath);
excelApplication.Run("SolveEquationWithSolver");
workbook.CheckCompatibility = false;
workbook.SaveAs(SaveAsPath);
}
finally
{
if (workbook != null)
{
workbook.Close(Microsoft.Office.Interop.Excel.XlSaveAction.xlDoNotSaveChanges, Type.Missing, Type.Missing);
NAR(workbook);
}
if (workbooks != null)
{
workbooks.Close();
NAR(workbooks);
}
if (excelApplication != null)
{
excelApplication.Quit();
NAR(excelApplication);
}
// Kick GC, as suggested elsewhere on SO. Not my idea.
GC.Collect();
GC.WaitForPendingFinalizers();
// Double-tap GC, as suggested elsewhere on SO. Not my idea.
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
更新
另一个论坛建议使用excelApplication.ActiveWindow.Close()
,这样可行!! (如果删除了workbook.Close()
来电)。
然而,这打破了“两点”规则。那么,它在做什么意味着我们可以在这种情况下逃脱它,但不是在一般情况下?
答案 0 :(得分:1)
我曾经遇到过与你类似的问题,并最终放弃并决定杀死Excel。如果在杀死进程之前关闭所涉及的工作簿,则不应该有任何烦人的副作用(例如下次打开Excel时“恢复”的工作簿)。
using System.Runtime.InteropServices;
// ...
// Inside a class:
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(
IntPtr hWnd, out uint lpdwProcessId);
// Returns "true" on success, "false" on failure.
public static bool KillExcel(Application excel) {
uint processId;
GetWindowThreadProcessId((IntPtr)excel.Hwnd, out processID);
try {
Process.GetProcessById((int)processID).Kill()
} catch (Exception /* TODO: catch only relevant exceptions */) {
return false;
}
return true;
}