2012-01-07 34 views
2

问题:如何在ASP.NET中使用原生dll?

我使用System.Data.OracleClient。

System.Data.OracleClient需要OracleInstantClient,它们是本地dll的。 因此,为了使用System.Data.OracleClient,我需要安装本机dll,或者在路径环境变量的文件夹中。

现在,基本的问题是,我没有管理员权限(公司的笔记本电脑 - 企业的愚蠢 - 不会改变)...
因此,我既不能安装任何东西,也不在PATH的文件夹中复制任何东西,我也不能将文件夹添加到PATH环境变量,我也可以重新启动/管理IIS或任何其他服务......

那么作为一个测试,我只是复制OCI.DLL和oraociei11.dll到同一文件夹作为WinForms .exe。
这工作得很好。我能够毫无问题地访问Oracle数据库(SELECT * FROM COUNTRIES)。

但现在,我需要在ASP.NET解决方案中执行相同的查询。 问题是,ASP.NET dll在执行时会将阴影复制到临时文件夹。

我们得到的dll到Web应用斌非的少,
在Global.asax中的

public class MvcApplication : System.Web.HttpApplication 

我重写了初始化这个:

public override void Init() 
{ 
    int iBitNess = IntPtr.Size; 
    //System.Windows.Forms.MessageBox.Show(iBitNess.ToString()); 
    // iBitNess = 4, so 32 bit dll's are right 



    string strTargetDirectory = System.Reflection.Assembly.GetExecutingAssembly().Location; 
    strTargetDirectory = typeof(DB.Abstraction.cDAL).Assembly.Location; 
    strTargetDirectory = typeof(MvcApplication).Assembly.Location; 
    strTargetDirectory = System.IO.Path.GetDirectoryName(strTargetDirectory); 

    string strSourcePath = Server.MapPath("~/bin/dependencies/InstantClient"); 
    string[] astrAllFiles = System.IO.Directory.GetFiles(strSourcePath, "*.dll"); 

    foreach (string strSourceFile in astrAllFiles) 
    { 
     string strTargetFile = System.IO.Path.GetFileName(strSourceFile); 
     strTargetFile = System.IO.Path.Combine(strTargetDirectory, strTargetFile); 
     System.IO.File.Copy(strSourceFile, strTargetFile); 
    } 

    base.Init(); 
} // End Sub Init 

,以复制本地dll的到所谓的正确位置。 但我仍然得到DllNotFound异常...

我该在哪里或如何将本机DLL放入ASP.NET应用程序?

我再说一遍:我无法设置环境变量,也无法将dll复制到路径中的文件夹。(这通常会解决问题)。

在您使用的

strTargetDirectory = 

我试了几个possibilites,其中没有工作的多次出现见。

+0

所有你应该做的是把你的应用程序的bin文件夹中的DLL。你为什么要在Init()代码中分别访问DLL? – RickNZ 2012-01-07 09:08:55

+0

@RickNZ:应该是对的。但事实并非如此。但我现在解决了它。新增解决方案 – 2012-01-07 09:39:55

+0

@RickNZ:ShadowCopy将.NET dll复制到另一个文件夹中,并从那里执行。因此,bin文件夹中的本机dll位于另一个文件夹中,并且不会找到/加载。 – 2015-05-20 10:01:39

回答

3

已解决。
显然仍然需要加载本机dll后将其复制到目标文件夹。
OnInit错误,它是针对HTTP模块的。
我们只需要这样做一次,因此移动到了Application_Start。

这里是我的代码,如果有人需要它:

