68 votes

Les DLL non gérées ne se chargent pas sur le serveur ASP.NET

Cette question concerne un site Web ASP.NET, initialement développé en VS 2005 et maintenant en VS 2008.

Ce site Web utilise deux DLL externes non gérées qui ne sont pas .NET. Je ne dispose pas du code source pour les compiler et je dois les utiliser telles quelles.

Ce site web fonctionne bien à partir de Visual Studio, en localisant et en accédant correctement à ces DLL externes. Cependant, lorsque le site Web est publié sur un serveur Web (exécutant IIS6 et ASP.NET 2.0) plutôt que sur le PC de développement, il ne peut pas localiser et accéder à ces DLL externes, et j'obtiens l'erreur suivante :

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

Les DLL externes sont situées dans le répertoire bin du site Web, avec les DLL gérées qui les enveloppent et toutes les autres DLL du site Web.

Une recherche sur ce problème révèle que de nombreuses autres personnes semblent avoir le même problème d'accès aux DLL externes non.NET à partir de sites Web ASP.NET, mais je n'ai pas trouvé de solution qui fonctionne.

J'ai essayé ce qui suit :

  • Exécuter DEPENDS pour vérifier les dépendances afin d'établir que les trois premières sont dans le répertoire System32 dans le chemin, le dernier est dans le cadre .NET 2 Framework.
  • J'ai mis les deux DLL et leurs dépendances dans System32 et redémarré le serveur, mais le site web ne pouvait toujours pas ne pouvait pas charger ces DLLs externes.
  • J'ai donné les droits complets à ASPNET, IIS_WPG et IUSR (pour ce serveur) sur le répertoire bin du site web et j'ai reboosté le site. le répertoire bin du site web et redémarré, mais le site web ne pouvait toujours pas charger ces DLL externes.
  • J'ai ajouté les DLL externes en tant qu'éléments existants aux projets et j'ai configuré leur propriété "Copy to Output" à "Copy Always", et le site web ne trouve toujours pas les DLLs.
  • J'ai également défini leur propriété "Build Action" sur "Embedded resource". le site Web ne trouve toujours pas les DLL.

Toute aide pour résoudre ce problème serait grandement appréciée !

48voto

onedozenbagels Points 1192

Cela se produit parce que les dlls gérées sont copiées à l'envers dans un emplacement temporaire sous le répertoire .NET Framework. Voir http://msdn.microsoft.com/en-us/library/ms366723.aspx pour les détails.

Malheureusement, les dll non gérées ne sont PAS copiées et le processus ASP.NET ne pourra pas les trouver lorsqu'il devra les charger.

Une solution simple consiste à placer les dll non gérées dans un répertoire qui se trouve dans le chemin d'accès du système (tapez "path" à la ligne de commande pour voir le chemin d'accès de votre machine) afin qu'elles puissent être trouvées par le processus ASP.NET. Le répertoire System32 est toujours dans le chemin, donc y placer les dlls non gérées fonctionne toujours, mais je recommanderais d'ajouter un autre dossier au chemin et d'y ajouter les dlls pour éviter de polluer le répertoire System32. L'inconvénient majeur de cette méthode est que vous devez renommer les dll non gérées pour chaque version de votre application et vous pouvez rapidement avoir votre propre enfer de dll.

4 votes

Cette réponse est meilleure que la réponse acceptée, car elle explique pourquoi vous voulez faire cela.

0 votes

D'après mon expérience, lorsque je crée un nouveau répertoire, que je l'ajoute à PATH et que j'y place la DLL, elle est trouvée sans problème lors d'une exécution locale. Cependant, ce n'est pas le cas lorsqu'il est hébergé sur IIS - la DLL n'est trouvée que si elle se trouve dans /Windows/System32. Est-ce que IIS utilise peut-être une variable différente pour le chemin d'accès dans certains cas ?

42voto

Matt Woodard Points 553

Au lieu de placer la dll dans un dossier qui se trouve déjà dans le chemin (comme system32), vous pouvez modifier la valeur du chemin dans votre processus en utilisant le code suivant

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

Ensuite, lorsque LoadLibrary essaie de trouver la DLL non gérée, il analyse également searchPath. Cela peut être préférable à la création d'un désordre dans System32 ou d'autres dossiers.

4 votes

Ne fonctionne qu'avec PInvoke. Si vous utilisez un assemblage en mode mixte, les DLL sont liées (et échouent) avant l'exécution de tout code.

21voto

Matt Points 410

Essayez de placer les dlls dans le répertoire \System32\Inetsrv répertoire. Il s'agit du répertoire de travail de IIS sur Windows Server.

Si cela ne fonctionne pas, essayez de placer les dll dans le répertoire System32 et les fichiers de dépendance dans le répertoire Inetsrv.

3 votes

Voici une réponse sans avoir besoin de polluer le dossier system32 : stackoverflow.com/a/4598747/92756

9 votes

Au lieu de cela, vous pouvez désactiver le ShadowCopying en ajoutant <hostingEnvironment shadowCopyBinAssemblies="false"/> sur le web.config, à condition que vous ne modifiez pas les binaires dans l'application en direct.

0 votes

Je me suis brûlé en faisant une copie de ma DLL et en la mettant dans System32 parce que je l'avais oubliée, et ensuite j'avais la mauvaise version de Microsoft.Azure.Documents.ServiceInterop.dll chargée pour mon projet, ce qui a entraîné des erreurs locales bizarres de queryRanges[0].isMinInclusive lorsque j'ai essayé de me connecter à la base de données. Ma solution a été de m'assurer que l'identité de mon IIS DefaultAppPool local était mon utilisateur local. Voir aussi : github.com/Azure/azure-documentdb-dotnet/issues/267

12voto

En complément de la réponse de Matt, voici ce qui a finalement fonctionné pour moi sur un serveur 2003 64 bits / IIS 6 :

  1. vérifiez que vos dlls / asp.net sont de la même version (32 / 64 bit)
  2. Mettez les dlls non gérées dans le répertoire inetsrv (notez que dans Windows 64 bit, ceci est sous syswow64, même si le répertoire sys32/inetsrv est créé).
  3. Laissez les dlls gérées dans /bin
  4. Assurez-vous que les deux ensembles de dll ont les droits de lecture/exécution.

6voto

Arnout Points 2278

Jetez un coup d'œil avec FileMon o ProcMon et filtrer sur les noms des DLLs problématiques. Cela vous montrera quels répertoires sont analysés à la recherche des DLL, et les éventuels problèmes de permission.

1 votes

ProcMon est extrêmement utile pour connaître les dépendances et savoir ce qu'une certaine DLL ne peut pas charger.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X