x64 上类方法崩溃的地址

2024-02-16

The AddressOf运算符仅适用于标准 .bas 模块内的方法。我使用以下代码来检索类方法的地址:

Option Explicit

#If VBA7 Then
    Private Declare PtrSafe Function DispCallFunc Lib "oleaut32.dll" (ByVal pvInstance As LongPtr, ByVal oVft As LongPtr, ByVal cc As tagCALLCONV, ByVal vtReturn As Integer, ByVal cActuals As Long, ByRef prgvt As Integer, ByRef prgpvarg As LongPtr, ByRef pvargResult As Variant) As Long
    Private Declare PtrSafe Function DispGetIDsOfNames Lib "oleaut32.dll" (ByVal ptinfo As LongPtr, ByVal rgszNames As LongPtr, ByVal cNames As Long, ByVal rgDispId As LongPtr) As Long
#Else
    Private Declare Function DispCallFunc Lib "oleaut32.dll" (ByVal pvInstance As Long, ByVal oVft As Long, ByVal cc As tagCALLCONV, ByVal vtReturn As Integer, ByVal cActuals As Long, ByRef prgvt As Integer, ByRef prgpvarg As Long, ByRef pvargResult As Variant) As Long
    Private Declare Function DispGetIDsOfNames Lib "oleaut32.dll" (ByVal ptinfo As Long, ByVal rgszNames As Long, ByVal cNames As Long, ByVal rgDispId As Long) As Long
#End If

Private Type INVOKE_ARGS
    args() As Variant
    argsVT() As Integer
    #If VBA7 Then
        argsPtrs() As LongPtr
    #Else
        argsPtrs() As Long
    #End If
    argsCount As Long
End Type

#If Win64 Then
    Private Const PTR_SIZE As Long = 8
#Else
    Private Const PTR_SIZE As Long = 4
#End If

'IDispatch derives from the IUnknown interface
Private Enum IDispatchVtblOffset
    oQueryInterface = PTR_SIZE * 0   'IUnknown
    oAddRef = PTR_SIZE * 1           'IUnknown
    oRelease = PTR_SIZE * 2          'IUnknown
    oGetTypeInfoCount = PTR_SIZE * 3 'IDispatch
    oGetTypeInfo = PTR_SIZE * 4      'IDispatch
    oGetIDsOfNames = PTR_SIZE * 5    'IDispatch
    oInvoke = PTR_SIZE * 6           'IDispatch
End Enum

'ITypeInfo derives from the IUnknown interface
Private Enum ITypeInfoVtblOffset
    oQueryInterface = PTR_SIZE * 0   'IUnknown
    oAddRef = PTR_SIZE * 1           'IUnknown
    oRelease = PTR_SIZE * 2          'IUnknown
    oGetTypeAttr = PTR_SIZE * 3
    oGetTypeComp = PTR_SIZE * 4
    oGetFuncDesc = PTR_SIZE * 5
    oGetVarDesc = PTR_SIZE * 6
    oGetNames = PTR_SIZE * 7
    oGetRefTypeOfImplType = PTR_SIZE * 8
    oGetImplTypeFlags = PTR_SIZE * 9
    oGetIDsOfNames = PTR_SIZE * 10
    oInvoke = PTR_SIZE * 11
    oGetDocumentation = PTR_SIZE * 12
    oGetDllEntry = PTR_SIZE * 13
    oGetRefTypeInfo = PTR_SIZE * 14
    oAddressOfMember = PTR_SIZE * 15
    oCreateInstance = PTR_SIZE * 16
    oGetMops = PTR_SIZE * 17
    oGetContainingTypeLib = PTR_SIZE * 18
    oReleaseTypeAttr = PTR_SIZE * 19
    oReleaseFuncDesc = PTR_SIZE * 20
    oReleaseVarDesc = PTR_SIZE * 21
End Enum

Private Enum tagINVOKEKIND
    INVOKE_FUNC = &H1
    INVOKE_PROPERTYGET = &H2
    INVOKE_PROPERTYPUT = &H4
    INVOKE_PROPERTYPUTREF = &H8
End Enum

'Calling Conventions
Private Enum tagCALLCONV
    CC_FASTCALL = 0
    CC_CDECL = 1
    CC_MSCPASCAL = 2
    CC_PASCAL = CC_MSCPASCAL
    CC_MACPASCAL = 3
    CC_STDCALL = 4
    CC_FPFASTCALL = 5
    CC_SYSCALL = 6
    CC_MPWCDECL = 7
    CC_MPWPASCAL = 8
    CC_MAX = 9
