development

관리되지 않는 DLL이 ASP.NET 서버에서로드되지 않음

big-blog 2020. 11. 14. 10:50
반응형

관리되지 않는 DLL이 ASP.NET 서버에서로드되지 않음


이 질문은 원래 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이 있습니다.

이 문제를 검색하면 다른 많은 사람들이 ASP.NET 웹 사이트에서 .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을 찾을 수 없습니다.

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


\ System32 \ Inetsrv 디렉터리에 dll을 넣어보십시오. 이것은 Windows Server에서 IIS의 작업 디렉토리입니다.

이것이 작동하지 않으면 System32 디렉토리에 dll을 넣고 Inetsrv 디렉토리에 종속성 파일을 넣으십시오.


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

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

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


이미 경로에있는 폴더 (예 : system32)에 dll을 넣는 대신 다음 코드를 사용하여 프로세스의 경로 값을 변경할 수 있습니다.

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

그런 다음 LoadLibrary가 관리되지 않는 DLL을 찾으려고하면 searchPath도 검색합니다. 이것은 System32 또는 다른 폴더를 엉망으로 만드는 것보다 낫습니다.


Matt의 답변에 추가하면 이것이 64 비트 서버 2003 / IIS 6에서 마침내 저에게 효과적이었습니다.

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

FileMon 또는 ProcMon을 살펴보고 문제가있는 DLL의 이름을 필터링하십시오. 그러면 DLL을 검색 할 때 어떤 디렉터리가 검색되는지, 그리고 사용자가 가질 수있는 권한 문제가 표시됩니다.


또 다른 옵션은 기본 DLL을 관리되는 DLL에 리소스로 포함하는 것입니다. ASP.NET에서는 런타임에 임시 폴더에 기록해야하기 때문에 더 복잡합니다. 이 기술은 다른 SO 답변에 설명되어 있습니다.


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


XYZ.dll을 배포 한 위치에서 직접 DEPENDS를 실행합니다. 누락 된 내용이없는 경우 플랫폼 SDK의 fuslogvw 도구를 사용하여 로더 오류를 추적하십시오. 또한 이벤트 로그에는 때때로 DLL로드 실패에 대한 정보가 포함됩니다.


나는 같은 문제를 만났습니다. 그리고 위의 모든 옵션을 시도했지만 system32, inetpub에 복사, 경로 환경 설정 등 아무것도 작동하지 않았습니다. 이 문제는 관리되지 않는 dll을 웹 애플리케이션 또는 웹 서비스의 bin 디렉토리에 복사하여 최종적으로 해결됩니다.


이 문제로 하루 종일 고군분투하고 마침내 나에게 맞는 해결책을 찾았습니다. 테스트 일 뿐이지 만 방법은 작동합니다.

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

참고 URL : https://stackoverflow.com/questions/344608/unmanaged-dlls-fail-to-load-on-asp-net-server

반응형