C# 如何正确释放SafeHandleZero或NusoneisInvalid或SafeHandle?

C# 如何正确释放SafeHandleZero或NusoneisInvalid或SafeHandle?,c#,.net,unmanaged,handle,intptr,C#,.net,Unmanaged,Handle,Intptr,我已经阅读了一些文档,下面是我用于IntPtr操作的类,以使它们更安全: internal class MySafeHandleOperator : SafeHandleZeroOrMinusOneIsInvalid { public MySafeHandleOperator(IntPtr handle) : base(true) { SetHandle(handle); } public IntPtr GetPtr() {

我已经阅读了一些文档,下面是我用于IntPtr操作的类,以使它们更安全:

internal class MySafeHandleOperator : SafeHandleZeroOrMinusOneIsInvalid
{
    public MySafeHandleOperator(IntPtr handle) : base(true)
    {
        SetHandle(handle);
    }

    public IntPtr GetPtr()
    {
        return this.handle;
    }

    protected override bool ReleaseHandle()
    {
        this.Dispose(true);
        return true;
    }
}
主要问题在于releasehold方法。我是这样用的,但我不知道这是不是一种正确的用法?是否有另一种正确的方法来释放句柄并清除这个类

我想以类似的方式使用这个类(一个简单的例子):


如果有人看一看,说我做的一切都对,或者这个方法需要重写,我将不胜感激。

不,这看起来不太好。SafeHandle的要点是确保在将句柄传递给本机代码时不会破坏类对象。这可能很糟糕,您的终结器被调用,本机代码继续使用无效句柄。除了可能导致的运行时故障和损坏之外,还有一个非常可怕的句柄回收攻击场景,它由这一点启用

但是,您完全无法控制该窗口句柄的生存期。你不能阻止它被摧毁,你自己也不能做任何事情来摧毁它。好吧,假设您不打算使用终结器终止进程。如果没有对ReleaseHandle()进行有用的重写,您可能会发现一些问题。例如,使用作为实际派生类的示例。NET框架有很多,一个好的反编译器是找到它们的一个很好的方法


长话短说,既然没有必要包装它,那么IntPtr很好

不,这看起来不太好。SafeHandle的要点是确保在将句柄传递给本机代码时不会破坏类对象。这可能很糟糕,您的终结器被调用,本机代码继续使用无效句柄。除了可能导致的运行时故障和损坏之外,还有一个非常可怕的句柄回收攻击场景,它由这一点启用

但是,您完全无法控制该窗口句柄的生存期。你不能阻止它被摧毁,你自己也不能做任何事情来摧毁它。好吧,假设您不打算使用终结器终止进程。如果没有对ReleaseHandle()进行有用的重写,您可能会发现一些问题。例如,使用作为实际派生类的示例。NET框架有很多,一个好的反编译器是找到它们的一个很好的方法


长话短说,由于没有包装它的意义,因此IntPtr很好

您可以继承自
SafeHandleZeroOrMinusOneIsInvalid
以确保句柄正确关闭,例如使用
HWND
不是那种句柄。您不需要从safehandle类继承来传递它。如果是那种句柄,您可以从
releasehold
调用
CloseHandle(this.handle)
。不要尝试从此处处置对象。您可以继承自
SafeHandleZeroOrMinusOneIsInvalid
以确保句柄正确关闭,例如使用
HWND
不是那种句柄。您不需要从safehandle类继承来传递它。如果是那种句柄,您可以从
releasehold
调用
CloseHandle(this.handle)
。不要试图从那里处理对象。因此,据我所知,没有必要使用这个类和简单的窗口资源,返回IntPtr。使用它的唯一合理方法是拥有一些资源,我自己控制着这些资源,而这些资源实际上是代码的灵感来源。“调用非托管函数时,该代码与此代码有什么区别?”询问并回答。他有一个有用的ReleaseHandle()覆盖。所以,据我所知,没有必要使用这个类和简单的窗口资源,返回IntPtr。使用它的唯一合理方法是拥有一些资源,我自己控制着这些资源,而这些资源实际上是代码的灵感来源。“调用非托管函数时,该代码与此代码有什么区别?”询问并回答。他有一个有用的ReleaseHandle()覆盖。你没有。
Process p = Process.Start(processName);
MySafeHandleOperator mh = new MySafeHandleOperator(p.MainWindowHandle);