调用 Delphi DLL 导致 VB6 exe 崩溃,并显示“运行时错误 '-2147418113 (8000ffff)”方法“~”对象的“~”失败”,但仅限于某些机器!

发布于 2024-10-05 09:00:18 字数 1905 浏览 2 评论 0原文

我已经搜索了几个小时但找不到类似的东西。

这次崩溃有两种情况:一种是“运行时错误 '-2147418113 (8000ffff)' 对象 '~' 的方法 '~' 失败”,第二种是完全崩溃,Windows 询问我是否要向 Microsoft 报告此情况。在第二种情况下,我选择调试一次,它显示“App.exe (OLEAUT32.DLL) 中未处理的异常:0xC0000005:访问冲突”。

反汇编屏幕在顶行显示黄色指针:

>> 771148A4  mov ecx, dword ptr [esi]
   771148A6  add ecx, 15h
   771148A9  and ecx, 0FFFFFFF0h
   771148AC  push ecx
   771148AD  push esi
...

在第三方 Delphi DLL 中调用特定基本函数时出现问题,但我不能直接声明该 DLL 有错误,因为这种情况仅发生在我编译的程序可执行文件中。同样的 dll 被数百个其他客户使用,并且(至少目前)我是唯一遇到此问题的人。在客户的 PC 或第三方供应商的办公室中编译的相同源代码可以正常工作。

所以问题归结为:带有 SP6 的 VB6 从完全相同的源代码生成不同的二进制 exe 文件。在我的电脑上编译的那个在我的电脑上运行良好,我安装了一个干净的虚拟电脑来检查这一点,但在它应该的任何地方都不起作用;除了我的电脑之外,在客户或第三方供应商中编译的版本在任何地方都可以正常工作。

这与 Boost 描述的问题不同(请参阅此链接),因为 IDE并且编译后的应用程序在所有计算机上的行为方式相同。它们要么工作正常,要么严重损坏。

Public mXApp As XObjects.XApplication

Public Sub Main    
    On Error Resume Next
    Set mXApp = New XObjects.XApplication
    If Err.Number = 0 Then
        MsgBox "Found: " & mXApp.Version & vbCrLf & mXApp.GetAppPath
    Else
        MsgBox "XApp DLL not found. " & Err.Number & ": " & Err.Description
    End If
    Err.Clear
End Sub

Public Sub Login(Byval uid As String,  Byval pwd As String, Byval companyNr as Long)
Dim ok as Boolean
    ok = mXApp.Login(uid, pwd, companyNr)' >> CRASH! Program never gets to the next line.'
    If ok Then
        MsgBox "Login success"
    Else
        MsgBox "Login fails"
    End If
End Sub

请注意,创建 mXApp 对象后,完成两个函数调用(即 Version 和 GetAppPath),没有任何问题。崩溃发生在登录调用中。 VB IDE 对象浏览器将三个函数的定义显示为:

Function Version() As String
Function GetAppPath() As String
Function Login(UserName As String, Password As String, FirmNr As Long) As Boolean

有没有人有任何解决方案或(同样有用的)方法可以使供应商在他们自己的机器上重现此问题?

I have searched for hours but could not find anything similar.

The crash has two flavors; one is with "Run-time error '-2147418113 (8000ffff)' Method '~' of object '~' failed" and the second flavor is a total crash where Windows asks if I want to report this to Microsoft. In the second case I chose to debug once and it showed "Unhandled exception in App.exe (OLEAUT32.DLL): 0xC0000005: Access violation."

The Disassembly screen showed the yellow pointer at top line of:

>> 771148A4  mov ecx, dword ptr [esi]
   771148A6  add ecx, 15h
   771148A9  and ecx, 0FFFFFFF0h
   771148AC  push ecx
   771148AD  push esi
...

The problem occurs when calling a particular essential function in a third-party Delphi DLL, but I cannot declare outright that the DLL is buggy because this happens only in the program executables I compile. This same dll is used in hundreds of other customers and (at least for now) I am the only one running into this problem. The same source code compiled in the customer's PC, or the 3rd party supplier's office works fine.

So the problem boils down to this: VB6 with SP6 produces different binary exe files from the exact same source code. The one compiled on my pc works fine in my pc, and a clean virtual pc I installed to check this, but does not work anywhere it should; and the one compiled in the customer or the 3rd party supplier works fine everywhere except my pc.

It is unlike the problem Boost describes (see this link) since both the IDE and the compiled application behave in the same manner on all machines. They either work fine or break terribly.

Public mXApp As XObjects.XApplication

Public Sub Main    
    On Error Resume Next
    Set mXApp = New XObjects.XApplication
    If Err.Number = 0 Then
        MsgBox "Found: " & mXApp.Version & vbCrLf & mXApp.GetAppPath
    Else
        MsgBox "XApp DLL not found. " & Err.Number & ": " & Err.Description
    End If
    Err.Clear
End Sub

Public Sub Login(Byval uid As String,  Byval pwd As String, Byval companyNr as Long)
Dim ok as Boolean
    ok = mXApp.Login(uid, pwd, companyNr)' >> CRASH! Program never gets to the next line.'
    If ok Then
        MsgBox "Login success"
    Else
        MsgBox "Login fails"
    End If
