2

マネージ コードでラップした C ライブラリを必要とするプロジェクトに取り組んでいます。C ライブラリは 32​​ ビット用にコンパイルされており、msvcr71.dll. 問題は、何らかの理由で、この DLL が Windows Server 2008 の SysWOW64 ディレクトリにストックされていないことです。

システム上の 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

私自身の質問に答えるのは嫌いですが、他の人のために記録された解決策が必要です. ここで私が抱えていた中心的な問題は実際にはありませんでした(最終的には、Windows Server 2008 にデフォルトで含まれているmsvcr71.dllC ランタイムのバージョン 10 に対して、問題のライブラリの元の C ソースを再コンパイルすることになったと思いました.msvcr100.dll

私はまだ x86 に対してライブラリを実行しています。ただし、ここでの本当の問題は、.NET で文字列を使用して P/Invokes で Interop を実行すると、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 ツールのシェープファイル用です。

http://shapelib.maptools.org/

これにはある程度の意味がありましたが、私のライブラリは C++ ではなく C で書かれています。とにかく、どちらの言語も私の得意分野ではなくCoTaskMemFree、C コンパイラに存在するメソッドを見つけることができませんでした。それはおそらく私自身のせいですが、古代の C コードを学び、書き直す時間がありませんでした。

.NET メソッドを使用して文字列をマーシャリングすることはできず、IntPtrIIS のクラッシュを防ぐために手動でマーシャリングすることはできないことがわかりました。

これが私の元のインポートです:

    [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 に答える