vb.net - PInvoke FormatMessage Message ByRef lpBuffer As [String] 没有

标签 vb.net pinvoke wininet kernel32

声明此函数:

    <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

场景
我目前正在调用 wininet.dll 对服务器执行 FTP 事务。如果遇到错误,我会从 Err.LastDllError 获取错误代码。我定义了一个函数,它获取 dll 错误并根据错误代码返回一条消息,但它没有按预期工作。这是我用来抛出 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://learn.microsoft.com/en-us/windows/desktop/wininet/appendix-c-handling-errors我期望根据此特定 dll 的错误代码获得某种字符串消息,例如,如果我收到错误代码 12110 (ERROR_FTP_TRANSFER_IN_PROGRESS。引用: https://support.microsoft.com/en-au/help/193625/info-wininet-error-codes-12001-through-12156 ),我希望收到一条消息(在变量中) sMessageBuffer)类似于以下内容(如果不相同)“无法在 FTP session 句柄上进行请求的操作,因为操作已在进行中。”。然而,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

关于vb.net - PInvoke FormatMessage Message ByRef lpBuffer As [String] 没有,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56862115/

相关文章:

.net - TableAdapter 向导未生成 INSERT 方法 - UPDATE 和 DELETE 正常

vb.net - 舍入数字 : if number is closer to 100, 向下舍入到最接近的 250,否则向上舍入到最接近的 250

vb.net - Visual Basic-在线程应用程序中使用嵌套互斥对象-风险和建议

c# - PInvoke 能否将 [out] 参数转换为返回值?

c# - 调用Delphi dll函数时PInvokeStackImbalance

SSL 证书上下文 - 如何使用 NPAPI 获取它

c# - System.Text.Encoding.UTF8.GetBytes 额外字节

c# - 使用 PInvoke 的回调非常慢

asp.net - 使用httpSendRequest c++上传文件

c++ - 无法使用 wininet 将 ZIP 文件发布到服务器