gpt4 book ai didi

c# - 代码运行时退出 Interop 控制的 Excel

转载 作者:行者123 更新时间:2023-11-30 12:48:23 24 4
gpt4 key购买 nike

我已经用 C# 为 Excel 编写了一个包装器,以便允许在批处理过程中运行 Excel 工作簿(在 JobScheduler 下)。我的问题是……

如果代码运行时间太长或需要通过作业调度程序终止,则包装器需要处理此终止事件。为此我添加了

SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);

进入代码。在 ConsoleCtrlCheck 方法中,我调用了一个通用的退出例程(在正常或终止情况下使用)。此路由根据 MS 的建议执行以下操作。

关闭和释放工作簿
关闭并释放 Excel
垃圾收集

然后退出并返回调用的 Excel 方法的返回码(入口点)。这很好用。

但是,如果 VBA 代码仍在运行,Interop 对象将不会响应工作簿关闭或应用程序退出调用。这可能是因为一切进展缓慢或因为已发出模态对话框。为了解决这个问题,我在这个通用例程的开头添加了以下内容......

  • 创建新线程以运行 KillExcel 方法
  • KillExcel 方法休眠一段指定的时间(因此正常的退出代码有机会起作用)然后终止进程
  • 如果正常代码工作正常,它会在线程上调用 Abort
private static void Cleanup()
{
// Give this X seconds then terminate
mKillThread = new Thread(KillExcel);
mKillThread.IsBackground = false;
mKillThread.Start();
...
// close the workbooks and excel application
// Marshal.FinalReleaseComObject etc

GC.Collect();
GC.WaitForPendingFinalizers();

// Not sure if necessary but makes sure Process gone
try
{
Process p = Process.GetProcessById(mExcelPid);
p.WaitForExit();
}
catch(ArgumentException)
{}

mKillThread.Abort();
}

private static void KillExcel()
{
Thread.Sleep(Settings.Default.KillWaitMilliSeconds);

if (mLog.IsInfoEnabled)
mLog.Info(string.Format("Waited {0} seconds, killing Excel process [{1}]",Settings.Default.KillWaitMilliSeconds/1000, mExcelPid));

try
{
Process p = Process.GetProcessById(mExcelPid);

if (!p.HasExited)
p.Kill();
}
catch(ArgumentException)
{
}
}

我的问题是,是否有更好的方法来解决这个问题,或者是否必须采用这种方法才能确保在作业终止事件中删除 excel 进程?

最佳答案

您所做的几乎是完全确保 Excel 退出的标准方法。考虑到涉及 COM Interop,并且 excel 有留下孤儿实例的坏习惯,您遵循的方法几乎是万无一失的。

但是,如果您可以访问 vba 代码并且可以控制它,那么您可以做一件基本的事情来确保 VBA 代码确实允许其他代码运行。

DoEvents

根据我的经验,在运行大量计算之前和之后放置这一行代码通常可以让 excel 正确处理例行事件。虽然通常建议将其用于 UI 相关操作,但它也可以让 Worksheet/Application 事件正常工作。

希望这对您有所帮助。

关于c# - 代码运行时退出 Interop 控制的 Excel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14269777/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com