如何使 WinHttpCrackUrl 在 64 位下工作

bov*_*der 5 windows excel 64-bit vba winhttp

我有 Visual Basic for Applications 代码,它WinHttp可以在 32 位 Windows XP 上运行的 32 位 Office 2010 上完美地使用和运行。相同的代码无法在 64 位 Windows 8 上的 64 位 Office 2013 上正常运行,即使它编译正常。

问题是WinHttpCrackUrl()在 Windows 8 上返回错误 87“参数不正确”。

我已经双重检查和三重检查所有指针都在代码中适当地声明为 LongPtr 。我究竟做错了什么?

这是在 32 位 Excel/Windows 上运行良好,但无法在 64 位 Excel/Windows 上运行的代码:

Private Type URL_COMPONENTS
    dwStructSize      As Long
    lpszScheme        As LongPtr
    dwSchemeLength    As Long
    nScheme           As Long
    lpszHostName      As LongPtr
    dwHostNameLength  As Long
    nPort             As Long
    lpszUserName      As LongPtr
    dwUserNameLength  As Long
    lpszPassword      As LongPtr
    dwPasswordLength  As Long
    lpszUrlPath       As LongPtr
    dwUrlPathLength   As Long
    lpszExtraInfo     As LongPtr
    dwExtraInfoLength As Long
End Type

Private Declare PtrSafe Function WinHttpCrackUrl Lib "WinHTTP" ( _
    ByVal pwszUrl As LongPtr, _
    ByVal dwUrlLength As Long, _
    ByVal dwFlags As Long, _
    ByRef lpUrlComponents As URL_COMPONENTS) As Long

Sub Test()
    Dim result as Long
    Dim URLComp As URL_COMPONENTS
    Dim mURL as String
    mURL = "http://www.stackoverflow.com" & vbNullChar

    With URLComp
        .dwStructSize = Len(URLComp)
        .dwHostNameLength = -1
        .dwSchemeLength = -1
        .dwUrlPathLength = -1
    End With

    result = WinHttpCrackUrl(StrPtr(mURL), 0, 0, URLComp)

    ' Prints 1 on 32-bit Excel/Windows (indicating success)
    ' Prints 0 on 64-bit Excel/Windows (indicating failure)
    Debug.Print result

    ' Prints 87 on 64-bit Excel/Windows ("The parameter is incorrect.")
    Debug.Print err.LastDllError
End Sub
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 5

所述struct在C ++代码对齐,但VBA结构被打包。在 32 位中,对于您的结构,这无关紧要,因为所有成员都对齐 4。但在 64 位中,指针需要 8 字节对齐,并且结构有一些额外的填充。像这样放进去:

Private Type URL_COMPONENTS
    dwStructSize      As Long
    padding1          As Long
    lpszScheme        As LongPtr
    dwSchemeLength    As Long
    nScheme           As Long
    lpszHostName      As LongPtr
    dwHostNameLength  As Long
    nPort             As Long
    lpszUserName      As LongPtr
    dwUserNameLength  As Long
    padding2          As Long
    lpszPassword      As LongPtr
    dwPasswordLength  As Long
    padding3          As Long
    lpszUrlPath       As LongPtr
    dwUrlPathLength   As Long
    padding4          As Long
    lpszExtraInfo     As LongPtr
    dwExtraInfoLength As Long
    padding5          As Long
End Type
Run Code Online (Sandbox Code Playgroud)

我想你会想要一些条件编译来切换更好的 32 位和 64 位版本,但我必须承认不知道如何用 VBA 做到这一点。

  • 条件编译开关是 [`#If Win64 Then` ... `#End If`](https://docs.microsoft.com/en-us/office/vba/language/concepts/getting-started/compiler-常量),应放置在每个填充周围。 (2认同)