Contrairement aux suggestions de certaines des autres réponses, l'utilisation de l' DllImport
attribut reste la bonne approche.
Honnêtement, je ne comprends pas pourquoi vous ne pouvez pas faire comme tout le monde dans le monde et spécifier un chemin relatif vers votre DLL. Oui, le chemin dans lequel votre application sera installée diffère sur les ordinateurs de différentes personnes, mais c'est fondamentalement une règle universelle en matière de déploiement. Le DllImport
mécanisme est conçu dans cet esprit.
En fait, ce n'est même pas cela DllImport
qui le gère. Ce sont les règles de chargement de la DLL Win32 native qui régissent les choses, que vous utilisiez ou non les wrappers gérés pratiques (le marshaller P / Invoke appelle simplement LoadLibrary
). Ces règles sont énumérées en détail ici , mais les plus importantes sont extraites ici:
Avant que le système recherche une DLL, il vérifie les éléments suivants:
- Si une DLL portant le même nom de module est déjà chargée en mémoire, le système utilise la DLL chargée, quel que soit le répertoire dans lequel elle se trouve. Le système ne recherche pas la DLL.
- Si la DLL figure dans la liste des DLL connues pour la version de Windows sur laquelle l'application s'exécute, le système utilise sa copie de la DLL connue (et les DLL dépendantes de la DLL connue, le cas échéant). Le système ne recherche pas la DLL.
Si SafeDllSearchMode
est activé (par défaut), l'ordre de recherche est le suivant:
- Le répertoire à partir duquel l'application a été chargée.
- Le répertoire système. Utilisez la
GetSystemDirectory
fonction pour obtenir le chemin de ce répertoire.
- Le répertoire système 16 bits. Aucune fonction n'obtient le chemin de ce répertoire, mais il est recherché.
- Le répertoire Windows. Utilisez la
GetWindowsDirectory
fonction pour obtenir le chemin de ce répertoire.
- Le répertoire actuel.
- Les répertoires répertoriés dans la
PATH
variable d'environnement. Notez que cela n'inclut pas le chemin d'accès par application spécifié par la clé de registre App Paths. La clé App Paths n'est pas utilisée lors du calcul du chemin de recherche DLL.
Ainsi, à moins que vous ne nommiez votre DLL de la même manière qu'une DLL système (ce que vous ne devriez évidemment pas faire, jamais, en aucune circonstance), l'ordre de recherche par défaut commencera à chercher dans le répertoire à partir duquel votre application a été chargée. Si vous placez la DLL là pendant l'installation, elle sera trouvée. Tous les problèmes compliqués disparaissent si vous utilisez simplement des chemins relatifs.
Ecrivez:
[DllImport("MyAppDll.dll")] // relative path; just give the DLL's name
static extern bool MyGreatFunction(int myFirstParam, int mySecondParam);
Mais si cela ne fonctionne pas pour une raison quelconque et que vous devez forcer l'application à rechercher la DLL dans un autre répertoire, vous pouvez modifier le chemin de recherche par défaut à l'aide de la SetDllDirectory
fonction .
Notez que, selon la documentation:
Après l'appel SetDllDirectory
, le chemin de recherche standard de la DLL est:
- Le répertoire à partir duquel l'application a été chargée.
- Le répertoire spécifié par le
lpPathName
paramètre.
- Le répertoire système. Utilisez la
GetSystemDirectory
fonction pour obtenir le chemin de ce répertoire.
- Le répertoire système 16 bits. Aucune fonction n'obtient le chemin de ce répertoire, mais il est recherché.
- Le répertoire Windows. Utilisez la
GetWindowsDirectory
fonction pour obtenir le chemin de ce répertoire.
- Les répertoires répertoriés dans la
PATH
variable d'environnement.
Ainsi, tant que vous appelez cette fonction avant d'appeler la fonction importée de la DLL pour la première fois, vous pouvez modifier le chemin de recherche par défaut utilisé pour localiser les DLL. L'avantage, bien sûr, est que vous pouvez transmettre une valeur dynamique à cette fonction qui est calculée au moment de l'exécution. Ce n'est pas possible avec l' DllImport
attribut, donc vous utiliserez toujours un chemin relatif (le nom de la DLL uniquement) là-bas, et comptez sur le nouvel ordre de recherche pour le trouver pour vous.
Vous devrez P / Invoquer cette fonction. La déclaration ressemble à ceci:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);