Im Gegensatz zu den Vorschlägen einiger anderer Antworten ist die Verwendung des DllImport
Attributs immer noch der richtige Ansatz.
Ich verstehe ehrlich gesagt nicht, warum Sie nicht wie alle anderen auf der Welt einen relativen Pfad zu Ihrer DLL angeben können . Ja, der Pfad, in dem Ihre Anwendung installiert wird, unterscheidet sich auf den Computern verschiedener Personen. Dies ist jedoch im Grunde eine universelle Regel für die Bereitstellung. Der DllImport
Mechanismus ist in diesem Sinne ausgelegt.
Tatsächlich ist es nicht einmal das DllImport
, was damit umgeht. Es sind die nativen Win32-DLL-Laderegeln, die die Dinge regeln, unabhängig davon, ob Sie die handlichen verwalteten Wrapper verwenden (der P / Invoke-Marshaller ruft nur auf LoadLibrary
). Diese Regeln werden hier sehr detailliert aufgeführt , aber die wichtigsten sind hier auszugsweise:
Bevor das System nach einer DLL sucht, überprüft es Folgendes:
- Wenn bereits eine DLL mit demselben Modulnamen im Speicher geladen ist, verwendet das System die geladene DLL, unabhängig davon, in welchem Verzeichnis sie sich befindet. Das System sucht nicht nach der DLL.
- Befindet sich die DLL in der Liste der bekannten DLLs für die Windows-Version, unter der die Anwendung ausgeführt wird, verwendet das System die Kopie der bekannten DLL (und gegebenenfalls die abhängigen DLLs der bekannten DLL). Das System sucht nicht nach der DLL.
Wenn SafeDllSearchMode
aktiviert (Standardeinstellung), lautet die Suchreihenfolge wie folgt:
- Das Verzeichnis, aus dem die Anwendung geladen wurde.
- Das Systemverzeichnis. Verwenden Sie die
GetSystemDirectory
Funktion, um den Pfad dieses Verzeichnisses abzurufen.
- Das 16-Bit-Systemverzeichnis. Es gibt keine Funktion, die den Pfad dieses Verzeichnisses abruft, aber es wird gesucht.
- Das Windows-Verzeichnis. Verwenden Sie die
GetWindowsDirectory
Funktion, um den Pfad dieses Verzeichnisses abzurufen.
- Das aktuelle Verzeichnis.
- Die Verzeichnisse, die in der
PATH
Umgebungsvariablen aufgeführt sind. Beachten Sie, dass dies nicht den Anwendungspfad enthält, der im Registrierungsschlüssel für Anwendungspfade angegeben ist. Der Schlüssel "App-Pfade" wird bei der Berechnung des DLL-Suchpfads nicht verwendet.
Sofern Sie Ihre DLL nicht wie eine System-DLL benennen (was Sie unter keinen Umständen tun sollten), wird die Standardsuchreihenfolge in dem Verzeichnis angezeigt, aus dem Ihre Anwendung geladen wurde. Wenn Sie die DLL während der Installation dort platzieren, wird sie gefunden. Alle komplizierten Probleme verschwinden, wenn Sie nur relative Pfade verwenden.
Einfach schreiben:
[DllImport("MyAppDll.dll")] // relative path; just give the DLL's name
static extern bool MyGreatFunction(int myFirstParam, int mySecondParam);
Wenn dies jedoch aus irgendeinem Grund nicht funktioniert und Sie die Anwendung zwingen müssen, in einem anderen Verzeichnis nach der DLL zu suchen, können Sie den Standardsuchpfad mithilfe der SetDllDirectory
Funktion ändern .
Beachten Sie, dass gemäß der Dokumentation:
Nach dem Aufruf SetDllDirectory
lautet der Standard-DLL-Suchpfad:
- Das Verzeichnis, aus dem die Anwendung geladen wurde.
- Das durch den
lpPathName
Parameter angegebene Verzeichnis .
- Das Systemverzeichnis. Verwenden Sie die
GetSystemDirectory
Funktion, um den Pfad dieses Verzeichnisses abzurufen.
- Das 16-Bit-Systemverzeichnis. Es gibt keine Funktion, die den Pfad dieses Verzeichnisses abruft, aber es wird gesucht.
- Das Windows-Verzeichnis. Verwenden Sie die
GetWindowsDirectory
Funktion, um den Pfad dieses Verzeichnisses abzurufen.
- Die Verzeichnisse, die in der
PATH
Umgebungsvariablen aufgeführt sind.
Solange Sie diese Funktion aufrufen, bevor Sie die aus der DLL importierte Funktion zum ersten Mal aufrufen, können Sie den Standardsuchpfad zum Suchen von DLLs ändern. Der Vorteil ist natürlich, dass Sie dieser Funktion, die zur Laufzeit berechnet wird, einen dynamischen Wert übergeben können. Dies ist mit dem DllImport
Attribut nicht möglich. Daher verwenden Sie dort immer noch einen relativen Pfad (nur den Namen der DLL) und verlassen sich auf die neue Suchreihenfolge, um ihn für Sie zu finden.
Sie müssen diese Funktion aufrufen. Die Erklärung sieht folgendermaßen aus:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);