// Hinweis: Anweisungen zum Aktivieren des klassischen Modus von IIS6 oder IIS7 
    // finden Sie unter "http://go.microsoft.com/?LinkId=9394801". 
    public class MvcApplication : System.Web.HttpApplication 
    { 

     [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)] 
     static extern IntPtr LoadLibrary(string lpFileName); 

     [System.Runtime.InteropServices.DllImport("kernel32", CharSet = System.Runtime.InteropServices.CharSet.Ansi, ExactSpelling = true, SetLastError = true)] 
     static extern UIntPtr GetProcAddress(IntPtr hModule, string procName); 

     [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)] 
     [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)] 
     static extern bool FreeLibrary(IntPtr hModule); 


     // See http://mpi4py.googlecode.com/svn/trunk/src/dynload.h 
     const int RTLD_LAZY = 1; // for dlopen's flags 
     const int RTLD_NOW = 2; // for dlopen's flags 

     [System.Runtime.InteropServices.DllImport("libdl")] 
     static extern IntPtr dlopen(string filename, int flags); 

     [System.Runtime.InteropServices.DllImport("libdl")] 
     static extern IntPtr dlsym(IntPtr handle, string symbol); 

     [System.Runtime.InteropServices.DllImport("libdl")] 
     static extern int dlclose(IntPtr handle); 

     [System.Runtime.InteropServices.DllImport("libdl")] 
     static extern string dlerror(); 


     public void LoadSharedObject(string strFileName) 
     { 
      IntPtr hSO = IntPtr.Zero; 

      try 
      { 

       if (Environment.OSVersion.Platform == PlatformID.Unix) 
       { 
        hSO = dlopen(strFileName, RTLD_NOW); 
       } 
       else 
       { 
        hSO = LoadLibrary(strFileName); 

       } // End if (Environment.OSVersion.Platform == PlatformID.Unix) 

      } // End Try 
      catch (Exception ex) 
      { 
       System.Diagnostics.Debug.WriteLine(ex.Message); 
      } // End Catch 

      if (hSO == IntPtr.Zero) 
      { 
       throw new ApplicationException("Cannot open " + strFileName); 
      } // End if (hExe == IntPtr.Zero) 

     } // End Sub LoadSharedObject 


     // http://stackoverflow.com/questions/281145/asp-net-hostingenvironment-shadowcopybinassemblies 
     public void EnsureOracleDllsLoaded() 
     { 
      int iBitNess = IntPtr.Size * 8; 

      string strTargetDirectory = System.Reflection.Assembly.GetExecutingAssembly().Location; 
      strTargetDirectory = System.IO.Path.GetDirectoryName(strTargetDirectory); 

      string strSourcePath = "~/bin/dependencies/InstantClient/"; 

      if (Environment.OSVersion.Platform == PlatformID.Unix) 
      { 
       strSourcePath += "Linux" + iBitNess.ToString(); 
      } 
      else 
      { 
       strSourcePath += "Win" + iBitNess.ToString(); 
      } 

      strSourcePath = Server.MapPath(strSourcePath); 

      string[] astrAllFiles = System.IO.Directory.GetFiles(strSourcePath, "*.dll"); 


      foreach (string strSourceFile in astrAllFiles) 
      { 
       string strTargetFile = System.IO.Path.GetFileName(strSourceFile); 
       strTargetFile = System.IO.Path.Combine(strTargetDirectory, strTargetFile); 
       System.IO.File.Copy(strSourceFile, strTargetFile, true); 

       //if(strTargetFile.EndsWith("orannzsbb11.dll", StringComparison.OrdinalIgnoreCase)) 
       if (System.Text.RegularExpressions.Regex.IsMatch(strTargetFile, @"^(.*" + RegexDirSeparator + @")?orannzsbb11\.(dll|so|dylib)$", System.Text.RegularExpressions.RegexOptions.IgnoreCase)) 
        continue; // Unneeded exception thrower 

       try 
       { 
        LoadSharedObject(strTargetFile); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine(ex.Message); 
       } 

      } // Next strSourceFile 

     } // End Sub EnsureOracleDllsLoaded 


     public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
     { 
      filters.Add(new HandleErrorAttribute()); 
     } // End Sub RegisterGlobalFilters 


     public static void RegisterRoutes(RouteCollection routes) 
     { 
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

      routes.MapRoute(
       "Default", // Routenname 
       "{controller}/{action}/{id}", // URL mit Parametern 
       //new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameterstandardwerte 
       new { controller = "Home", action = "Test", id = UrlParameter.Optional } // Parameterstandardwerte 
      ); 

     } // End Sub RegisterRoutes 


     protected void Application_Start() 
     { 
      EnsureOracleDllsLoaded(); 
      AreaRegistration.RegisterAllAreas(); 

      RegisterGlobalFilters(GlobalFilters.Filters); 
      RegisterRoutes(RouteTable.Routes); 
     } // End Sub Application_Start 


    } // End Class MvcApplication : System.Web.HttpApplication 
+0

RegexDirSeparator:System.Text.RegularExpressions.Regex.Escape(System.IO.Path.DirectorySeparatorChar.ToString()); – 2016-11-14 15:16:18