32 位应用程序在 64 位计算机上失败的非明显原因是什么?

发布于 2024-08-30 04:38:15 字数 284 浏览 2 评论 0原文

我们有一个用 Borland Delphi 编写和编译的 32 位库。该库被各种其他项目引用,包括 IIS 中托管的 WCF Web 服务。 Web 服务是使用 x86 选项编译的,并且在 32 位计算机上一切正常。然而,在我们的 64 位服务器上,调用 32 位 Delphi 库时服务失败。我们的一些客户甚至在 64 位计算机上调用 32 位 .NET Forms 库时遇到问题;尽管我们无法重现这个特定问题。

那么,有谁知道为什么使用 32 位选项编译的 .NET 代码在 64 位计算机上调用非 .NET 32 位库时仍然会失败?

We have a 32-bit library written and compiled in Borland Delphi. This library is referenced by various other projects including a WCF Web Service hosted in IIS. The web service is compiled using the x86 option and everything works fine on a 32-bit machine. However, on our 64-bit server the service fails when calling into the 32-bit Delphi library. Some of our clients are even having problem with 32-bit .NET Forms calling into the library on a 64-bit machine; though we have not been able to duplicate that particular problem.

So, does anyone know why .NET code compiled with 32-bit option would still fail while calling a non-.NET 32-bit library on a 64-bit machine?

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

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

发布评论

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

评论(3

寄意 2024-09-06 04:38:15

好吧,只是一种疯狂的猜测:)

你是否有多个进程在交互?这些进程是否尝试写入/读取受保护的文件夹(例如%PROGRAMFILES%、%WINDIR%)? (即,这些进程是否使用 IPC 等文件夹中的文件?)

由于 64 位 Windows 会将写入重定向到 32 位应用程序的此类文件夹(基于每个用户),如果进程在不同的用户凭据下运行,这些进程可能只是无法找到其他进程创建的文件。

Well, just a wild guess :)

Do you have more than one process interacting?. Does these processes try to write/read to protected folders (for instance %PROGRAMFILES%, %WINDIR%)? (i.e, does these processes use files in such folders as a IPC ?)

Since 64 bits Windows will redirect writes to such folders for 32 bit apps (on a per user base) if the processes run under different user credentials these processes may be just failing to find a file created by the other process.

笨死的猪 2024-09-06 04:38:15

我猜您正在 .NET 端定义方法的入口点,如下所示?

internal static class Delphi
{
    [DllImport("delphi32bitlibrary.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool Encrypt(
        IntPtr parameter1,
        string parameter2,
        out string parameter3);
}

然后你以类似的方式在某个地方调用它?

string encryptedString;
Delphi.Encrypt(IntPtr.Zero, "test", out encryptedString);

如果是这种情况(实际实现中您的情况可能会有所不同),您可以这样重写吗:

string encryptedString;
try
{
    Delphi.Encrypt(IntPtr.Zero, "test", out encryptedString);
}
catch (Exception ex)
{
    EventLog log = new EventLog();

    log.WriteEntry(ex.Message + "\n" + ex.StackTrace, EventLogEntryType.Error);
}

这应该在计算机的事件日志中放入调用 32 位片段时发生的情况的详细解释。从那里,您(可能还有我们)可以获得一些关于可能出现故障的良好证据。

I'm guessing you're defining the entry point of the method on the .NET side something like this?

internal static class Delphi
{
    [DllImport("delphi32bitlibrary.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool Encrypt(
        IntPtr parameter1,
        string parameter2,
        out string parameter3);
}

and then you call it somewhere in a similar fashion?

string encryptedString;
Delphi.Encrypt(IntPtr.Zero, "test", out encryptedString);

If that is the case (your mileage may vary in the actual implementation), can you rewrite it as such:

string encryptedString;
try
{
    Delphi.Encrypt(IntPtr.Zero, "test", out encryptedString);
}
catch (Exception ex)
{
    EventLog log = new EventLog();

    log.WriteEntry(ex.Message + "\n" + ex.StackTrace, EventLogEntryType.Error);
}

This should put in the computer's event log a detailed explanation of what happened when the 32-bit piece was called. From there, you (and possibly us) can get some good evidence as to what may be failing.

梦罢 2024-09-06 04:38:15

堆腐败!显然有一个名为 HeapEnableTerminationOnCorruption 的标志以前默认情况下未启用。作为 Windows Vista 中的一项新功能,当检测到堆损坏时,IIS 工作进程将终止。因此,它似乎只在我们的独立应用程序和 32 位 Windows XP 计算机上运行,​​而实际上它只是忽略了该错误。

为了解决这个问题,我们更改了调用 Delphi 库的代码以使用 IntPtrs 并使用 out 参数将数据传回。例如:

    public string CallDLL(string sTest)
    {
        string s = "";

        IntPtr p1 = Marshal.StringToHGlobalAnsi(sTest);
        s = Marshal.PtrToStringAnsi(p1);
        if (p1 != IntPtr.Zero)
        {
            Class1.TestDLL(out p1);
            s = Marshal.PtrToStringAnsi(p1);
        }

        Marshal.FreeCoTaskMem(p1);
        return s;
    }

希望这可以帮助任何遇到同样问题的人。

Heap corruption! Apparently there is a flag called HeapEnableTerminationOnCorruption that was not previously enabled by default. As a new feature in Windows Vista, the IIS worker process terminates when the heap corruption is detected. So, it only APPEARED to be working in our stand-alone apps and on our 32-bit Windows XP machines, when in actuality it was simply ignoring the error.

To fix the problem we changed our code for calling into the Delphi libraries to use IntPtrs and pass data back using out parameters. For example:

    public string CallDLL(string sTest)
    {
        string s = "";

        IntPtr p1 = Marshal.StringToHGlobalAnsi(sTest);
        s = Marshal.PtrToStringAnsi(p1);
        if (p1 != IntPtr.Zero)
        {
            Class1.TestDLL(out p1);
            s = Marshal.PtrToStringAnsi(p1);
        }

        Marshal.FreeCoTaskMem(p1);
        return s;
    }

Hope this helps anyone with the same issue.

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