C# PtrToStringUni在windows 10中不工作

C# PtrToStringUni在windows 10中不工作,c#,marshalling,C#,Marshalling,因此,我一直在使用urlmon.dll的帮助来获取答案中建议的MIME类型的文件数据,并且在Windows7中运行良好 但是,在windows 10上,当尝试从mime指针创建字符串时,相同的代码会生成System.AccessViolationException 这是有问题的代码: uint mimeType; FindMimeFromData(0, null, data, 256, null, 0, out mimeType, 0); var mimePointer = new IntPtr

因此,我一直在使用
urlmon.dll
的帮助来获取答案中建议的MIME类型的文件数据,并且在Windows7中运行良好

但是,在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);
该代码在Windows7和相同的文件上运行良好,但是在Windows10上运行时,我突然发现访问冲突

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

uint mimeType;
FindMimeFromData(0, null, data, 256, null, 0, out mimeType, 0);
var mimePointer = new IntPtr(mimeType);
这肯定是错误的64位。。。
IntPtr
是64位(它是一个内存地址)。。。一个
uint
(32位)如何包含它

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

[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上的方法文档非常糟糕,但调用
findmemefromdata
将导致内存泄漏:您必须释放收到的
ppwzMimeOut
。。。问题是不清楚如何使用:建议使用
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
,内存将保持稳定

这肯定是错误的64位。。。
IntPtr
是64位(它是一个内存地址)。。。一个
uint
(32位)如何包含它

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

[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上的方法文档非常糟糕,但调用
findmemefromdata
将导致内存泄漏:您必须释放收到的
ppwzMimeOut
。。。问题是不清楚如何使用:建议使用
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,进程使用的内存将快速增加。。。如果我还原
封送.FreeCoTaskMem
,内存将保持稳定。

您是否在管理模式下运行过它?是否也有原因无法从文件扩展名获取
mimetype
。@AndrewE是的,我尝试以管理员身份运行,但它不起作用(这也不是一个解决方案,因为普通用户将在公司计算机上使用它,没有管理员权限)。我确实考虑了扩展名,但很多时候我使用的文件类型与扩展名不匹配(责怪我们的客户),我更喜欢自己检查。Windows 10是3年前发布的,所以这不是一个问题“是否有其他人遇到此”错误。这是目前唯一受支持的Windows版本。缓冲区可能太小,或者指针类型错误,或者您可能在64位计算机上使用了32位版本的DLL。至少,发布完整的异常,包括其调用堆栈。您可以使用
exception.ToString()轻松获取它
@Banana只是尝试一下,您是否尝试将
平台目标更改为x64@AndrewE是的,我有,事实上这是我第一次尝试,但是没有用。你是否在管理模式下运行过它?还有,你不能从文件扩展名中获取
mimetype
的原因吗?@AndrewE是的,我尝试过以管理员和它不起作用(也不是一个解决方案,因为普通用户将在公司计算机上使用它,没有管理员权限)。我确实考虑了扩展名,但很多时候我使用的文件类型与扩展名不匹配(责怪我们的客户)我更愿意自己检查一下。Windows 10是3年前发布的,所以这不是一个“其他人遇到过吗?”“错误。这是目前唯一受支持的Windows版本。缓冲区可能太小,指针类型错误,或者您可能在64位计算机上使用了32位版本的DLL。至少,发布完整的异常,包括其调用堆栈。您可以使用
exception.ToString()轻松获取它。”
@Banana只是尝试一下,您是否尝试将
平台目标更改为x64@AndrewE是的,我试过了,事实上这是我第一次尝试,但没有成功。我们的观点是有道理的,但它在windows 7 64位上运行得很好,在windows 10中有什么不同?@Banana并非所有64位地址都需要64位…有些地址保持在4gb以下,CA也是如此表到32位。但很明显,这是随机的计算机im测试上有4gb的ram,所以没有合格的地址来造成这一点problem@Banana物理内存地址和虚拟内存地址是有区别的。你的4gb内存可以映射到任何地址。@Banana如果我必须做出有根据的猜测,我会说Microsoft在Windows 7和Windows 10之间对
ASLR
(地址空间布局随机化)的更改导致内存分配超过4gb虚拟空间的“边界”。其中一种可能的随机化是关于自底向上的内存分配(请参阅),我要说,这就是导致内存地址从“非常低”变为“非常低”的原因(<4gb)到“随机”(>4gb)你的观点是有道理的,但它在windows 7 64位上运行得很好,在windows 10中有什么不同?@Banana并非所有64位地址都需要64位…有些地址低于4gb,因此可以转换为32位。但很明显,这是随机的,我测试的计算机有4gb的ram,因此没有符合条件的地址导致这种情况problem@Banana有一个di物理内存地址和虚拟内存地址之间的差异。您的4gb内存可以映射到任何地址。@如果我必须做出有根据的猜测,我会说Microsoft在Windows 7和Windows 10之间对
ASLR
(地址空间布局随机化)所做的更改导致内存分配超出4gb的“边界”虚拟spac的实现