如何使 WinHttpCrackUrl 在 64 位下工作

问题描述 投票:0回答:2

我有使用

WinHttp
的 Visual Basic for Applications 代码,并且可以与在 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
windows vba excel 64-bit winhttp
2个回答
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

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


0
投票

由于该线程在我的搜索中多次出现,尽管很古老 - OP 的问题是使用 Len 而不是 LenB。

不需要手动添加填充。 VBA 遵循正常的打包规则,并将自动插入该填充。除了需要 .dwStructSize = LenB(URLComp) 而不是 Len(URLComp) 之外,原始代码很好。

不必要时不要疯狂使用填充和条件编译。

PS- 这两篇文章都不正确,因为 nPort 应该是一个整数(typedef WORD INTERNET_PORT;)。将其设为 Long 不会中断调用,因为当它为 Integer 时,会有填充字节,但即使您设置了它,它也会始终将端口设置为零。

© www.soinside.com 2019 - 2024. All rights reserved.