如果COM应用程序崩溃,如何正确处置COM对象?

时间:2017-09-21 07:13:20

标签: c# com com-interop

问题:

我必须通过来自C#.NET应用程序的COM interop调用应用程序。我已经编写了一个包装类来处理COM的东西,所有这些都很有效。

public sealed class ComWrapper : IDisposable
{
    private Application comApplication = new Application(); // Referenced COM assembly.
    private bool disposed;

    // Several methods to interact with the com application.

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
         if(disposed)
             return;

         try
         {
             if(comApplication != null && Marshal.IsComObject(comApplication));
                 Marshal.ReleaseComObject(comApplication);
         }
         finally
         {
             comApplication = null;
         }

         disposed = true;
    }
}

只要COM应用程序正常运行,我就可以调用应用程序,使用其方法和所有工作。

但是,如果应用程序崩溃(有时在数据库连接丢失时会执行此操作),则可执行文件将保持加载状态。在Process Explorer中,我可以在svchost.exe下使用werfault.exe进程查看应用程序的进程,即使我在捕获COMException后手动调用垃圾收集器。

catch(COMException)
{
    app.Dispose();
    app = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();
}

如何以正确退出应用程序并关闭进程的方式正确处理COM对象,即使该COM应用程序已崩溃?我考虑过确定所述应用程序的进程ID并使用Process.Kill(),但这对我来说似乎有点难看。那么什么是终止和释放崩溃应用程序资源的适当方法呢?

1 个答案:

答案 0 :(得分:2)

如果这是外部COM服务器,则无法从客户端执行任何操作。

在你身边,除了你已经做的事情,你可以做任何其他事情。处理COM对象,你就完成了。如果COM应用程序仍然存在,则会有一些错误处理程序导致应用程序不关闭。也许它显示错误信息。

但我想知道,你看到了一个SVCHOST进程。这是一项服务吗?如果是这样,SCM应该管理失败。 COM通常在SVCHOST.EXE中托管外部服务器。

因此,您可能没有提供有关所使用的外部流程类型的足够信息。

BTW:调用GC.Collect永远不会明智......;)