我正在尝试使用*
通知是否有某个应用退出。它至少在我想要的东西上起作用,但在我关闭主窗体之后,它会抛出异常:
SEHException:外部组件抛出异常
堆栈追踪:
/
以下是代码:
ThreadPool.UnsafeRegisterWaitForSingleObject
我甚至不需要等待调用回调,只需运行代码,然后关闭主窗体就会抛出异常。
有趣的是,如果使用at Microsoft.Win32.SafeNativeMethods.CloseHandle(IntPtr handle)
at Microsoft.Win32.SafeHandles.SafeProcessHandle.ReleaseHandle()
at System.Runtime.InteropServices.SafeHandle.InternalFinalize()
at System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
at System.Runtime.InteropServices.SafeHandle.Finalize()
本机函数来获取进程句柄而不是像这样使用Load += (s, e) => {
var p = System.Diagnostics.Process.GetProcessById(8524).Handle;
var wh = new ManualResetEvent(false);
wh.SafeWaitHandle = new SafeWaitHandle(p, true);
var cl = ThreadPool.UnsafeRegisterWaitForSingleObject(
wh, new WaitOrTimerCallback((o, b) =>
{
MessageBox.Show("Exited!");
}), null, Timeout.Infinite, true);
};
类:
OpenProcess
然后它没有任何异常,但是我不太确定在这种情况下是否更好地坚持托管包装器。此外,我想了解为什么在使用Process
类时抛出此异常。看起来//ProcessAccessFlags.Synchronize = 0x00100000
var p = OpenProcess(ProcessAccessFlags.Synchronize, false, 8524);
标志(记录的必需标志)是使用Process
和包装器Synchronize
之间的区别。如果是这样的话OpenProcess
在这种情况下无法替换Process
,或者我在这里错过了什么?
其他信息:面向.NET 4.0的Visual Studio 2010
谢谢。
答案 0 :(得分:2)
wh.SafeWaitHandle = new SafeWaitHandle(p, true);
这就是问题开始的地方。您现在有两个 SafeHandles包装相同的句柄。一个在Process对象中,另一个在ManualResetEvent对象中。不可避免地,其中一个总会失败。您的代码将始终崩溃,在这种情况下,它发生的原因是MRE的终结器首先运行。相反,你有50%的赔率,当Process Finalizer首先运行时就会发生。
第一种方法是不要这样做。您已经有了一个很好的活动,可以使用https://www.iso.org/obp/ui/#search。您甚至可以在正确的线程上运行它,以便MessageBox不会在另一个窗口后面消失,使用它的SynchronizingObject属性。
另一种方法是通过对DuplicateHandle进行pinvoking来复制句柄。的Bleh。或者只是解释为什么你首先滥用这个ManualResetEvent。 Process类是在.NET 1.0中设计的,如果其Handle属性为SafeHandle,则不会遇到此问题。但是它的IntPtr,他们再也无法解决这个问题了。通过从SafeHandle派生自己的类来修复它,不要在ReleaseHandle()重载中做任何事情。