PInvoke FormatMessage 消息 ByRef lpBuffer As [String] Is Nothing
PInvoke FormatMessage Message ByRef lpBuffer As [String] Is Nothing
正在声明此函数:
<DllImport("kernel32.dll", EntryPoint:="FormatMessageW", SetLastError:=True, CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.StdCall)>
Public Shared Function FormatMessage(ByVal dwFlags As Integer,
ByRef lpSource As IntPtr,
ByVal dwMessageId As Integer,
ByVal dwLanguageId As Integer,
ByRef lpBuffer As [String],
ByVal nSize As Integer,
ByRef Arguments As IntPtr) As Integer
End Function
基于此处的定义:https://pinvoke.net/default.aspx/kernel32/FormatMessage.html
场景
我目前正在 PInvoking wininet.dll 对服务器执行 FTP 事务。如果遇到错误,我会从 Err.LastDllError 返回错误代码。我定义了一个函数,它获取 dll 错误和 returns 基于错误代码的消息,但是它没有按预期工作。这是我用来抛出 dll 错误的函数:
Private Sub ThrowLastDllError()
Dim iLastErrorID As Integer = Err.LastDllError
Dim iMessageBuffer As IntPtr = Nothing
Dim iModuleHandle As IntPtr = GetModuleHandle("wininet.dll")
Dim sMessageBuffer As String = Nothing
If iLastErrorID > 12000 And iLastErrorID < 12157 Then
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE Or
FORMAT_MESSAGE_IGNORE_INSERTS Or
FORMAT_MESSAGE_ALLOCATE_BUFFER,
iModuleHandle,
iLastErrorID,
0,
sMessageBuffer,
256,
Nothing)
Debugger.Break()
'TODO: Throw exception with error code message here
End If
End Sub
基于此处描述的技术:https://docs.microsoft.com/en-us/windows/desktop/wininet/appendix-c-handling-errors I am expecting to get some kind of string message based on the error code for this particular dll, for example if I get an error code of 12110 (ERROR_FTP_TRANSFER_IN_PROGRESS. Reference: https://support.microsoft.com/en-au/help/193625/info-wininet-error-codes-12001-through-12156) 如果不相同 "The requested operation cannot be made on the FTP session handle because an operation is already in progress.",我希望得到类似于以下内容的消息(在变量 sMessageBuffer 中)。然而,sMessageBuffer 从未被赋值并且保持为空。我只能假设我以某种方式滥用了这种技术,我尝试了在线论坛和本网站本身描述的各种方法,但我没有成功。
这里有一些有效的示例代码:
Sub Main()
Dim h As IntPtr = LoadLibrary("wininet.dll") ' or GetModuleHandle ...
Dim sb = New StringBuilder(1024)
FormatMessage(Format_Message.FORMAT_MESSAGE_FROM_HMODULE Or Format_Message.FORMAT_MESSAGE_IGNORE_INSERTS,
h,
12002,
0,
sb,
sb.Capacity,
Nothing)
Console.WriteLine(sb) ' prints "The operation timed out"
' FreeLibrary, etc.
End Sub
Enum Format_Message
FORMAT_MESSAGE_IGNORE_INSERTS = &H200
FORMAT_MESSAGE_FROM_SYSTEM = &H1000
FORMAT_MESSAGE_FROM_HMODULE = &H800
End Enum
<DllImport("Kernel32", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Function FormatMessage(ByVal dwFlags As Format_Message, ByVal lpSource As IntPtr, ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, lpBuffer As StringBuilder, ByVal nSize As Integer, ByVal Arguments As IntPtr) As Integer
End Function
<DllImport("kernel32", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Function LoadLibrary(ByVal lpFileName As String) As IntPtr
End Function
正在声明此函数:
<DllImport("kernel32.dll", EntryPoint:="FormatMessageW", SetLastError:=True, CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.StdCall)>
Public Shared Function FormatMessage(ByVal dwFlags As Integer,
ByRef lpSource As IntPtr,
ByVal dwMessageId As Integer,
ByVal dwLanguageId As Integer,
ByRef lpBuffer As [String],
ByVal nSize As Integer,
ByRef Arguments As IntPtr) As Integer
End Function
基于此处的定义:https://pinvoke.net/default.aspx/kernel32/FormatMessage.html
场景
我目前正在 PInvoking wininet.dll 对服务器执行 FTP 事务。如果遇到错误,我会从 Err.LastDllError 返回错误代码。我定义了一个函数,它获取 dll 错误和 returns 基于错误代码的消息,但是它没有按预期工作。这是我用来抛出 dll 错误的函数:
Private Sub ThrowLastDllError()
Dim iLastErrorID As Integer = Err.LastDllError
Dim iMessageBuffer As IntPtr = Nothing
Dim iModuleHandle As IntPtr = GetModuleHandle("wininet.dll")
Dim sMessageBuffer As String = Nothing
If iLastErrorID > 12000 And iLastErrorID < 12157 Then
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE Or
FORMAT_MESSAGE_IGNORE_INSERTS Or
FORMAT_MESSAGE_ALLOCATE_BUFFER,
iModuleHandle,
iLastErrorID,
0,
sMessageBuffer,
256,
Nothing)
Debugger.Break()
'TODO: Throw exception with error code message here
End If
End Sub
基于此处描述的技术:https://docs.microsoft.com/en-us/windows/desktop/wininet/appendix-c-handling-errors I am expecting to get some kind of string message based on the error code for this particular dll, for example if I get an error code of 12110 (ERROR_FTP_TRANSFER_IN_PROGRESS. Reference: https://support.microsoft.com/en-au/help/193625/info-wininet-error-codes-12001-through-12156) 如果不相同 "The requested operation cannot be made on the FTP session handle because an operation is already in progress.",我希望得到类似于以下内容的消息(在变量 sMessageBuffer 中)。然而,sMessageBuffer 从未被赋值并且保持为空。我只能假设我以某种方式滥用了这种技术,我尝试了在线论坛和本网站本身描述的各种方法,但我没有成功。
这里有一些有效的示例代码:
Sub Main()
Dim h As IntPtr = LoadLibrary("wininet.dll") ' or GetModuleHandle ...
Dim sb = New StringBuilder(1024)
FormatMessage(Format_Message.FORMAT_MESSAGE_FROM_HMODULE Or Format_Message.FORMAT_MESSAGE_IGNORE_INSERTS,
h,
12002,
0,
sb,
sb.Capacity,
Nothing)
Console.WriteLine(sb) ' prints "The operation timed out"
' FreeLibrary, etc.
End Sub
Enum Format_Message
FORMAT_MESSAGE_IGNORE_INSERTS = &H200
FORMAT_MESSAGE_FROM_SYSTEM = &H1000
FORMAT_MESSAGE_FROM_HMODULE = &H800
End Enum
<DllImport("Kernel32", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Function FormatMessage(ByVal dwFlags As Format_Message, ByVal lpSource As IntPtr, ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, lpBuffer As StringBuilder, ByVal nSize As Integer, ByVal Arguments As IntPtr) As Integer
End Function
<DllImport("kernel32", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Function LoadLibrary(ByVal lpFileName As String) As IntPtr
End Function