Question

This method is to get the MIME type from a Byte array in C#. I got most of the code already converted to VB.Net, however I am struggling with parts of it

C# Code

    [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);

    public static string GetMimeFromBytes(byte[] data) {
        int MimeSampleSize = 256;
        string DefaultMimeType = "application/octet-stream";

        if (data == null) {
            throw new ArgumentNullException("data", "Hey, data is null.");
        }

        IntPtr mimeTypePointer = IntPtr.Zero;
        try {

            FindMimeFromData(IntPtr.Zero, null, data, MimeSampleSize, null, 0, out mimeTypePointer, 0);
            var mime = Marshal.PtrToStringUni(mimeTypePointer);
            return mime ?? DefaultMimeType;
        } catch (AccessViolationException e) {
            //Debug.WriteLine(e.ToString());
            return DefaultMimeType;
        } finally {
            if (mimeTypePointer != IntPtr.Zero) {
                Marshal.FreeCoTaskMem(mimeTypePointer);
            }
        }
    }

Vb.Net (with errors)

<DllImport("urlmon.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True, SetLastError:=False)> _
Function FindMimeFromData(pBC As IntPtr, _
    <MarshalAs(UnmanagedType.LPWStr)> ByVal pwzUrl As String, _
    <MarshalAs(UnmanagedType.LPArray, ArraySubType:=UnmanagedType.I1, SizeParamIndex:=3)> ByVal pBuffer() As Byte, _
    cbSize As Integer, _
    <MarshalAs(UnmanagedType.LPWStr)> ByVal pwzMimeProposed As String, _
    dwMimeFlags As Integer, _
    <OutAttribute> ppwzMimeOut As IntPtr, _
    dwReserved As Integer) As Integer
End Function

Public Function GetMimeFromBytes(data() As Byte) As String
    Dim MimeSampleSize As Integer = 256
    Dim DefaultMimeType As String = "application/octet-stream"

    If data == null Then
        Throw New ArgumentNullException("data", "Hey, data is null.")
    End If

    Dim mimeTypePointer As IntPtr = IntPtr.Zero
    Try
        FindMimeFromData(IntPtr.Zero, null, data, MimeSampleSize, null, 0, out mimeTypePointer, 0)
        Dim mime = Marshal.PtrToStringUni(mimeTypePointer)
        return mime ?? DefaultMimeType
    Catch e As AccessViolationException
        Return DefaultMimeType
    Finally
        If Not mimeTypePointer = IntPtr.Zero Then
            Marshal.FreeCoTaskMem(mimeTypePointer)
        End If
    End Try
End Function

The following are the errors i have

Function FindMimeFromData(pBC As IntPtr DllImport cannot be applied to instance method

If data == null Then null is not declared. Null constant is no longer supported. use System.BDNull instead. When I change it to System.BDNull is telling me that it can't be used as an expression

out mimeTypePointer, 0) out is not declared

<OutAttribute> ppwzMimeOut As IntPtr, _ here should I be using <OutAttribute> or ByRef

Thanks

Was it helpful?

Solution 3

I don't know what errors you might be having are... but I work in both languages simultaneously and constantly, and from what I can see, the exact translation for the C# code, above, is:

<DllImport("urlmon.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True, SetLastError:=False)> _
Public Shared Function FindMimeFromData(pBC As IntPtr, _
    <MarshalAs(UnmanagedType.LPWStr)>
    pwzUrl As String, _
    <MarshalAs(UnmanagedType.LPArray, ArraySubType:=UnmanagedType.U1, SizeParamIndex:=3)>
    pBuffer() As Byte, _
    cbSize As Integer, _
    <MarshalAs(UnmanagedType.LPWStr)>
    pwzMimeProposed As String, _
    dwMimeFlags As Integer, _
    ByRef ppwzMimeOut As IntPtr, _
    dwReserved As Integer) As Integer
End Function

Public Shared Function GetMimeFromBytes(data As Byte()) As String

    Dim MimeSampleSize As Integer = 256
    Dim DefaultMimeType As String = "application/octet-stream"

    If (data Is Nothing) Then
        Throw New ArgumentNullException("data", "Hey, data is null.")
    End If

    Dim mimeTypePointer As IntPtr = IntPtr.Zero

    Try

        FindMimeFromData(IntPtr.Zero, Nothing, data, MimeSampleSize, Nothing, 0, mimeTypePointer, 0)
        Dim mime As String = Marshal.PtrToStringUni(mimeTypePointer)
        Return If((mime IsNot Nothing) AndAlso (mime <> ""), mime, DefaultMimeType)
    Catch ex As AccessViolationException
        'Debug.WriteLine(e.ToString())
        Return DefaultMimeType
    Finally
        If (mimeTypePointer <> IntPtr.Zero) Then
            Marshal.FreeCoTaskMem(mimeTypePointer)
        End If
    End Try
End Function

Now. If you run into problems with the LPArray being Null, that might be something to consider, you might want to make that an IntPtr (or ByRef IntPtr, depending on what the case is, here), and then convert the IntPtr to array using a Marshal.Copy or some such...

... however, one thing I can tell you, is that if the function succeeds, Marshal.FreeCoTaskMem might never be called... I'm not sure about the Finally block behavior on Return, but I would never have written it that way, in VB. Because, in VB, you would want to write the code this way:

<DllImport("urlmon.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True, SetLastError:=False)> _
Public Shared Function FindMimeFromData(pBC As IntPtr, _
    <MarshalAs(UnmanagedType.LPWStr)>
    pwzUrl As String, _
    <MarshalAs(UnmanagedType.LPArray, ArraySubType:=UnmanagedType.U1, SizeParamIndex:=3)>
    pBuffer() As Byte, _
    cbSize As Integer, _
    <MarshalAs(UnmanagedType.LPWStr)>
    pwzMimeProposed As String, _
    dwMimeFlags As Integer, _
    ByRef ppwzMimeOut As IntPtr, _
    dwReserved As Integer) As Integer
End Function

Public Shared Function GetMimeFromBytes(data As Byte()) As String

    Dim MimeSampleSize As Integer = 256
    Dim DefaultMimeType As String = "application/octet-stream"

    If (data Is Nothing) Then
        Throw New ArgumentNullException("data", "Hey, data is null.")
    End If

    Dim mimeTypePointer As IntPtr = IntPtr.Zero

    Try

        FindMimeFromData(IntPtr.Zero, Nothing, data, MimeSampleSize, Nothing, 0, mimeTypePointer, 0)
        Dim mime As String = Marshal.PtrToStringUni(mimeTypePointer)
        GetMimeFromBytes = CType(If((mime IsNot Nothing) AndAlso (mime <> ""), mime, DefaultMimeType), String)
    Catch ex As AccessViolationException
        'Debug.WriteLine(e.ToString())
        GetMimeFromBytes = DefaultMimeType
    Finally
        If (mimeTypePointer <> IntPtr.Zero) Then
            Marshal.FreeCoTaskMem(mimeTypePointer)
        End If
    End Try
End Function

And this code validates with Option Strict On, so ... Option Infer On is probably not necessary.

OTHER TIPS

Function FindMimeFromData(pBC As IntPtr

Make it Shared. Shared = static.

If data == null Then null is not declared. Null constant is no longer supported. use System.BDNull instead. When I change it to System.BDNull is telling me that it can't be used as an expression

== operator is only available in c#. Use the = operator instead. The = operator in vb.net equals the == operator in c#.

out mimeTypePointer, 0) out is not declared ppwzMimeOut As IntPtr, _ here should I be using or ByRef

Declare it as ByRef ppwzMimeOut As IntPtr and remove the out keyword.

You need to set 'Option Infer On' ('mime' uses inferred typing) and the following should work fine:

<DllImport("urlmon.dll", CharSet := CharSet.Unicode, ExactSpelling := True, SetLastError := False)> _
Shared Function FindMimeFromData(ByVal pBC As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal pwzUrl As String, <MarshalAs(UnmanagedType.LPArray, ArraySubType := UnmanagedType.I1, SizeParamIndex := 3)> ByVal pBuffer() As Byte, ByVal cbSize As Integer, <MarshalAs(UnmanagedType.LPWStr)> ByVal pwzMimeProposed As String, ByVal dwMimeFlags As Integer, ByRef ppwzMimeOut As IntPtr, ByVal dwReserved As Integer) As Integer
End Function

Public Shared Function GetMimeFromBytes(ByVal data() As Byte) As String
    Dim MimeSampleSize As Integer = 256
    Dim DefaultMimeType As String = "application/octet-stream"

    If data Is Nothing Then
        Throw New ArgumentNullException("data", "Hey, data is null.")
    End If

    Dim mimeTypePointer As IntPtr = IntPtr.Zero
    Try

        FindMimeFromData(IntPtr.Zero, Nothing, data, MimeSampleSize, Nothing, 0, mimeTypePointer, 0)
        Dim mime = Marshal.PtrToStringUni(mimeTypePointer)
        Return If(mime, DefaultMimeType)
    Catch e As AccessViolationException
        'Debug.WriteLine(e.ToString());
        Return DefaultMimeType
    Finally
        If mimeTypePointer <> IntPtr.Zero Then
            Marshal.FreeCoTaskMem(mimeTypePointer)
        End If
    End Try
End Function
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top