2012-01-07 2 views
2

Question:Comment utiliser les DLL natives dans ASP.NET?

J'utilise System.Data.OracleClient.

System.Data.OracleClient requiert OracleInstantClient, qui sont des DLL natives. Donc, pour utiliser System.Data.OracleClient, j'ai besoin de la DLL native installée, ou dans un dossier de la variable d'environnement path.

Maintenant, le problème de base est, je n'ai pas les droits d'administrateur (entreprise portable - bêtise corporative - ne va pas changer) ...
Donc je ne peux rien installer, ni copier quoi que ce soit dans un dossier dans PATH , je ne peux pas non plus ajouter un dossier à la variable d'environnement path, je ne peux pas redémarrer/administrer IIS ou tout autre service ...

Comme test, je viens de copier oci.dll et oraociei11.dll dans le même dossier comme le WinForms .exe.
Cela a bien fonctionné. J'ai pu accéder à la base de données Oracle (SELECT * FROM COUNTRIES) sans problèmes.

Mais maintenant, j'ai besoin d'effectuer la même requête dans une solution ASP.NET. Le problème est que les fichiers ASP.NET dll sont copiés dans un dossier temporaire lors de leur exécution.

Maintenant, pour obtenir les dll à la poubelle webapp non le moins,
dans Global.asax dans

public class MvcApplication : System.Web.HttpApplication 

Je réenregistrés Init avec ceci:

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 

afin de copier la DLL native à l'emplacement supposé correct. Mais je reçois toujours l'exception DllNotFound ...

Où ou comment dois-je mettre un dll natif dans une application ASP.NET?

Je répète: je ne peux pas définir les variables d'environnement, et je ne peux pas copier les DLL dans un dossier qui est dans path. (ce qui devrait normalement résoudre le problème).

Comme vous le voyez avec les multiples occurences de

strTargetDirectory = 

J'ai essayé plusieurs, aucune des possibilités qui ont travaillé.

+0

Tout ce que vous devriez avoir à faire pour mettre la DLL dans le dossier bin de votre application. Pourquoi essayez-vous d'accéder à la DLL séparément dans votre code Init()? – RickNZ

+0

@RickNZ: Doit est bon. Mais ce n'est pas le cas. Mais je l'ai résolu maintenant. Solution ajoutée –

+0

@RickNZ: ShadowCopy copie les DLL .NET dans un autre dossier, et s'exécute à partir de là.Ainsi, les DLL natives dans le dossier bin se trouvent dans un autre dossier et ne seront pas trouvées/chargées. –

Répondre

3

Résolu.
Apparemment, il faut encore charger la DLL native après les avoir copiées dans le dossier cible.
OnInit était incorrect, c'est pour les modules HTTP.
Nous devons le faire une seule fois, donc déplacé vers Application_Start.

Voici mon code, dans le cas où tout le monde a besoin:

// 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()); –

Questions connexes