2

我正在开发一个需要使用托管代码包装的 C 库的项目。C 库是为 32 位编译的,我发现它需要msvcr71.dll. 问题是,无论出于何种原因,此 DLL 在 SysWOW64 目录中都没有随 Windows Server 2008 一起提供。

我已经从系统上的 SQL Management Studio 复制了 DLL,我可以验证它是否可以在服务器上的独立 EXE 中运行。没有什么可以阻止它工作。

但是......当我将它链接到我的 ASP.NET 应用程序并确保我的库的 DLL 和 msvcr71.dll 都在我的/bin目录中时,我的网站的应用程序池从我下面掉出来了。werfault.exe启动,吃掉一堆 CPU 和 RAM,然后离开并在事件查看器中留下这个几乎无用的日志。

然后应用程序池重新启动并等待再次失败。它在集成模式下与 .NET 4 一起运行。该站点基于 MVC 3。

Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7a5f8
Faulting module name: ntdll.dll, version: 6.1.7601.17725, time stamp: 0x4ec49b8f
Exception code: 0xc0000374
Fault offset: 0x000ce6c3
Faulting process id: 0x998
Faulting application start time: 0x01cd753eb1fcd760
Faulting application path: C:\Windows\SysWOW64\inetsrv\w3wp.exe
Faulting module path: C:\Windows\SysWOW64\ntdll.dll
Report Id: 7b54f020-e132-11e1-a34d-404094d3cf82

这到底是怎么回事?我很想将 DLL 直接链接到我的 ASP.NET 站点,但我正处于编写代理应用程序的边缘……如果可能的话,我想避免这种黑客攻击。谢谢。

旁注所有这些在我的本地机器上都可以正常工作。只有在服务器上,我才能将它链接到 IIS 中。

更新

在 IIS 中运行时,这似乎是一个互操作问题,尤其是使用字符串方法时……我现在正在研究它……

http://blogs.msdn.com/b/asiatech/archive/2009/12/24/net-application-may-crash-on-windows-2008-when-calling-function-from-native-c-dll。 aspx

4

1 回答 1

1

讨厌回答我自己的问题,但它需要为其他人记录一个解决方案。我在这里遇到的核心问题实际上并不是msvcr71.dll(最终我认为我最终确实针对 C 运行时的版本 10 重新编译了相关库的原始 C 源代码,msvcr100.dll因为它默认包含在 Windows Server 2008 中。

我仍在针对 x86 运行该库。然而,这里真正的问题是,在使用 .NET 中的字符串对 P/Invokes 进行互操作时,存在某种内存管理错误(或功能,由您决定)导致 IIS 7 崩溃。我认为它的目的是作为一种安全功能......谁知道呢。

查看上面问题更新中列出的文章,了解有关此问题的部分详细信息:

http://blogs.msdn.com/b/asiatech/archive/2009/12/24/net-application-may-crash-on-windows-2008-when-calling-function-from-native-c-dll。 aspx

如果你好奇的话,我正在使用的特定库是用于 GIS 工具中的 Shapefile。

http://shapelib.maptools.org/

这对我来说很有意义,但我的库是用 C 而不是 C++ 编写的。无论如何,这两种语言都不是我的强项,而且我找不到CoTaskMemFreeC 编译器中存在的方法。这可能是我自己的错,但我真的没有时间学习和重写一些古老的C代码。

我发现我不能使用 .NET 方法将字符串编组回来,而是手动执行IntPtr以防止 IIS 崩溃。

这是我的原始导入:

    [DllImport("shapelib.dll", CharSet = CharSet.Ansi)]
public static extern string DBFReadStringAttribute (IntPtr hDBF, int iShape, int iField);

...这就是我必须将其更改为:

    [DllImport("shapelib.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr DBFReadStringAttribute (IntPtr hDBF, int iShape, int iField);

这种变化本身就阻止了应用程序崩溃。然后我不得不创建这种技巧来拉出弦乐。我知道这绝非乐观主义者,但这是我目前能做的最好的事情。

这就是我最终做的事情......

public static string DBFReadStringAttribute(IntPtr hDBF, int iShape, int iField)
{
    IntPtr dataPtr = _DBFReadStringAttribute(hDBF, iShape, iField);
    string output = Marshal.PtrToStringAnsi(dataPtr, 255); //255 is the supposed max length for DBF databases
    int idx = output.IndexOf('\0');
    string strData;
    if (idx > 0)
        strData = output.Substring(0, idx).Trim();
    else
        strData = "";

    return strData;
}

[DllImport("shapelib.dll", CharSet = CharSet.Ansi, EntryPoint = "DBFReadStringAttribute")]
private static extern IntPtr _DBFReadStringAttribute (IntPtr hDBF, int iShape, int iField);

附加说明

无论出于何种原因,都Marshal.PtrToStringAnsi(dataPtr)没有正确检索字符串(它会损坏)。我必须设置一个 maxlength 并自己解析它。

于 2012-08-09T00:49:22.693 回答