【问题标题】:Exiting Interop controlled Excel when code running代码运行时退出互操作控制的 Excel
【发布时间】:2023-03-16 00:48:01
【问题描述】:

我用 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 进程而必须这样做?

【问题讨论】:

    标签: c# excel com-interop interrupt terminate


    【解决方案1】:

    您所做的几乎是完全确保 Excel 退出的标准方法。鉴于涉及 COM 互操作,并且 Excel 有留下孤立实例的讨厌习惯,您遵循的方法几乎是万无一失的。

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

    DoEvents
    

    根据我的经验,在运行繁重的计算之前和之后放置那一行代码通常可以让 excel 正确处理常规事件。虽然通常建议将这用于 UI 相关操作,但它也可以让工作表/应用程序事件正常工作。

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      是否有机会用第三方库(如 EPPLUS)替换 VBA 逻辑?那将是更快的数量级....

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-25
        • 1970-01-01
        相关资源
        最近更新 更多