简体   繁体   English

SafeFileHandle.Close抛出异常,但句柄有效且有效

[英]SafeFileHandle.Close throws an exception but the handle is valid and works

I'm having a problem with custom cursors in a WPF application. 我在WPF应用程序中遇到自定义游标的问题。 I use the following code to create the Cursor objects: 我使用以下代码来创建Cursor对象:

[DllImport("user32.dll")]
private static extern IntPtr CreateIconIndirect(ref IconInfo icon);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);

private static Cursor CreateCursor(string cursorName, System.Drawing.Bitmap bmp, 
    int xHotspot, int yHotspot, out SafeFileHandle handle)
{
    IconInfo tmp = new IconInfo();
    GetIconInfo(bmp.GetHicon(), ref tmp);
    tmp.xHotspot = xHotspot;
    tmp.yHotspot = yHotspot;
    tmp.fIcon = false;

    IntPtr ptr = CreateIconIndirect(ref tmp);
    handle = new SafeFileHandle(ptr, true);

    if (handle.IsClosed)
    {
        return null;
    }

    Cursor cur = CursorInteropHelper.Create(handle);

    return cur;
}

When I close my application and GC starts picking up the trash, it throws an exception: 当我关闭我的应用程序并且GC开始拾取垃圾时,它会引发异常:

System.Runtime.InteropServices.SEHException was unhandled
  Message=External component has thrown an exception.
  Source=mscorlib
  ErrorCode=-2147467259
  StackTrace:
       at Microsoft.Win32.Win32Native.CloseHandle(IntPtr handle)
       at Microsoft.Win32.SafeHandles.SafeFileHandle.ReleaseHandle()
       at System.Runtime.InteropServices.SafeHandle.InternalDispose()
       at System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
       at System.Runtime.InteropServices.SafeHandle.Dispose()
       at System.Windows.Input.Cursor.Finalize()
  InnerException:

I did some further investigation by placing a breakpoint on if (handle.IsClosed) and using the immediate window to call handle.Close() . 我通过在if (handle.IsClosed)上放置断点并使用立即窗口调用handle.Close()进行了一些进一步的调查。 Some of the SafeFileHandle 's close just fine, others throw the same exception — immediately after the handle was created. 一些SafeFileHandle的关闭很好,其他人抛出相同的异常 - 在创建句柄后立即执行。

And just to make things fun, the handles themselves work just fine. 只是为了让事情变得有趣,手柄本身也很好用。 IsInvalid is false, IsClosed is false, and the cursors appear. IsInvalid为false, IsClosed为false,并且显示游标。 It's just that some of the handles can never be closed. 只是有些句柄永远不会被关闭。

As I never intend to close the handles manually, and they will only be closed during finalization of the Cursor objects when the application closes, I might be able to just ignore them. 因为我从不打算手动关闭句柄,并且只有在应用程序关闭时完成Cursor对象的过程中才会关闭它们,我可能只能忽略它们。 I haven't tried a Release build outside VS2010 and I don't know if that will cause a crash dialog to appear. 我没有在VS2010之外尝试过Release版本,我不知道是否会导致出现崩溃对话框。 But even if I can ignore them, it's still messy. 但即使我可以忽略它们,它仍然是凌乱的。

So basically I'm looking for any info on what might be going wrong here, where to look to try and debug this... everything seems to be in native code or GC and I can't debug any of it. 所以基本上我正在寻找关于这里可能出现什么问题的任何信息,在哪里寻找尝试和调试这一切...一切似乎都在本机代码或GC中,我无法调试任何它。

You're wrapping the HICON returned from CreateIconIndirect in a SafeFileHandle which, on releasing, calls CloseHandle on the HICON instead of the needed DestroyIcon . 你将从CreateIconIndirect返回的HICON包装在一个SafeFileHandle中,它在释放时调用HICON上的CloseHandle而不是所需的DestroyIcon Don't wrap HICON in SafeFileHandle but instead in an own, specialized SafeHandle : 不要将HICON包装在SafeFileHandle ,而是包含在自己的专用SafeHandle

class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool DestroyIcon(
        [In] IntPtr hIcon);

    private SafeIconHandle()
        : base(true)
    {
    }

    public SafeIconHandle(IntPtr hIcon)
        : base(true)
    {
        this.SetHandle(hIcon);
    }

    protected override bool ReleaseHandle()
    {
        return DestroyIcon(this.handle);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM