如何恢复尚未正确释放的COM对象?

时间:2012-08-21 00:30:04

标签: c# .net windows com-interop taskmanager

当有人使用任务管理器结束已实例化COM对象的.NET进程时,AFAIK无法在Marshal.FinalReleaseComObjecttry {} finally {}或事件处理中调用using {}块。

下次启动应用程序时,COM对象处于不可用状态,我需要重启机器才能使其再次运行。

我使用Marshal.BindToMoniker来实例化对象。

我做错了什么,有什么我错过的吗?


我尝试了赛义德的建议,但它没有用

private const int WM_CLOSE = 0x0010;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_CLOSE)
    {
        logger.Info("WM_CLOSE");
        Marshal.FinalReleaseComObject(comObject);
    }

    base.WndProc(ref m);
}

2 个答案:

答案 0 :(得分:1)

您可能不需要。当垃圾收集器到处释放内存时,它会检查对象是否有一个尚未被调用的Dispose()方法。如果尚未调用Dispose()方法,它将调用它。

我在一个控制台应用程序中对此进行测试,并在我的Dispose功能中发出3个扬声器。退出应用程序后,无需在对象上调用Dispose,大约需要30秒才能听到3声嘟嘟声。时间是决定性的。

当然,必须正确编码对象。

您是否尝试在关机后立即运行该应用程序?为什么不等几分钟看它是否有效?

编辑:我假设您在Dispose函数中有Marshal.FinalReleaseComObject。

答案 1 :(得分:1)

任务管理器正在使用本地等效的Process.Kill(或者可能更强大的东西)。请注意文档中的这个叙述:

  

Kill 强制终止流程,而CloseMainWindow仅请求终止。

     

...

     

调用CloseMainWindow发送请求以关闭主窗口,该窗口在格式良好的应用程序中...

  

如果您拨打 Kill ,则流程编辑的数据或分配给流程的资源可能会丢失。 Kill 导致流程异常终止,只应在必要时使用。

简而言之,在程序代码中没有什么可以真正做到的,以防止这种情况 - 插头已被拉动。不会发送任何窗口消息。