End Enum

Const S_OK As Long = 0

#If VBA7 Then
Public Function GetAddressOfClassMethod(ByVal classInstance As Object, ByVal methodName As String) As LongPtr
#Else
Public Function GetAddressOfClassMethod(ByVal classInstance As Object, ByVal methodName As String) As Long
#End If
    #If VBA7 Then
        Dim iDispatchPtr As LongPtr
        Dim iTypeInfoPtr As LongPtr
    #Else
        Dim iDispatchPtr As Long
        Dim iTypeInfoPtr As Long
    #End If
    Dim localeID As Long 'Not really needed. Could pass 0 instead
    '
    'Get a pointer to the IDispatch interface
    iDispatchPtr = ObjPtr(GetDefaultInterface(classInstance))
    '
    'Get a pointer to the ITypeInfo interface
    localeID = Application.LanguageSettings.LanguageID(msoLanguageIDUI)
    IDispatch_GetTypeInfo iDispatchPtr, 0, localeID, iTypeInfoPtr
    '
    Dim arrNames(0 To 0) As String: arrNames(0) = methodName
    Dim arrIDs(0 To 0) As Long
    '
    'Get ID of required member
    DispGetIDsOfNames iTypeInfoPtr, VarPtr(arrNames(0)), 1, VarPtr(arrIDs(0))
    '
    'Get address of member
    ITypeInfo_AddressOfMember iTypeInfoPtr, arrIDs(0), INVOKE_FUNC, GetAddressOfClassMethod
End Function

'*******************************************************************************
'Returns the default interface for an object
'All VB intefaces are dual interfaces meaning all interfaces are derived from
'   IDispatch which in turn is derived from IUnknown. In VB the Object datatype
'   stands for the IDispatch interface.
'Casting from a custom interface (derived only from IUnknown) to IDispatch
'   forces a call to QueryInterface for the IDispatch interface (which knows
'   about the default interface)
'*******************************************************************************
Private Function GetDefaultInterface(obj As IUnknown) As Object
    Set GetDefaultInterface = obj
End Function

'*******************************************************************************
'IDispatch::GetTypeInfo
'*******************************************************************************
#If VBA7 Then
Private Function IDispatch_GetTypeInfo(ByVal iDispatchPtr As LongPtr, ByVal iTInfo As Long, ByVal lcid As Long, ByRef ppTInfo As LongPtr) As Long
#Else
Private Function IDispatch_GetTypeInfo(ByVal iDispatchPtr As Long, ByVal iTInfo As Long, ByVal lcid As Long, ByRef ppTInfo As Long) As Long
#End If
    Dim hResult As Long
    '
    With CreateInvokeArgs(iTInfo, lcid, VarPtr(ppTInfo))
        hResult = DispCallFunc(iDispatchPtr, IDispatchVtblOffset.oGetTypeInfo, CC_STDCALL, vbLong, .argsCount, .argsVT(0), .argsPtrs(0), IDispatch_GetTypeInfo)
    End With
    If hResult <> S_OK Then Err.Raise hResult, "IDispatch_GetTypeInfo"
End Function

'*******************************************************************************
'ITypeInfo::AddressOfMember
'*******************************************************************************
#If VBA7 Then
Private Function ITypeInfo_AddressOfMember(ByVal iTypeInfoPtr As LongPtr, ByVal memid As Long, ByVal invKind As tagINVOKEKIND, ByRef ppv As LongPtr) As Long
#Else
Private Function ITypeInfo_AddressOfMember(ByVal iTypeInfoPtr As Long, ByVal memid As Long, ByVal invKind As tagINVOKEKIND, ByRef ppv As Long) As Long
#End If
    Dim hResult As Long
    '
    With CreateInvokeArgs(memid, invKind, VarPtr(ppv))
        hResult = DispCallFunc(iTypeInfoPtr, ITypeInfoVtblOffset.oAddressOfMember, CC_STDCALL, vbLong, .argsCount, .argsVT(0), .argsPtrs(0), ITypeInfo_AddressOfMember)
    End With
    If hResult <> S_OK Then Err.Raise hResult, "ITypeInfo_AddressOfMember"
End Function

