ASP.NET 서버에서 관리되지 않는 DLL을로드 할 수 없다



Answers

이는 관리되는 DLL이 .NET Framework 디렉토리 아래의 임시 위치로 섀도 복사본을 가져 오기 때문에 발생합니다. 자세한 내용은 http://msdn.microsoft.com/en-us/library/ms366723.aspx 를 참조하십시오.

불행히도 관리되지 않는 dll은 복사되지 않으며 ASP.NET 프로세스는로드해야 할 때이를 찾을 수 없습니다.

하나의 쉬운 솔루션은 시스템 경로 (명령 줄에서 "path"를 입력하여 컴퓨터의 경로를 볼 수있는)에있는 디렉터리에 관리되지 않는 dll을 두어 ASP.NET 프로세스에서 찾을 수 있도록하는 것입니다. System32 디렉토리는 항상 경로에 있으므로 관리되지 않는 dll은 항상 작동하지만, 경로에 다른 폴더를 추가 한 다음 dll을 추가하여 System32 디렉토리를 오염시키지 않는 것이 좋습니다. 이 방법의 한 가지 큰 단점은 응용 프로그램의 모든 버전에 대해 관리되지 않는 dll의 이름을 바꾸어야하고 자신의 dll을 빠르게 가질 수 있다는 것입니다.

Question

이 질문은 원래 VS 2005 및 현재 VS 2008에서 개발 된 ASP.NET 웹 사이트와 관련이 있습니다.

이 웹 사이트는 .NET이 아닌 관리되지 않는 두 개의 외부 DLL을 사용하며 컴파일 할 소스 코드가 없으므로 그대로 사용해야합니다.

이 웹 사이트는 Visual Studio 내에서 정상적으로 실행되어 이러한 외부 DLL을 올바르게 찾아 액세스합니다. 그러나 웹 사이트가 개발 PC가 아닌 웹 서버 (IIS6 및 ASP.NET 2.0 실행)에 게시 될 때이 외부 DLL을 찾아 액세스 할 수 없으며 다음과 같은 오류가 발생합니다.

Unable to load DLL 'XYZ.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

외부 DLL은 웹 사이트의 bin 디렉토리와 해당 DLL을 감싸는 관리 DLL 및 웹 사이트의 다른 모든 DLL과 함께 위치합니다.

이 문제를 검색하면 많은 다른 사람들이 ASP.NET 웹 사이트에서 외부 non.NET DLL에 액세스하는 것과 동일한 문제가있는 것으로 보이지만 제대로 작동하는 솔루션을 찾지 못했습니다.

나는 다음을 시도했다.

  • DEPENDS를 실행하여 종속성을 검사하여 처음 세 개가 경로의 System32 디렉터리에 있고 마지막이 .NET 2 프레임 워크에 있음을 확인합니다.
  • 나는 두 개의 DLL과 그 의존성을 System32에두고 서버를 재부팅했지만 웹 사이트는 여전히 이러한 외부 DLL을로드 할 수 없었다.
  • ASPNET, IIS_WPG 및 IUSR (해당 서버용)에 대한 전체 권한을 웹 사이트 bin 디렉토리에 부여하고 재부팅했지만 웹 사이트는 여전히 이러한 외부 DLL을로드 할 수 없었습니다.
  • 외부 DLL을 프로젝트에 기존 항목으로 추가하고 "Copy to Output"속성을 "Copy Always"로 설정하면 웹 사이트는 여전히 DLL을 찾을 수 없습니다.
  • 또한 "Build Action"속성을 "Embedded resource"로 설정하면 웹 사이트는 여전히 DLL을 찾을 수 없습니다.

이 문제에 대한 도움을 주시면 매우 감사하겠습니다!




Matt의 답변을 추가하면 64 비트 서버 2003 / IIS 6에서 마침내 성공했습니다.

  1. dll / asp.net이 동일한 버전 (32 / 64 비트)인지 확인하십시오.
  2. inetsrv dir에 관리되지 않는 dll을 넣습니다 (64 비트 창에서는 sys32 / inetsrv 디렉토리가 만들어졌지만 syswow64 아래에 있음)
  3. 관리되는 dll은 / bin에 두십시오.
  4. dll의 두 세트에 읽기 / 실행 권한이 있는지 확인하십시오.



항상 환경 설정에서 경로 변수를 확인할 가치가 있습니다.




➢이 문제에 대해 하루 종일 고민하고 결국에는 저에게 적합한 해결책을 찾았습니다. 그것은 단지 시험이지만,이 방법이 효과적입니다.

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();
                  }
                }
          }
        }
    }
}



또 다른 옵션은 네이티브 DLL을 관리되는 DLL에 리소스로 포함시키는 것입니다. 이것은 ASP.NET에서 더 복잡합니다. 런타임시 임시 폴더에 쓰기가 필요하기 때문입니다. 이 기술은 다른 SO 응답에서 설명됩니다 .




Related