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的实现