PtrToStringUni 在 windows 10 中不起作用

PtrToStringUni doesnt work in windows 10

所以我一直在使用 urlmon.dll's help with getting the MIME type of files' 中建议的数据 This 答案,并且它在 windows 7.

中运行良好

但是,在 windows 10 上,当尝试从 mime 指针创建字符串时,相同的代码会生成 System.AccessViolationException

这是有问题的代码:

uint mimeType;
FindMimeFromData(0, null, data, 256, null, 0, out mimeType, 0);
var mimePointer = new IntPtr(mimeType);
//Exception is thrown on the next line
var mime = Marshal.PtrToStringUni(mimePointer);

代码在 windows 7 和相同的文件上工作正常,但是当 运行 在 windows 10 上运行时,我突然遇到访问冲突。

还有其他人遇到过这个错误吗?

uint mimeType;
FindMimeFromData(0, null, data, 256, null, 0, out mimeType, 0);
var mimePointer = new IntPtr(mimeType);

这在64位肯定是错误的... IntPtr是64位(它是内存地址)... uint(32位)怎么可能包含它?

如果我们看一下 pinvoke site 签名应该是:

[DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)]
static extern int FindMimeFromData(IntPtr pBC,
    [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I1, SizeParamIndex=3)] 
    byte[] pBuffer,
    int cbSize,
    [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed,
    int dwMimeFlags,
    out IntPtr ppwzMimeOut,
    int dwReserved);

非常重要虽然方法的文档在msdn上很差,调用FindMimeFromData会导致内存泄漏:你必须释放ppwzMimeOut 你收到... 问题是不清楚如何:here建议使用CoTaskMemFree,即Marshal.FreeCoTaskMem。我会说这是正确的,经过测试:

byte[] bytes = File.ReadAllBytes("someimage.jpg");

while (true)
{
    IntPtr ptr1;
    int success1 = FindMimeFromData(IntPtr.Zero, null, bytes, bytes.Length, null, 0, out ptr1, 0);
    Marshal.FreeCoTaskMem(ptr1);
}

如果我删除 Marshal.FreeCoTaskMem 并使用 TaskManager 查看,进程使用的内存将上升得非常快......如果我恢复 Marshal.FreeCoTaskMem,内存将保留稳定。