运行时错误 49,错误的 DLL 调用约定
Posted
技术标签:
【中文标题】运行时错误 49,错误的 DLL 调用约定【英文标题】:Runtime Error 49, Bad DLL calling convention 【发布时间】:2013-04-02 07:49:54 【问题描述】:问。每当加载我的插件时,Excel 都会抛出以下错误()
尽管绝对没有外部 DLL 引用,但每次都会开始弹出对话框,但没有指明错误在哪里。
或
问。每次我保存特定的代码行时,Excel 都会崩溃。
如何解决这个问题?
【问题讨论】:
【参考方案1】:此错误可能是由于编译器错误而发生的。 最简单的解决方案是进行小的代码更改并重新编译。 我通常做的是,
1 -> 将Private Enum
类型添加到插件中任何模块的顶部
Private Enum Something
member = 1
End Enum
2 -> 编译插件
3 -> 重启excel
4 -> 删除所做的代码更改。不再需要了。
【讨论】:
有趣!只是出于好奇:您如何设法同时发布问题和答案?你“预写”了答案吗? @PeterAlbert 在将问题发布到answer it yourself 时有一个复选框。 我使用以下快捷键:Ctrl+A
- Ctrl+X
- Ctrl+V
- Ald+D
- L
在使用 stenci 的 Ctrl+X 技术时要小心。它消除了每个宏键盘快捷键。和描述。【参考方案2】:
即使此错误涉及外部 (DLL) 函数调用,它 可以由参数或返回值类型不匹配触发 VBA 定义的函数或子例程。此外,当它是 由这些原因触发,调试器有时会显示错误 指向不同的函数调用,通常在 调用堆栈,包括一直有效且稳定的调用,直到 问题情境被创造出来。通常,问题被触发 由于固定类型的参数参数或返回值与 变体,反之亦然。
示例:变量值函数返回一个 分配给整数变量的运行时长值。
分辨率:
仔细检查所有参数参数并返回 值类型和赋值语句,尤其是对于那些 你最近一直在工作。如果有任何变体值函数,则显式类型转换为正确的类型 任务。 如果由于使用 Application.Run 方法调用不同工作簿中的例程(您无法控制参数定义)而无法避免上述情况,则由于 Application.Run 方法传递了所有参数ByVal,然后,如果包含例程是 Sub,请尝试将其转换为没有指定返回类型的 Function。这似乎会强制清理堆栈并抑制错误条件在调用堆栈中的更高级别引发。一种对象方法(例如 AutoFit)应用于该方法不可用的错误对象变体(例如 AutoFit 应用于既不是整行也不是整行的范围 列范围)。与上述情况类似,错误可能是 抛出问题所在例程的返回点 语句存在,而不是语句本身。
解决方案:首先修复 语法问题。不幸的是,有时应该有效的修复 继续抛出错误,直到 VBE 编辑器被重置。一世 尚未推断出解决该问题的最小步骤集,但 这样的事情通常有效:
显式重新编译项目。 保存文件并关闭它。 重新打开文件并重新运行代码。如果对外部库函数的调用被确定为罪魁祸首,请参阅 Microsoft 的错误文档:
错误的 DLL 调用约定
*传递给动态链接库 (DLL) 的参数必须完全匹配 那些例行公事所期望的。调用约定处理数字, 类型和参数的顺序。您的程序可能正在调用例程 在传递错误类型或参数数量的 DLL 中。
要纠正这个错误,请确保所有参数类型都与这些一致 在您正在调用的例程的声明中指定。
确保您传递的参数数量与 您正在调用的例程的声明。
如果 DLL 例程需要按值参数,请确保 ByVal 是 在例程的声明中为这些参数指定。
返回参数: 一件事很容易被忽视 谈论过程参数是返回参数。确保 它的类型正确,或者它没有丢失。 Excel/VBA 用户 习惯于这样一个事实,如果你遗漏了一个返回类型 函数,系统隐式将返回类型设置为 Variant,并且 它适用于任何返回的数据。外部声明的情况并非如此 职能!!返回类型必须在 DECLARE 中声明 声明。*
损坏的库引用:检查模块代码的库引用是否有效。在 VBA IDE 中,选择 Tools=>References 查看引用库列表并制作 确保所有选中的项目都没有标记为“Missing”。如果是这样,修复 那些。
【讨论】:
【参考方案3】:或者,最好的选择:
- 重写例程的名称。
- 然后重新编译!
你现在可以走了!
【讨论】:
这个答案缺乏细节和细节。虽然有些人可能不同意“语气” - 我对此很好,实际上,我喜欢它,但答案本身就是想要...... JoeG,我尊重你的意见。希望你明白,如果我能提供更多细节,我会的。但是,请在遇到问题时回到这里,并在我建议的解决方案之前尝试一切。然后试试这个解决方案。它会像魅力一样起作用。那是一个承诺。关于语气,感谢您对此表示满意。 在测试之前给答案 -1 实际上是我非常不同意的。 为我工作。我不知所措 - 没有任何合乎逻辑的工作。 @FernandoFernandes 有我的投票!谢谢老哥!【参考方案4】:关于信息,我还在运行良好的 Excel VBA 代码中遇到了“运行时错误 49,错误的 DLL 调用约定”。
错误指向一个内部函数调用,我的解决方法是将参数从 ByVal 更改为 ByRef。存在对另一个函数的调用,其中该值已通过 ByRef 传递,因此这可能是一个因素。
【讨论】:
【参考方案5】:替代“更改/添加某些内容并重新编译”的另一种方法是/反编译您的项目。 特别是。在可以解决很多问题的大型 access/excel 项目中。
【讨论】:
我希望我能投票更多。这正是问题所在!谢谢。 @Stejin 你如何反编译 Excel 项目? 应该与 Access 中的工作方式相同。使用“/反编译”参数,例如打开目标程序的 cmd 脚本:“path_to_exe /decompile path_to_file”【参考方案6】:只是为了添加另一个可能的原因,我使用 Application.OnTime 方法来调用带有参数的公共子。该参数应该是很长的(当前行),但我猜它实际上是作为字符串值传递的。
这是 OnTime 调用的示例:
Application.OnTime Now + TimeValue("00:00:01"), "'UpdateEditedPref " & curRow & "'"
我尝试对代码执行任意更新并重新编译,但这并没有解决问题。修复它的原因是在被调用的 sub 中将参数类型从 long 更改为 string:
Public Sub UpdateEditedPref(ByVal inRowStr As String)
然后你只需要将字符串转换为 sub 中的值。谢天谢地,没有更多错误。
更新: 使用 Application.OnTime 传递参数似乎导致了另一个错误,“无法运行宏”。当工作表被锁定时,我收到了这个错误。我仍在使用 Application.OnTime,但我没有传递参数,而是将值保存在全局变量中并在被调用的子变量中使用该值。这现在似乎工作正常。
OnTime 调用现在如下所示:
' Set global variable
gCurRow = curRow
Application.OnTime Now + TimeValue("00:00:01"), "UpdateEditedPref"
【讨论】:
【参考方案7】:我遇到了类似的问题,在我的开发 PC 上它工作得很好。有趣的是,我对同一个例程进行了两次单独的调用,一个有效,另一个无效。在生产 PC 上,不断收到错误消息。尝试重命名例程,更改参数,参数类型无济于事。
对我有用的是将失败的调用例程移动到与被调用子例程相同的模块中。
之前运行的例程已经在同一个模块中。
【讨论】:
【参考方案8】:在我的情况下,这是由于在单个 if 条件中过度使用继续字符 _ 而“引起”的
我已经重新编译,检查了所有返回码,移动了模块,重新启动了 excel,重新启动了我的计算机,将代码复制到了一个全新的 Excel 电子表格中,我读了这篇文章,关于返回码的一点让我思考if 语句中可以返回多少个返回值
我有这个
If CompressIntoOneLineON(rg1, rgstart, rgend) or _
CompressIntoOneLineOS(rg1, rgstart, rgend) or _
CompressIntoOneLineOGN(rg1, rgstart, rgend) or _
CompressIntoOneLineOGS(rg1, rgstart, rgend) or _
CompressIntoOneLineGO(rg1, rgstart, rgend) Then
<code>
End If
包含此代码的子例程退出时出现错误 所以我改成了这个
matched = True
If CompressIntoOneLineON(rg1, rgstart, rgend) Then
ElseIf CompressIntoOneLineOS(rg1, rgstart, rgend) Then
ElseIf CompressIntoOneLineOGN(rg1, rgstart, rgend) Then
ElseIf CompressIntoOneLineOGS(rg1, rgstart, rgend) Then
ElseIf CompressIntoOneLineGO(rg1, rgstart, rgend) Then
Else
matched = False
End If
if matched then
<code>
错误消失了
【讨论】:
【参考方案9】:我的实验表明: 当我替换声明时,错误:“运行时错误 49,错误的 DLL 调用约定”消失了:
Dim coll as new Collection
开
Dim coll as Collection
Set coll = New Collection
对象必须在创建失败时显式变为 Nothing(如果它本身没有),以便可以追踪其存在。
谢谢,RubberDuck VBA
【讨论】:
以上是关于运行时错误 49,错误的 DLL 调用约定的主要内容,如果未能解决你的问题,请参考以下文章