【问题标题】:"Type Mismatch Error" in 64 bit where code developed for 32 bit64 位中的“类型不匹配错误”,其中代码为 32 位开发
【发布时间】:2022-11-04 23:04:38
【问题描述】:

我正在使用 64 位 VBA。该代码是为 32 位开发的。

我在 VarPtr (Public Function Hook() As Boolean) 中遇到类型不匹配错误。

Option Explicit


Private Const PAGE_EXECUTE_READWRITE = &H40

Private Declare PtrSafe Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (Destination As Long, Source As Long, ByVal Length As Long)

Private Declare PtrSafe Function VirtualProtect Lib "kernel32" (lpAddress As Long, _
        ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long

Private Declare PtrSafe Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As Long

Private Declare PtrSafe Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, _
        ByVal lpProcName As String) As Long

Private Declare PtrSafe Function DialogBoxParam Lib "User32" Alias "DialogBoxParamA" (ByVal hInstance As Long, _
        ByVal pTemplateName As Long, ByVal hWndParent As Long, _
        ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer

Dim HookBytes(0 To 5) As Byte
Dim OriginBytes(0 To 5) As Byte
Dim pFunc As Long
Dim Flag As Boolean

Private Function GetPtr(ByVal Value As Long) As Long
    GetPtr = Value
End Function

Public Sub RecoverBytes()
    If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6
End Sub

Public Function Hook() As Boolean
    Dim TmpBytes(0 To 5) As Byte
    Dim p As Long
    Dim OriginProtect As Long

    Hook = False

    pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")


    If VirtualProtect(ByVal pFunc, 6, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then

        MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
        If TmpBytes(0) <> &H68 Then

            MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6

            p = GetPtr(AddressOf MyDialogBoxParam)

            HookBytes(0) = &H68
            MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
            HookBytes(5) = &HC3

            MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
            Flag = True
            Hook = True
        End If
    End If
End Function

【问题讨论】:

  • 哪条具体线路有问题?
  • Varptr 将在 64 位 Excel 上返回“LongPtr”,在 32 位 Excel 上返回“Long”。您的 api 声明都使用“Long”,这在 VarPtr 将返回 Long 的 32 位世界中很好,但在 VarPtr 返回 LongPtr 的 64 位 excel 中则不然。您需要更新您的 api 声明以使用 LongPtr 而不是 Long 用于 64 位。
  • 它显示错误是一件好事,可以避免崩溃的 Excel。你有promised 到你有verified 类型的编译器,并将LongPtr 放在它需要的所有地方。你没有;您所有的Declared 函数的论点都非常错误。不过,这不是您最关心的问题。您主要担心的是您正在尝试将 32 位程序集注入 64 位代码。即使您的Declares 正确,它一开始也不会起作用。

标签: excel vba


【解决方案1】:

Varptr 将在 64 位 Excel 上返回“LongPtr”,在 32 位 Excel 上返回“Long”。您的 api 声明都使用“Long”,这在 VarPtr 将返回 Long 的 32 位世界中很好,但在 VarPtr 返回 LongPtr 的 64 位 excel 中则不然。您需要更新您的 api 声明以使用 LongPtr 而不是 Long 用于 64 位。以下 API 调用之一的示例:

#If VBA7 Then
    Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias _
            "RtlMoveMemory" (ByRef Destination As LongPtr, ByRef Source As LongPtr, _
            ByVal Length As LongPtr)
#Else
    Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias _
           "RtlMoveMemory" (Destination As Long, Source As Long, _
            ByVal Length As Long)
#End If

【讨论】:

  • 如果将 Source 和 Destination 声明为 LongPtr,则它们都必须是 ByVal。
猜你喜欢
  • 1970-01-01
  • 2011-04-23
  • 2014-04-27
  • 1970-01-01
  • 2016-07-13
  • 1970-01-01
  • 1970-01-01
  • 2012-02-10
  • 1970-01-01
相关资源
最近更新 更多