End Sub

Note that after the mXApp object is created, two function calls are done -namely Version and GetAppPath- without any problem. The crash occurs in the Login call. VB IDE Object browser displays the definitions of the three functions as:

Function Version() As String
Function GetAppPath() As String
Function Login(UserName As String, Password As String, FirmNr As Long) As Boolean

Does anyone have any solutions or (equally usefully) ways that I can make the supplier reproduce this problem in their own machines?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

请持续率性 2024-10-12 09:00:18

好吧,如果没有看到 Delphi 方面的情况,很难确定,但是当您在 DLL 调用中遇到这样的问题时,首先需要检查两个标准的事情。

首先,确保 DLL 函数及其在 VB 程序中的导入标头使用相同的调用约定。如果 VB 将参数放在一处,而 Delphi DLL 在其他地方查找它们,则会出现未定义的行为。

其次,确保两侧使用相同的字符串类型。如果这是 COM,则您的字符串类型应该是 COM BSTR 类型,在 Delphi 中称为 WideString。不知道VB怎么称呼它。如果您向 DLL 传递的字符串类型与它预期接收的字符串类型不同,它将获得损坏的数据。

仔细检查这两件事,看看是否不能解决问题。

Well, it's hard to say for sure without being able to see the Delphi side of it, but when you get problems like this in DLL calls, there are two standard things to check first.

First, make sure the DLL function and the import header for it in the VB program are using the same calling convention. If VB is putting the paramters in one place and the Delphi DLL is looking for them somewhere else, you get undefined behavior.

Second, make sure you're using the same string type on both sides. If this is COM, your string type should be the COM BSTR type, known as WideString in Delphi. Not sure what VB calls it. If you're passing the DLL a different string type than it's expecting to receive, it'll get corrupt data.

Double-check these two things and see if that doesn't fix it.

茶底世界 2024-10-12 09:00:18

问题解决了!梅森让我仔细检查时说得很对:

...确保 DLL 函数和
在VB程序中导入它的头文件
使用相同的调用约定。
如果 VB 将参数放在一个
地点和 Delphi DLL 正在寻找
对于他们在其他地方,你会得到
未定义的行为。

我电脑上的 DLL 和客户中的 DLL 的构建始终略有不同。我假设它们具有完全相同的界面。但先别以为我粗心了;我不仅仅是假设这一点,在注册两个版本的 DLL 后,我在此处发布我的问题之前就已经编译了两个不同的可执行文件。

当我以为我已经尝试了第二个dll时,我错了。我在我的电脑上注册了 dll 版本 1.1。对象查看器显示了问题中的声明。我编译了可执行文件并进行了测试。然后,在不退出 IDE 的情况下,我注册了 dll 版本 1.2,并再次编译,假设 VB 编译器在编译期间会读取 dll 接口。那么这个假设是错误的。结果发现必须重新启动IDE。

在 dll 的供应商告诉我有一个可选的新参数后,问题得到了解决,但他们之前没有提及它,假设这不会成为问题,因为它是可选的。

以下是导致崩溃的差异:

Function Login(UserName As String, Password As String, FirmNr As Long, [PeriodNr As Long]) As Boolean

Problem Solved! Mason was quite right when telling me to double-check:

...make sure the DLL function and the
import header for it in the VB program
are using the same calling convention.
If VB is putting the paramters in one
place and the Delphi DLL is looking
for them somewhere else, you get
undefined behavior.

The DLL on my pc and the one in the customer were slightly different builds all along. And I had assumed that they had exactly the same interface. But wait before thinking I was careless; I did not just assume this, I had compiled two different executables after registering both versions of the DLL long before posting my question here.

When I thought I had tried the second dll, I was mistaken. I had registered the dll version 1.1 on my pc. The Object Viewer showed the declarations in the question. I compiled the executable and tested. And then without exiting the IDE, I registered the dll version 1.2 and compiled again assuming that the VB compiler would read the dll interface during compilation. Well this assumption was wrong. It turns out that the IDE had to be restarted.

Problem was solved after the supplier of the dll told me there was an optional new parameter, but they did not mention it earlier assuming this would not be problem since it was optional.

Below is the difference that caused the crashes:

Function Login(UserName As String, Password As String, FirmNr As Long, [PeriodNr As Long]) As Boolean
何以笙箫默 2024-10-12 09:00:18

确保加载正确的 DLL。 SysInternals 中的 Process Explorer 将向您显示任何应用程序正在使用的 DLL(将其配置为在下部窗格中显示 DLL)。也许您在不知不觉中加载了不同版本的 DLL。
您可以在这里直接运行它:
http://live.sysinternals.com/ 单击 procexp.exe

Make sure you're loading the right DLL. Process Explorer from SysInternals will show you the DLLs being used by any app (configure it to show DLLs in the lower pane). Maybe you're loading a different version of the DLL, unknowingly.
You can run it directly here:
http://live.sysinternals.com/ click on procexp.exe

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文