'*******************************************************************************
'Helper function that creates the necessary arrays to use with DispCallFunc
'Passing arguments:
'   - ByVal: pass the arg
'   - ByRef: pass VarPtr(arg)
'*******************************************************************************
Private Function CreateInvokeArgs(ParamArray args() As Variant) As INVOKE_ARGS
    With CreateInvokeArgs
        .argsCount = UBound(args) + 1 'ParamArray is always 0-based (LBound)
        If .argsCount = 0 Then
            ReDim .argsVT(0 To 0)
            ReDim .argsPtrs(0 To 0)
            Exit Function
        End If
        '
        .args = args 'Avoid ByRef issues by making a copy
        ReDim .argsVT(0 To .argsCount - 1)
        ReDim .argsPtrs(0 To .argsCount - 1)
        Dim i As Long
        '
        'For Each is not used because it does copies of the values inside the
        '   array and we need the actual addresses of the values (ByRef)
        For i = 0 To .argsCount - 1
            .argsVT(i) = VarType(.args(i))
            .argsPtrs(i) = VarPtr(.args(i))
        Next i
    End With
End Function

假设一个Class1类有一个Name方法,我可以像这样使用上面的方法:

Debug.Print GetAddressOfClassMethod(New Class1, "Name")

该方法在 x32 上始终运行良好,并且大多数时候在 x64 上运行良好。问题是有时它会导致 x64 上崩溃。崩溃仅发生在ITypeInfo_AddressOfMember称呼。这IDispatch_GetTypeInfo永远不会导致崩溃。

我没有在这里发布代码,但我还调用了 ITypeInfo 接口甚至 ITypeComp 接口的其他方法,但没有崩溃。

难道我做错了什么?对于为什么会发生崩溃有什么想法吗?


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

