此方法是从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
由于
答案 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。