2010-03-30 22 views
2

Deux programmes Delphi doivent charger foo.dll, qui contient du code qui injecte un certificat client-auth dans une requête SOAP. foo.dll réside dans c: \ fooapp \ foo.dll et est normalement chargé par c: \ fooapp \ foo.exe. Cela fonctionne bien. L'autre programme a besoin de la même fonctionnalité, mais il réside dans c: \ program files \ unwantedstepchild \ sadapp.exe. Les deux aps chargent la DLL avec ce code:Delphi LoadLibrary A défaut de trouver un autre répertoire DLL - de bonnes options?

FOOLib := LoadLibrary('foo.dll'); 
... 
If FOOLib <> 0 then 
begin 
    FOOProc := GetProcAddress(FOOLib , 'xInjectCert'); 
    FOOProc(myHttpRequest, Data, CertName); 
end; 

Il fonctionne très bien pour foo.exe, comme dll est là. sadapp.exe ne parvient pas à charger la bibliothèque, FOOLib a donc la valeur 0 et le reste n'est jamais appelé. Le programme sadapp.exe échoue donc silencieusement à injecter le cert, et lorsque nous testons contre la production, le cert est manquant, la connexion échoue. Évidemment, nous devrions avoir entièrement qualifié le chemin vers la DLL. Sans entrer dans beaucoup de détails, certains aspects du test ont masqué ce problème jusqu'à récemment, et il est maintenant trop tard pour corriger le code, car cela nécessiterait un test de régression complet, et il n'y a pas de temps pour cela.

Puisque nous nous sommes peints dans un coin, j'ai besoin de savoir s'il y a des options que j'ai oubliées. Bien que nous ne puissions pas changer le code (pour cette version), nous pouvons modifier le programme d'installation. J'ai trouvé que placer c: \ fooapp dans le chemin fonctionne. Tout comme l'ajout d'une seconde copie de foo.dll directement dans c: \ program files \ unwantedstepchild. c: \ fooapp \ foo.exe sera toujours en cours d'exécution pendant que sadapp.exe est en cours d'exécution, donc j'espérais que Windows le trouverait de cette façon, mais apparemment pas. Existe-t-il un moyen de dire à Windows que je veux vraiment cette même DLL? Peut-être un manifeste ou quelque chose? C'est le genre de "balle magique" que je cherche. Je sais que je peux:

  1. Modifier le chemin de Windows, probablement dans le programme d'installation. C'est moche.
  2. Ajoutez une deuxième copie de la DLL, directement dans le dossier unwantedstepchild. Aussi moche
  3. Retardez le projet pendant que nous codons et testons un correctif approprié. Inacceptable.
  4. Autre?

Merci pour toute orientation, en particulier avec "Autre". Je comprends que ce problème n'est pas nécessairement spécifique à Delphi. Merci!

+0

1 et 2 sont acceptables pour moi. Vous avez dit que c'est seulement pour cette version. Donc, regardez-le comme une solution temporaire. Vous pouvez le faire correctement avec la prochaine version. À mon avis, vous n'avez pas besoin de perdre votre temps avec ça. 2 est probablement mieux parce que vous pouvez le désinstaller sans problèmes. – Runner

+0

Vous considérez que vos options 1 et 2 sont «moche». au contraire, ce sont des techniques standard et pas moche du tout. D'un autre côté, vous dites "Evidemment, nous devrions avoir complètement qualifié le chemin vers la DLL". ** Absolument pas! ** Ce que vous proposez ici vraiment *** serait UGLY ***. Tout le monde n'aime pas polluer leur structure C: \ folder avec votre dossier 'fooapp'. Pourtant, en codant dur un chemin, vous empêchez quelqu'un de faire autre chose. _Les utilisateurs devraient être capables d'installer n'importe quel emplacement ** ou n'importe quel lecteur ** et avoir toujours une application fonctionnelle. –

+1

Vous avez une 4ème option: installez DLL dans un dossier partagé sur le chemin Windows. Le "dossier système" de Windows est candidat (mais vous pouvez utiliser et configurer votre propre dossier si vous le souhaitez). Le dossier partagé a une petite mise en garde: cela signifie que toutes les applications utilisent la même version de la DLL. Et peut conduire à un problème connu sous le nom "DLL Hell" (lecture suggérée). Ceci est généralement résolu en plaçant une version spécifique de la DLL dans le dossier de l'application (c'est-à-dire votre option 2). Donc, naturellement, je suggère que l'option 2 est probablement la meilleure solution provisoire; puisque c'est quelque chose qui pourrait arriver de toute façon. –

Répondre

9

La documentation MSDN pour LoadLibrary vous indique exactement où Windows recherchera les DLL. Vous devez coder en dur le chemin d'accès à la DLL, le placer dans le même dossier que votre application ou le placer dans l'un de ces emplacements de recherche par défaut à partir des documents LoadLibrary.

+0

Merci - c'est un bon article, et je souffre apparemment de Delphi Myopia, car j'oublie de vérifier MSDN. Fait intéressant, MSDN affirme: "Si lpFileName n'inclut pas de chemin et qu'il existe plusieurs modules chargés avec le même nom de base et l'extension, la fonction renvoie un descripteur au module qui a été chargé en premier." Je m'attendrais à ce que cela m'aurait sauvé ici, mais apparemment, il y a plus que ça. Même si foo.exe a chargé foo.dll, SadApp.exe n'est pas en mesure de tirer parti de cela. –

+0

+1 Loadlibrary est mon arme de prédilection, et par conséquent, quelle aurait été ma suggestion. –

+0

Le problème s'est résolu, en raison de ma relecture des documents MSDN. La clé est que le «répertoire courant» est recherché en plus de «Le répertoire à partir duquel l'application a été chargée». Ok, alors pourquoi/quand seraient-ils différents? C'est la clé ici. Normalement, l'utilisateur lance SadApp à partir d'un menu dans foo.exe. Mais il y a aussi une icône qui peut être utilisée pour le lancer indépendamment. C'est là que ça échouait. Lorsqu'il est lancé "normalement" via le menu de l'application principale, le "répertoire courant" est c: \ fooapp, et la DLL est trouvée et chargée. Bingo! Maintenant, c'est juste un problème de procédure/formation. –

0

Ou vous pouvez simplement modifier la variable d'environnement "path" et placer le chemin d'accès à la DLL là-bas. Dans ce cas, ajouter ;c:\fooapp au chemin devrait être suffisant. Étant donné que les modifications d'environnement d'un parent affectent un enfant, vous pouvez également créer une application de chargement qui ajuste la variable d'environnement its puis génère une application dans votre application.

1

Ce n'est pas exactement une solution à la question posée, mais il me aurait aidé, quand je stumpled sur cette question:

Vous pouvez étendre le chemin de recherche pour LoadLibrary via SetDllDirectory.

De MSDN-Doku:

Le chemin de recherche peut être modifié en utilisant la fonction SetDllDirectory. Cette solution est recommandée au lieu d'utiliser SetCurrentDirectory ou en codant en dur le chemin d'accès complet à la DLL.

vous auriez besoin d'ajouter une ligne avant votre appel LoadLibrary (s):

SetDllDirectory(PChar('c:\fooapp'));