5

WinHttp32 ビット Windows XP で実行されている 32 ビット Office 2010 を使用して問題なく動作する Visual Basic for Applications コードがあります。同じコードは、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
4

1 に答える 1

5

The struct is aligned in the C++ code, but VBA structs are packed. In 32 bit, for your struct, it does not matter since all members have alignment 4. But in 64 bit the pointers need 8 byte alignment and the struct has some extra padding. Put it in like this:

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

I guess you'll want some conditional compilation to switch better 32 and 64 bit versions but I must confess to having no idea how to do that with VBA.

于 2013-06-17T21:08:35.427 に答える