I am creating a library of utilities to be used both in desktop environment in a web environment.
It contains several features that I believe are often repeated in my applications, including utility to get the mime type of a file by its content (not the extension).
The files that I'll have to check are the most common (jpg, png, pdf, txt) so I chose to use the external method FindMimeFromData
(link above)
Using .NET, how can you find the mime type of a file based on the file signature not the extension
The method works well, except for the two incorrect mime type of JPG (image/pjpg
) and PNG (image/x-png
), easily solved by doing a check before the return statement.
The library is compiled for the platform AnyCPU, because it must be installed on servers/clients in both 32 and 64 bits.
At the time of testing on desktop environment all working properly for both applications compiled for x86 and x64.
at the time of testing an ASP.NET application (an empty site with an http handler for test) occurs an error of type HRESULT, and the debugger tells me that it can not provide further information.
After a few test configuration, including changing the identity of the pool to Local System (with no result), I have identified the problem:
the pool should allow 32-bit applications (see image above).
Why?
It should not load the dll urlmon.dll
of the 64bit system where we are now?
This is a big problem, because the FindMimeFromData
method can be invoked by everywhere into this library:
the result is that an invocation of this method by another utility method may throw this exception and making it difficult to trace the problem also through debugging.
Any ideas/experience ?
Operating Systems used for testing
Desktop:
Web:
EDIT 2 (question solved)
Solved by Noseratio:
The correct type of parameters ppwzMimeOut
and pBC
must be System.IntPtr
instead of System.UInt32
.
I know that System.UInt32
causes problems into full 64bit web-apps, but i don't know why.
If someone know the reason of these problems, can explain it better in a comment?
Thanks in advance
If you used the pinvoke signature from the answer your linked, it's defined there like this:
[DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
private extern static System.UInt32 FindMimeFromData(
System.UInt32 pBC,
[MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
[MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
System.UInt32 cbSize,
[MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
System.UInt32 dwMimeFlags,
out System.UInt32 ppwzMimeOut,
System.UInt32 dwReserverd
);
I would rather use the defintion from pinvoke.net:
[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);
Note the difference in types for ppwzMimeOut
and pBC
parameter. In the former case, System.UInt32
is not a correct type for a 64-bit pointer under a 64-bit platform. For pBC
, this is probably not an issue (as long as it is NULL), but it matters for ppwzMimeOut
.
Refer to this implementation which appears to be correct.