x64 上类方法崩溃的地址 的相关文章

  • Word VBA“项目不可见”

    有谁知道如何使模板在 Word 2007 中可见 我创建了一个模板 Experiments dotm 使用加载项添加它 但是当我尝试在其中创建模块时 收到错误消息 项目无法查看 关于 项目无法查看 问题的解释可以参见here http ms
  • 按日期计算 Outlook 中的电子邮件

    我有以下代码来计算 Outlook 文件夹中的电子邮件数量 Sub HowManyEmails Dim objOutlook As Object objnSpace As Object objFolder As Object Dim Ema
  • VBA:删除数组项后减少循环迭代?

    在 Excel 的 VBA 中 For i 0 To UBound artMaster For j i To UBound artMaster If i lt gt j And artMaster i VDN artMaster j VDN
  • 双击事件 - 多个范围

    我正在寻找为双击事件在多个范围内进行编码的最佳方法 Private Sub Worksheet BeforeDoubleClick ByVal Target As Range Cancel As Boolean If Not Interse
  • Excel VBA - 循环文件夹中的文件、复制范围、粘贴到此工作簿中

    我有 500 个包含数据的 Excel 文件 我会将所有这些数据合并到一个文件中 实现此目标的任务列表 我想循环遍历文件夹中的所有文件 打开文件 复制此范围 B3 I102 将其粘贴到活动工作簿的第一张工作表中 重复但在下面粘贴新数据 我已
  • 更改索引设置访问 VBA

    我正在尝试自动化 Access 中的流程 我希望自动化的步骤之一是更改表中某些字段的索引设置 我需要这样做来提高后续查询的速度 使用索引查询速度大约快 100 倍 无论如何 假设我的表名为 Cars 如下所示 ID Name Charact
  • VBA rand 如何使用上限和下限生成随机数?

    所以也许这是多余的 也许这就像问为什么大多数人生来就有 5 个手指 最后的简短答案总是 因为事情就是这样 而且它就是这样工作的 但我讨厌这个答案 该死的我想知道怎么做VBA 中的 Rnd 函数有效 Ms Office Excel 的 MSD
  • 使用查询选择器从 VBA 中抓取

    我使用了该网站的代码来提取数据site https bazashifer ru proflist profnastil Option Explicit Public Sub GetInfo Dim sResponse As String i
  • 如何粘贴到Excel B列的最后一行?

    我需要将单元格从 H2 L2 一直向下剪切并将其粘贴到 B 列的最后一行 数据每次都会不同 所以我无法对任何范围进行硬编码 VBA 代码会很好 从 H2 L2 向下剪切并粘贴 插入到 B 列的最后一行 到目前为止我得到了 Range H2
  • Range.End() 困惑

    我有一个关于 VBA 中 Range End 属性的一般性问题 我已经阅读了有关该房产的信息here http msdn microsoft com en us library bb221181 aspx 但我还是很困惑 例子 With w
  • 拆分具有多行文本和单行文本的行

    我试图弄清楚如何拆分数据行 其中行中的 B C D 列包含多行 而其他列不包含多行 我已经弄清楚如何拆分多行单元格 如果我将这些列复制到新工作表中 手动插入行 然后运行下面的宏 仅适用于 A 列 但我在编码时迷失了休息 Here s wha
  • VBA 中的 VSTO:AddIn.Object 有时不返回任何内容 (null)

    Given VSTO 插件 An override object RequestComAddInAutomationService 它返回一个名为的类的实例Facade在我的场景中 Excel 2007 中的 VBA 宏可访问AddIn O
  • 如果 FIND 函数在 vba 中找不到任何内容,那么[重复]

    这个问题在这里已经有答案了 我目前正在自动化执行以下步骤的手动流程 1 提示用户打开一个数据文件并打开文件 2 插入4列 3 使用文件中已有的数据创建格式为 DD MM YYYY TEXT 的唯一字符串 其中文本是变量 4 使用 if 语句
  • Excel 宏与 Javascript

    我希望使用 Javascript 中的宏而不是默认的 VBA 来操作 Excel 电子表格 我可以使用以下 VBA 代码执行 javascript 代码 javascript to execute Dim b As String b fun
  • Excel VBA - 如何逐行读取csv文件而不是整个文件

    这是我需要读取的 csv 文件内容 header header header header header header value value value value value value value value value 我在网上找到
  • 使用 VBA 通过简单命令从非连续范围的并集获取值到数组中(无循环)

    我有以下任务 表面上很简单 使用 VBA 将电子表格上多个列的值复制到二维数组中 为了让生活更有趣 这些柱子并不相邻 但它们的长度都相同 显然 可以通过依次循环每个元素来做到这一点 但这看起来非常不优雅 我希望有一个更紧凑的解决方案 但我很
  • 字典、集合和数组的比较

    我正在尝试找出字典与集合和数组相比的相对优点和功能 我发现了一篇很棒的文章here http www experts exchange com articles 3391 Using the Dictionary Class in VBA
  • 证明 Excel VBA Scripting.Dictionary 不保留项目插入顺序

    我正在尝试决定是否为我的项目使用 Excel VBA 集合或字典 出于多种原因 我倾向于字典 但在使用字典时我会继续阅读它For Each循环检索字典项目或从字典 Items 数组读取项目时 检索顺序可能不是添加项目的顺序 这对于我的应用程
  • MS Access - 粘贴确认事件后

    当用户将记录直接粘贴到数据表子报表中时 是否可以在显示粘贴确认消息后捕获事件 我需要它能够在审计表中创建新记录时进行记录 通过捕获更新前 更新后和插入事件 我可以轻松创建已添加的记录集合 准备将详细信息插入审核日志 但是在所有这些事件触发后
  • 根据单元格值向用户窗体添加复选框

    我对 VBA 很陌生 只有 3 天 但我发现它非常有用且易于使用 但现在我面临一个问题 我需要制作一个具有不同复选框的用户窗体 但我需要根据工作表某一列中使用的信息自动添加它们 我相信我可以使用 For Each Next 但我真的不知道如

