【问题标题】:What are the non-obvious reasons a 32-bit app would fail on a 64-bit machine?32 位应用程序在 64 位计算机上失败的非显而易见的原因是什么?
【发布时间】:2011-02-11 12:56:47
【问题描述】:

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

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

【问题讨论】:

  • 失败的性质是什么?请出现堆栈跟踪或返回代码失败等异常。
  • 嗨,杰西,谢谢您的回复。基本上,服务只是停止工作,werfault.exe *32 出现在任务管理器中。

标签: .net wcf 32bit-64bit


【解决方案1】:

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

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

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

【讨论】:

  • 它实际上只是一个用于加密/解密字符串的库。我们将一个字符串/键组合传递给它,它返回另一个字符串。不过,我很欣赏你的想法。我们没有自己的线索......
【解决方案2】:

我猜你是在 .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 位片段时发生的情况。从那里,您(可能还有我们)可以得到一些很好的证据来证明什么可能会失败。

【讨论】:

    【解决方案3】:

    堆损坏!显然有一个名为 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;
        }
    

    希望这对遇到同样问题的人有所帮助。

    【讨论】:

      猜你喜欢
      • 2016-09-27
      • 2011-11-04
      • 1970-01-01
      • 2014-03-23
      • 2011-12-22
      • 2018-05-16
      • 1970-01-01
      • 1970-01-01
      • 2016-05-17
      相关资源
      最近更新 更多