Utilisation de Visual Studio C ++ V10, j'essaie de déterminer comment construire une DLL et résoudre un conflit de dénomination DLL. Voici les détails.
La société S expédition un produit appelé Société C expédiée une DLL appelée Idéally Société C et Société S accepterait de construire Un diagramme de la situation est le suivant: p> efficacement, j'ai besoin des deux Notez que je n'ai pas le Option pour reconstruire Je crois que les manifestes peuvent être utilisés de sorte que lorsque je construit m.exe code>. Supposons que m.exe code> est installé dans \ s \ bin \ m.exe code>. Société s statiquement liens vers une DLL appelée u.dll code>, qui est installé dans \ s \ bin \ u.dll code>. u.dll code> contient du code open source et est construit avec des options de compilateur Visual C ++ / ZC: WCHAR_T - CODE>, qui ne reconnaît pas WCHAR en tant que type natif. P > o.dll code> et publie l'API pour cette DLL et expédie une bibliothèque d'importation pour o.dll code>. Supposons que o.dll code> est installé dans \ c \ bin \ o.dll code>. o.dll code> liens statiquement vers une DLL appelée u.dll code>, qui est installé dans \ c \ bin \ u.dll code>. u.dll code> est construit sur le même code open source, mais est construit avec des options de compilateur Visual C ++ / ZC: WCHAR_T >, qui reconnaît wchar_t code> En tant que type natif. P> u.dll code> à l'aide des mêmes options Visual C ++, mais cela n'est pas possible. P> < p> m.exe code> de la société S est extensible, en ce que je peux construire ma propre dll dans non géré C ++, appelez-le nœud.dll code> que m.exe < / Code> invoquera si je fixais tout correctement. Je voudrais construire nœud.dll code> de sorte qu'il lie statilement vers o.dll code> de la société C. mais le problème est qu'une fois m.exe code > est en cours d'exécution, il a chargé la bibliothèque u.dll code> à partir de \ s \ bin code> et les symboles de \ s \ bin \ u.dll code > sont légèrement différents que ceux de \ c \ bin \ u.dll code>, car comment u.dll code> a été construit par chaque entreprise. Donc, lorsque m.exe tente> tente de charger nœud.dll code>, il échoue, car quand node.dll code> charges o.dll code>, qui nécessite u.dll code>, les symboles nécessaires à partir de \ c \ bin \ u.dll code> ne sont pas là, car Windows voit u.dll Code> Comme déjà en cours de chargement. p> \ s \ bin \ U.dll code> et \ c \ bin \ u.dll code> pour coexister dans le même espace de processus et que m.exe code> utilise sa version de u.dll code> et o.dll code> utilise sa version de u.dll code>. p> m.exe code> ou o.dll code> pour modifier la manière dont ils chargent u.dll code>. Ils viennent de tiers. La liaison statique ne peut donc pas être modifiée. Je n'ai pas non plus la possibilité d'utiliser loadlibrary code> sur o.dll code>, car il s'agit d'une bibliothèque C ++, fournie avec une bibliothèque d'importation. P> nœud.dll code> est lié statilement à o.dll, j'ai défini les choses dans le manifeste du noeud .Dll code> de sorte que o.dll code> charge sa propre copie de u.dll code> installé dans \ c \ bin \ u.dll code>. Je ne peux tout simplement pas comprendre comment faire cela. Idéalement, je voudrais ne pas modifier le manifeste de o.dll code>, mais si c'est la seule solution, je vais vivre avec ça. P> p>
4 Réponses :
Vous pouvez avoir plusieurs dlls avec le même nom de fichier Au lieu de la liaison pendant le processus de construction, vous devez Une fois que vous avez chargé le module, vous pouvez affecter chacune des fonctions nécessaires aux pointeurs de fonction, puis enveloppez-les ou utilisez le légal mais peu utilisé Syntaxe des fonctions d'appel Pointeurs comme fonctions normales ( Si vous êtes sur une version plus récente de Windows, vous pourrez peut-être utiliser des manifests DLL pour renforcer la version / la nommée autour du module et faire charger l'EXE de charger une DLL différente de celle qu'il ne le ferait généralement. Je ne connais pas exactement comment cela serait fait, bien qu'il soit documenté sur MSDN (et probablement ici aussi). P> std :: string modulename = AppPath + "\ s \ bin \ u.dll"; LOADMODULE (MODULENAME.C_STR ()) CODE>. Parce que cela est sans ambiguïté sur lequel la DLL doit être chargée, elle vous permet de charger plusieurs personnes avec le "même" nom. P>
FuncPtr (paramètres) code>). P>
Ce n'est pas une option, car je n'ai pas la capacité de reconstruire m.exe ou o.dll. Ils viennent de tiers différents.
Si l'un de ces modules utilise un chemin partiel ou absolu ou que l'on utilise un chargement dynamique, vous pourrez peut-être obtenir. Sinon, les manifestés seront votre seule chance.
Je crois que les manifestations sont le seul choix. J'aimerais savoir quoi mettre dans le manifeste pour faire fonctionner les choses. M.EXE et O.DLL sont construits à l'aide de bibliothèques importées qui chargent ensuite U.dll à l'aide des règles de chargement normales de la DLL. Chaque entreprise met sa propre version de U.DLL dans son propre répertoire bin. Lorsque M.EXE est exécuté, il récupère sa copie de U.dll. Lorsque vous écrivez un exe standard qui utilise o.dll, il récupère sa copie de u.dll.
Essayez d'utiliser LoadLibrary et GetProcAddress. Cela nécessitera une restructuration de votre code pour utiliser des pointeurs de fonction partout. Voir: P>
Ce n'est pas une option, car je n'ai pas la capacité de reconstruire m.exe ou o.dll. Ils viennent de tiers différents.
Vous pouvez résoudre la DLL source programmatique à Runtiome à l'aide de l'option / DelayLoad Linker Option (Linker / Entrée / Délais DLLS chargés dans les propriétés du projet VS) avec un crochet personnalisé. Dans l'un de vos fichiers source, vous devez définir et enregistrer une fonction de crochet de retard de connexion. Dans le gestionnaire de notification DLINoteProLoadlibrary DLINOTEPRELODLibrary de la fonction de crochet, appelez simplement LoadLibrary avec un chemin explicite de la DLL souhaitée, puis transmettez le HMODULE de DLL au code de diffusion. Le code de retard de retard résoudra les fonctions importées à la DLL que vous le donnez, que, si une autre DLL du même nom est déjà chargée dans le processus.
Off le sommet de ma tête, votre crochet ressemblera à ceci (où myCustMoadLibrary doit être remplacé par code qui appelle Chargement de chargement avec le chemin complet de la DLL souhaitée dans le cas contradictoire, ou juste le nom de fichier non qualifié autrement): P>
#include <delayimp.h>
FARPROC WINAPI MyDliNotifyHook( unsigned dliNotify, PDelayLoadInfo pdli )
{
if( dliNotify == dliNotePreLoadLibrary )
return (FARPROC)MyCustomLoadLibrary( pdli->szDll );
return NULL;
}
extern "C" PfnDliHook __pfnDliNotifyHook2 = MyDliNotifyHook;
Cela fonctionne uniquement si nœud.dll est celui qui se trouve à la DLL conflictuelle. Après avoir réaffecté votre question, je vois que vous dites que c'est l'une des DLL à charge qui relie la DLL contradictoire. Dans ce cas, vous devrez résoudre le tableau d'adresses d'importation de la DLL dépendante de manière programmatique. Ce n'est pas difficile à faire, mais il est trop complexe pour décrire les étapes ici.
"Résoudre le tableau d'adresses d'importation de la DLL dépendante Programmatiquement": pouvez-vous donner un pointeur, nous pouvons en savoir plus?
Il y a deux cas: le cas où le chargeur peut résoudre avec succès toutes les importations (bien qu'à la mauvaise DLL); et le cas où le chargeur ne peut pas résoudre les importations. Si votre cas est le premier, je peux fournir des indications. Si votre cas est ce dernier, vous devez reproduire essentiellement le code Windows Loader (résoudre les importations et appliquer des fixes, puis appeler la fonction du point d'entrée). Il y a une petite documentation précieuse et je ne connais aucune source d'information publique. Ce n'est pas pour les faibles de cœur, mais c'est possible: je l'ai fait avec succès.
"Si votre cas est le premier, je peux fournir des indications". Oui, s'il vous plaît monsieur.
Harper, je viens de réaliser que vous n'êtes pas le PO. Puisque cela est hors-thème pour l'OP, veuillez commencer votre propre question.
@ Owen-Wengerd - Mon cas est ce dernier. Le chargeur ne peut pas résoudre toutes les importations. Certains sont les mêmes, et certains sont différents. Idéalement, parce que M.Exe et o.dll sont construits par différents tiers et que je souhaite obtenir un soutien de chacun des tiers, je veux vraiment que M.EXe utilise la mise en œuvre de U.dll qu'elle fournit et avoir O.dll pour utiliser la mise en œuvre de U.dll qu'elle fournit. Comme je l'ai dit dans le poste d'origine, je pense que cela peut être fait avec des manifestes. Je ne peux tout simplement pas comprendre la manifeste.
@Irv J'ai très peu d'expérience en utilisant des manifestes car mon travail nécessite généralement une prise en charge des anciennes versions de Windows. Cela pourrait fonctionner et en théorie devrait fonctionner, mais j'ai bien peur de ne pouvoir offrir aucune aide concrète avec des manifestations.
Vous avez de la chance que u.dll est open source. Vous devrez créer une version prenant en charge em> le Mind You, s'il existe des variables globales ou / zc: wchar_t - code> et / zc: wchar_t code> fonctions. La première option définit simplement wchar_t - code> comme non signé court code>. Vous obtiendrez une tonne d'avertissements de liaison pour les symboles en double, pour chaque fonction qui ne dispose pas d'un argument wchar_t code>, mais sinon vous venez de vous retrouver avec une dll plus nombreuse. P>
statiques code> à l'aide de wchar_t code>, vous aurez également deux copies de ceux-ci. Mais vous auriez le même effet que si vous chaisez deux copies de u.dll code> dans un processus. P>
DLL, dll de partout! (Désolé, je ne pouvais pas m'en empêcher) Bonjour et bienvenue.
Essentiellement, le problème est que
o.dll code> dans son IAT spécifie qu'il s'agit de liens contreu.dll code>, non qualifié.