随机推荐

  • 如何检查 iOS 中的视图层次结构?

    是否有一个 GUI 工具可以检查 iOS 应用程序的视图层次结构 我正在考虑 Webkit 的网络检查器或类似工具 我正在寻找调试布局问题 例如视图的位置或大小错误 或者子视图未正确包含在其父视图中 目前 我必须添加断言来手动测试这些不同的
  • ICollectionView 取消当前更改

    我正在寻找一种方法来根据单击的项目取消 CurrentChanging 事件 在我的应用程序中 我使用 ICollectionView 来保存视图模型列表 这些视图模型在选项卡控件中呈现为选项卡项 对于特定的视图模型 我需要在激活视图模型之
  • 使用 sqlite 在 django 上实现不区分重音的搜索

    这个问题与我之前的问题有关重音不敏感搜索 django sqlite https stackoverflow com questions 31327019 accent insensitive search django sqlite 正如
  • a* 与 (a*)* 相同吗?

    快速提问 如果a是一个正则表达式 那么这是真的吗a a Is a 有效的表达 如果是 那么任何人都可以解释为什么它与a 我很抱歉在这里提问 但我无法通过谷歌找到任何东西 Yes a a 是一样的 两者都生成相同的语言 即字符串包含的任何数字
  • 逐个用户名查询需要超过 1 个参数

    我必须实现一个 spring 安全部分 它有超过 1 个参数来获取用户 它将通过 ID 和产品名称获取用户 我知道逐个用户名查询只能提供一个参数 我想知道是否可以提供许多逐个用户名查询选项并给他们某种 ID 但我不确定如何验证时将被引用 有
  • JavaScript for in 循环,但相反?

    采用具有 4 个属性的 JavaScript 对象 function Object this prop1 this prop2 this prop3 this prop4 var obj new Object 我使用 for in 循环来检
  • 播放 Json:将 Reads[T] 转换为 Reads[Seq[T]] 而不使用隐式

    我有一个Reads T 我想解析一个 Json 对象 它应该是一个数组T的 有没有简单的方法获得Reads Seq T without定义我的Reads T 隐含的 本质上 我正在寻找一个需要的函数Reads T 并返回Reads Seq
  • 理解 ngRepeat 'track by' 表达式

    我很难理解如何track byAngularJS 中 ng repeat 的表达有效 文档非常稀缺 http docs angularjs org api ng directive ngRepeat http docs angularjs
  • C# - 如何在没有 IDE/Visual Studio 的情况下编写程序? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在 Notepad 和 MonoDevelop 中仅使用 cs 文件而不是解决方案来制作 C 控制台应用程序 我从 CMD 编译代码 我
  • 为什么 DataFrame 中缺少分区键列

    我有一项工作 加载 DataFrame 对象 然后使用 DataFrame 将数据保存为镶木地板格式partitionBy方法 然后我发布创建的路径 以便后续作业可以使用输出 输出中的路径如下所示 ptest SUCCESS ptest i
  • 使用更少的代码进行脑筋急转弯

    这是我尝试编写的 R 问题的一个小脑筋急转弯 假设桌子上有 15 支蜡烛 在三个不同的回合中 您将根据蜡烛是否已经点燃来点燃或熄灭给定的蜡烛 因此 如果给定的蜡烛已经点燃 那么您的行动就是将其熄灭 另一方面 如果蜡烛没有点燃 那么你的行动就
  • CreateDC() 导致 glutInit() 失败?

    我编写了一段代码来创建一个窗口并在其中绘制一个形状 include
  • Jquery - 克隆表行时禁用 select2 下拉列表

    我有一个带有四个 select2 下拉列表的表 当我克隆该行以复制它时 新行的下拉列表被禁用 我无法单击它们 我必须在代码中添加什么才能激活它们 HTML 表格 table width 100 tbody tr th class tab h
  • 如何匹配不包含单词的行[重复]

    这个问题在这里已经有答案了 我想知道如何使用Python风格的正则表达式来匹配不包含特定单词的行 只需使用正则表达式 不涉及Python函数 Example PART ONE OVERVIEW 1 Chapter 1 Introductio
  • Postman中如何自动获取token

    我使用 Postman 桌面应用程序进行 Web API 测试 我有很多控制器 每个控制器都需要一个令牌 首先我得到Bearer token然后将其复制到其他请求中 该令牌有时间限制 我可以自动获取令牌 然后自动将其设置为所有其他请求吗 好
  • 生成的 JsonResult 中的属性名称大小写不一致

    我已经为此摸不着头脑有一段时间了 并决定让 SO 社区来尝试一下 我有一些响应客户端 POST 的操作 这些操作执行简单的任务并返回JsonResult从具有简单布尔 Success 属性的匿名类构建 如果成功 或者返回PartialVie
  • 错误:sonar.sources 的值无效

    尝试运行 sonartest 但失败了 我的詹金斯控制台输出 Started by user Badal Singh Building on master in workspace C Program Files x86 Jenkins w
  • 从设备获取屏幕截图时出现意外错误:EOF

    当我尝试在 Android Studio 中从我的某些项目中截取屏幕截图 通过按相机图标 时 我收到以下消息 Unexpected error while obtaining screenshot from device EOF 如果我在打
  • 如何比较java中的多个类?

    现在 我已经编写了对整数和字符串数组进行排序的比较器 从代码中可以看出 如果两个类不相同 则 String 类将采用大于值 但是 这仅允许两个类 如果我想向数组添加另一个基本类型 例如 Float 怎么办 我必须向 if else 语句添加
  • x64 上类方法崩溃的地址

    The AddressOf运算符仅适用于标准 bas 模块内的方法 我使用以下代码来检索类方法的地址 Option Explicit If VBA7 Then Private Declare PtrSafe Function DispCal