Contrairement à ce que suggèrent certaines des autres réponses, l'utilisation de l'option DllImport
L'attribut est toujours l'approche correcte.
Honnêtement, je ne comprends pas pourquoi vous ne pouvez pas faire comme tout le monde dans le monde et spécifier un relatif le chemin d'accès à votre DLL. Certes, le chemin dans lequel votre application sera installée diffère selon les ordinateurs, mais il s'agit là d'une règle universelle en matière de déploiement. Le site DllImport
est conçu dans cette optique.
En fait, ce n'est même pas DllImport
qui s'en occupe. Ce sont les règles de chargement des DLL Win32 natives qui régissent les choses, que vous utilisiez ou non les enveloppes gérées pratiques (le marshaller P/Invoke appelle simplement LoadLibrary
). Ces règles sont énumérées de manière très détaillée ici mais les plus importants sont extraits ici :
Avant que le système ne 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 est exécutée, 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 du système. Utilisez le
GetSystemDirectory
pour obtenir le chemin de ce répertoire.
- Le répertoire du système 16 bits. Il n'existe pas de fonction permettant d'obtenir le chemin de ce répertoire, mais il est recherché.
- Le répertoire de Windows. Utilisez le
GetWindowsDirectory
pour obtenir le chemin de ce répertoire.
- Le répertoire actuel.
- Les répertoires qui figurent dans la liste des
PATH
variable d'environnement. Notez que cela n'inclut pas le chemin 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 des DLL.
Ainsi, à moins que vous ne donniez à votre DLL le même nom 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 à cet endroit pendant l'installation, elle sera trouvée. Tous ces problèmes compliqués disparaissent si vous utilisez simplement des chemins relatifs.
Ecris juste :
[DllImport("MyAppDll.dll")] // relative path; just give the DLL's name
static extern bool MyGreatFunction(int myFirstParam, int mySecondParam);
Mais si cela n'a 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 commande SetDllDirectory
fonction .
Notez que, selon la documentation :
Après avoir appelé SetDllDirectory
Le chemin de recherche standard des DLL est le suivant
- Le répertoire à partir duquel l'application a été chargée.
- Le répertoire spécifié par l'option
lpPathName
paramètre.
- Le répertoire du système. Utilisez le
GetSystemDirectory
pour obtenir le chemin de ce répertoire.
- Le répertoire du système 16 bits. Il n'existe pas de fonction permettant d'obtenir le chemin de ce répertoire, mais il est recherché.
- Le répertoire de Windows. Utilisez le
GetWindowsDirectory
pour obtenir le chemin de ce répertoire.
- Les répertoires qui figurent dans la liste des
PATH
variable d'environnement.
Ainsi, tant que vous appelez cette fonction avant d'appeler pour la première fois la fonction importée de la DLL, vous pouvez modifier le chemin de recherche par défaut utilisé pour localiser les DLL. L'avantage, bien sûr, c'est que vous pouvez passer une fonction dynamique à cette fonction qui est calculée au moment de l'exécution. Ce n'est pas possible avec la fonction DllImport
Vous continuerez donc à utiliser un chemin d'accès relatif (le nom de la DLL uniquement) et vous compterez sur le nouvel ordre de recherche pour la trouver pour vous.
Vous devrez P/Invoke cette fonction. La déclaration ressemble à ceci :
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);
18 votes
Il suffit de déployer la DLL dans le même dossier que l'EXE pour n'avoir rien d'autre à faire que de spécifier le nom de la DLL sans le chemin. D'autres schémas sont possibles, mais ils sont tous gênants.
2 votes
Le problème est qu'il s'agit d'une extension Excel de MS Office, donc je ne pense pas que mettre la dll dans le répertoire de l'exe soit la meilleure solution...
9 votes
Votre solution est la mauvaise. Ne placez pas de fichiers dans les dossiers Windows ou système. Ils ont choisi ces noms pour une raison : parce qu'ils sont destinés aux fichiers système de Windows. Vous ne créez pas l'un de ces dossiers parce que vous ne travaillez pas pour Microsoft dans l'équipe Windows. Rappelez-vous ce que vous avez appris à l'école maternelle sur l'utilisation sans autorisation de choses qui ne vous appartiennent pas, et placez vos fichiers ailleurs qu'à cet endroit.
0 votes
Votre solution est toujours fausse. Les applications qui se comportent bien et qui ne sont pas en fait faire des choses administratives ne devrait pas nécessiter un accès administratif. L'autre problème est que vous ne savez pas si votre application va réellement être installé dans ce dossier. Je peux le déplacer ailleurs, ou changer le chemin d'installation pendant l'installation (je fais ce genre de choses pour le plaisir, juste pour casser les applications qui se comportent mal). Le codage en dur des chemins est la quintessence du mauvais comportement, et c'est complètement inutile. Si vous utilisez le dossier de votre application, alors c'est le chemin d'accès de l'application. premier chemin dans l'ordre de recherche par défaut pour les DLL. Tout automatique.
3 votes
Le mettre dans les fichiers programmes n'est PAS constant. Les machines 64 bits ont le fichier programme (x86) à la place, par exemple.
0 votes
@Jsncrdnl, je viens de mettre ceci
Directory.SetCurrentDirectory(DLLsFolder)
Les DLLs sont chargées à la demande, donc avant d'instancier un objet, qui utilise la DLL référencée, appelez 'SetCurrentDirectory'. Une fois chargées (à l'aide de dllimport), les DLL sont déchargées lorsque le processus est terminé (ou lorsqu'un AppDomain est finalisé, le cas échéant).0 votes
Depuis que j'ai vu cette syntaxe dans csharp, je savais qu'elle posait un problème ; une question mondiale serait, comment faire :( ignorer complètement une telle implémentation et définir d'autres paramètres d'application pour indiquer que la méthode n'utilise pas DLLImport ) ;