VB.Net等效于此方法获取MIME类型的C#

时间:2014-04-08 20:54:13

标签: vb.net mime-types dllimport

此方法是从C#中的Byte数组中获取MIME类型。我已将大部分代码转换为VB.Net,但我正在努力解决部分问题

C#代码

    [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(有错误)

<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

以下是我遇到的错误

Function FindMimeFromData(pBC As IntPtr DllImport不能应用于实例方法

未声明

If data == null Then null。不再支持空常量。请改用System.BDNull。当我将其更改为System.BDNull告诉我它不能用作表达式

未宣布

out mimeTypePointer, 0) out

<OutAttribute> ppwzMimeOut As IntPtr, _我应该使用<OutAttribute>ByRef

由于

3 个答案:

答案 0 :(得分:1)

  

函数FindMimeFromData(pBC As IntPtr

将其设为Shared。共享=静态。

  

如果data == null则不声明null。不再支持空常量。请改用System.BDNull。当我将其更改为System.BDNull告诉我它不能用作表达式

==运算符仅在c#中可用。请改用=运算符。 vb.net中的=运算符等于c#中的==运算符。

  

out mimeTypePointer,0)out未声明    ppwzMimeOut作为IntPtr,_这里我应该使用或ByRef

将其声明为ByRef ppwzMimeOut As IntPtr并删除out关键字。

答案 1 :(得分:1)

您需要设置&#39; Option Infer On&#39; (&#39; mime&#39;使用推断的打字)以下内容应该可以正常工作:

<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

答案 2 :(得分:0)

我不知道你可能会遇到什么错误......但是我同时和不断地使用两种语言,从我所看到的,上面C#代码的确切翻译是:< / p>

<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

现在。如果您遇到LPArray为Null的问题,可能需要考虑,您可能想要将其设置为IntPtr(或ByRef IntPtr,具体取决于具体情况,在此处),然后使用a将IntPtr转换为数组Marshal.Copy或其他一些......

...但是,我可以告诉你的一点是,如果函数成功,Marshal.FreeCoTaskMem可能永远不会被调用...我不确定Return上的Finally块行为,但我会从来没有这样写过,在VB中。因为,在VB中,您希望以这种方式编写代码:

<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

此代码使用Option Strict On验证,因此......可能不需要选项Infer On。