70

この質問は、もともと 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 にアクセスする際に同じ問題を抱えているようですが、うまくいく解決策は見つかりませんでした。

私は次のことを試しました:

  • DEPENDS を実行して依存関係を確認し、最初の 3 つがパスの System32 ディレクトリにあり、最後の 3 つが .NET 2 フレームワークにあることを確認します。
  • 2 つの DLL とその依存関係を System32 に配置し、サーバーを再起動しましたが、Web サイトはこれらの外部 DLL を読み込めませんでした。
  • ASPNET、IIS_WPG、および IUSR (そのサーバー用) に完全な権限を Web サイトの bin ディレクトリに与えて再起動しましたが、Web サイトはこれらの外部 DLL を読み込めませんでした。
  • 外部 DLL を既存の項目としてプロジェクトに追加し、それらの [出力にコピー] プロパティを [常にコピー] に設定しましたが、Web サイトはまだ DLL を見つけることができません。
  • また、「ビルド アクション」プロパティを「埋め込みリソース」に設定しても、Web サイトはまだ DLL を見つけることができません。

この問題に関するご支援をいただければ幸いです。

4

11 に答える 11

50

これは、マネージド DLL が .NET Framework ディレクトリの下の一時的な場所にシャドウ コピーされるために発生します。詳細については、 http://msdn.microsoft.com/en-us/library/ms366723.aspxを参照してください。

残念ながら、管理されていない dll はコピーされず、ASP.NET プロセスはそれらをロードする必要があるときにそれらを見つけることができません。

簡単な解決策の 1 つは、管理されていない DLL をシステム パス (コマンド ラインで "path" と入力して、マシン上のパスを確認します) にあるディレクトリに配置して、ASP.NET プロセスで検出できるようにすることです。System32 ディレクトリは常にパスにあるため、管理されていない dll をそこに置くことは常に機能しますが、System32 ディレクトリの汚染を防ぐために、他のフォルダーをパスに追加してからそこに dll を追加することをお勧めします。この方法の大きな欠点の 1 つは、アプリケーションのバージョンごとに管理されていない dll の名前を変更する必要があり、すぐに独自の dll 地獄を作成できることです。

于 2009-05-14T05:23:51.133 に答える
42

既にパスにあるフォルダー (system32 など) に dll を配置する代わりに、次のコードを使用してプロセスのパス値を変更できます。

System.Environment.SetEnvironmentVariable("Path", searchPath + ";" + oldPath)

次に、LoadLibrary がアンマネージ DLL を見つけようとするときに、searchPath もスキャンします。これは、System32 やその他のフォルダーを混乱させるよりも好ましい場合があります。

于 2011-01-04T21:44:39.760 に答える
22

\System32\Inetsrv ディレクトリに dll を配置してみてください。これは、Windows Server 上の IIS の作業ディレクトリです。

これが機能しない場合は、dll を System32 ディレクトリに、依存ファイルを Inetsrv ディレクトリに配置してみてください。

于 2008-12-05T20:31:54.540 に答える
12

Matt の回答に加えて、これが 64 ビット サーバー 2003/IIS 6 で最終的に機能したものです。

  1. dll / asp.net が同じバージョン (32 / 64 ビット) であることを確認してください。
  2. 管理されていない dll を inetsrv ディレクトリに配置します (64 ビット Windows では、sys32/inetsrv ディレクトリが作成されていても、これは syswow64 の下にあることに注意してください)。
  3. 管理された dll を /bin に残します
  4. 両方の dll セットに読み取り/実行権限があることを確認してください
于 2009-04-22T16:11:58.647 に答える
6

FileMonまたはProcMonを調べて、問題のある DLL の名前をフィルタリングします。これにより、DLL を検索するためにスキャンされるディレクトリと、発生する可能性のあるアクセス許可の問題が表示されます。

于 2008-12-05T20:37:21.753 に答える
4

もう1つのオプションは、ネイティブDLLをリソースとしてマネージDLLに埋め込むことです。これは、実行時に一時フォルダーに書き込む必要があるため、ASP.NETではより複雑です。 この手法は、別のSO回答で説明されています

于 2012-06-20T16:34:30.550 に答える
2

この問題に一日中苦労した後、ついに自分に合った解決策を見つけました。これは単なるテストですが、メソッドは機能しています。

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();
                  }
                }
          }
        }
    }
}
于 2015-12-12T09:29:53.510 に答える
2

私は同じ問題に遭遇しました。そして、system32へのコピー、inetpub、パス環境の設定など、上記のすべてのオプションを試しましたが、何も機能しませんでした。この問題は、管理されていない dll を Web アプリケーションまたは Web サービスの bin ディレクトリにコピーすることで最終的に解決されます。

于 2015-08-26T09:11:56.120 に答える
2

環境設定のパス変数も常にチェックする価値があります。

于 2008-12-05T20:39:04.433 に答える
1

配置した場所で、XYZ.dll に対して DEPENDS を直接実行します。不足しているものが見つからない場合は、プラットフォーム SDK の fuslogvw ツールを使用して、ローダー エラーを追跡します。また、イベント ログには、DLL の読み込みの失敗に関する情報が含まれている場合があります。

于 2008-12-05T17:38:54.593 に答える