问题
So i have been using urlmon.dll
's help with getting the MIME type of files' data as suggested in This answer, and its been working fine in windows 7.
However, on windows 10 the same code generates System.AccessViolationException
when trying to create a string from the mime pointer.
this is the problematic code:
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);
The code works fine on windows 7 and on the same files, however when running this on windows 10 i suddenly get Access Violation.
Did anyone else encounter this error ?
回答1:
uint mimeType;
FindMimeFromData(0, null, data, 256, null, 0, out mimeType, 0);
var mimePointer = new IntPtr(mimeType);
This is surely wrong at 64 bits... A IntPtr
is 64 bits (it is a memory address)... How could a uint
(a 32 bits) contain it?
And if we take a look at the pinvoke site the signature should be:
[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);
very important while the documentation of the method is very poor on msdn, calling FindMimeFromData
will cause a memory leak: you have to free the ppwzMimeOut
you receive... The problem is that it isn't clear how: here it is suggested to use CoTaskMemFree
, that is Marshal.FreeCoTaskMem
. I'll say that it is right, tested with:
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);
}
If I remove the Marshal.FreeCoTaskMem
and take a look with the TaskManager, the memory used by the process will go up quite quickly... If I restore the Marshal.FreeCoTaskMem
, the memory will remain stable.
来源:https://stackoverflow.com/questions/51037460/ptrtostringuni-doesnt-work-in-windows-10