この質問は、元はVS 2005で、現在はVS 2008で開発されたASP.NET Webサイトに関連しています。
このWebサイトは、.NETではない2つのアンマネージ外部DLLを使用しており、それらをコンパイルするソースコードがなく、そのまま使用する必要があります。
このWebサイトはVisual Studio内から正常に動作し、これらの外部DLLを正しく見つけてアクセスします。ただし、Webサイトが開発PCではなくWebサーバー(IIS6およびASP.NET 2.0を実行)で公開されると、これらの外部DLLを見つけてアクセスできず、次のエラーが表示されます。
Unable to load DLL 'XYZ.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
外部DLLは、それらをラップするマネージDLLおよびWebサイトの他のすべてのDLLとともに、Webサイトのbinディレクトリにあります。
この問題を検索すると、他の多くの人がASP.NET Webサイトから外部の非.NET DLLにアクセスするのと同じ問題を抱えているように見えますが、有効なソリューションは見つかりませんでした。
私は次を試しました:
この問題に関する支援は大歓迎です!
Dllを\ System32\Inetsrvディレクトリに配置してみてください。これは、Windows Server上のIISの作業ディレクトリです。
これが機能しない場合は、dllをSystem32ディレクトリに、依存関係ファイルをInetsrvディレクトリに入れてみてください。
これは、マネージDLLが.NET Frameworkディレクトリの下の一時的な場所にシャドウコピーされるために発生します。詳細については、 http://msdn.Microsoft.com/en-us/library/ms366723.aspx を参照してください。
残念ながら、アンマネージdllはコピーされず、ASP.NETプロセスはそれらをロードする必要があるときにそれらを見つけることができません。
簡単な解決策の1つは、管理されていないdllをシステムパス(コマンドラインで「path」と入力してマシン上のパスを表示)にあるディレクトリに配置し、ASP.NETプロセスで見つけられるようにすることです。 System32ディレクトリはパスにalwaysであるため、そこにアンマネージdllを配置すると常に機能しますが、パスに他のフォルダーを追加してから追加することをお勧めしますSystem32ディレクトリの汚染を防ぐために、そこにあるDLL。この方法の大きな欠点の1つは、アプリケーションのすべてのバージョンのアンマネージdllの名前を変更する必要があり、独自のdllヘルルがあることです。
既にパス(system32など)にあるフォルダーにdllを配置する代わりに、次のコードを使用してプロセスのパス値を変更できます。
System.Environment.SetEnvironmentVariable("Path", searchPath + ";" + oldPath)
次に、LoadLibraryがアンマネージDLLを見つけようとすると、searchPathもスキャンされます。これは、System32または他のフォルダーで混乱を起こすよりも望ましい場合があります。
Mattの答えに加えて、これが最終的に64ビットサーバー2003で私にとってうまくいったことです/ IIS 6:
別のオプションは、ネイティブDLLをマネージDLLのリソースとして埋め込むことです。これは、実行時に一時フォルダーに書き込む必要があるため、ASP.NETではより複雑です。 テクニックは別のSO answer で説明されています。
常に価値がある パスをチェックする 環境設定でも変数。
私は同じ問題に出くわしました。そして、上記のすべてのオプションを試してみましたが、system32、inetpubへのコピー、パス環境の設定など何も機能しませんでした。この問題は、アンマネージdllをWebアプリケーションまたはWebサービスのbinディレクトリにコピーすることで最終的に解決されます。
XYZ.dllを展開した場所で直接DEPENDSを実行します。見つからない場合は、プラットフォームSDKのfuslogvwツールを使用してローダーエラーをトレースします。また、イベントログには、DLLのロードの失敗に関する情報が含まれることがあります。
Аfterはこの問題に終日苦労し、最終的に私は自分に合った解決策を見つけました。これは単なるテストですが、メソッドは機能しています。
namespace TestDetNet
{
static class NativeMethods
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
}
public partial class _Default : System.Web.UI.Page
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate int GetRandom();
protected System.Web.UI.WebControls.Label Label1;
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = "Hell'ou";
Label1.Font.Italic = true;
}
protected void Button1_Click(object sender, EventArgs e)
{
if (File.Exists(System.Web.HttpContext.Current.Server.MapPath("html/bin")+"\\DelphiLibrary.dll")) {
IntPtr pDll = NativeMethods.LoadLibrary(System.Web.HttpContext.Current.Server.MapPath("html/bin")+"\\DelphiLibrary.dll");
if (pDll == IntPtr.Zero) { Label1.Text = "pDll is zero"; }
else
{
IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "GetRandom");
if (pAddressOfFunctionToCall == IntPtr.Zero) { Label1.Text += "IntPtr is zero"; }
else
{
GetRandom _getRandom = (GetRandom)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,typeof(GetRandom));
int theResult = _getRandom();
bool result = NativeMethods.FreeLibrary(pDll);
Label1.Text = theResult.ToString();
}
}
}
}
}
}
Application_startでこれを使用します(必要に応じて/ bin/x64およびbin/dll/x64フォルダーをカスタマイズします)
String _path = String.Concat(System.Environment.GetEnvironmentVariable("PATH")
,";"
, System.Web.Hosting.HostingEnvironment.MapPath("~/bin/x64")
,";"
, System.Web.Hosting.HostingEnvironment.MapPath("~/bin/dll/x64")
,";"
);
System.Environment.SetEnvironmentVariable("PATH", _path, EnvironmentVariableTarget.Process);