Contrariamente a las sugerencias de algunas de las otras respuestas, el uso del DllImport
atributo sigue siendo el enfoque correcto.
Sinceramente, no entiendo por qué no puedes hacer lo mismo que todos los demás en el mundo y especificar una ruta relativa a tu DLL. Sí, la ruta en la que se instalará su aplicación difiere en las computadoras de diferentes personas, pero esa es básicamente una regla universal cuando se trata de la implementación. El DllImport
mecanismo está diseñado con esto en mente.
De hecho, ni siquiera DllImport
eso lo maneja. Son las reglas de carga de DLL de Win32 nativas las que gobiernan las cosas, independientemente de si está utilizando los prácticos contenedores administrados (el encargado de invocación P / Invoke solo llama LoadLibrary
). Estas reglas se enumeran con gran detalle aquí , pero las importantes se extraen aquí:
Antes de que el sistema busque una DLL, verifica lo siguiente:
- Si una DLL con el mismo nombre de módulo ya está cargada en la memoria, el sistema usa la DLL cargada, sin importar en qué directorio se encuentre. El sistema no busca la DLL.
- Si la DLL está en la lista de DLL conocidas para la versión de Windows en la que se ejecuta la aplicación, el sistema usa su copia de la DLL conocida (y las DLL dependientes de la DLL conocida, si las hay). El sistema no busca la DLL.
Si SafeDllSearchMode
está habilitado (el valor predeterminado), el orden de búsqueda es el siguiente:
- El directorio desde el que se cargó la aplicación.
- El directorio del sistema. Use la
GetSystemDirectory
función para obtener la ruta de este directorio.
- El directorio del sistema de 16 bits. No hay ninguna función que obtenga la ruta de este directorio, pero se busca.
- El directorio de Windows. Use la
GetWindowsDirectory
función para obtener la ruta de este directorio.
- El directorio actual.
- Los directorios que se enumeran en la
PATH
variable de entorno. Tenga en cuenta que esto no incluye la ruta por aplicación especificada por la clave de registro de rutas de aplicaciones. La clave de Rutas de aplicación no se usa al calcular la ruta de búsqueda de DLL.
Entonces, a menos que esté nombrando su DLL de la misma manera que una DLL del sistema (lo que obviamente no debería hacer, nunca, bajo ninguna circunstancia), el orden de búsqueda predeterminado comenzará a buscar en el directorio desde el que se cargó su aplicación. Si coloca la DLL allí durante la instalación, se encontrará. Todos los problemas complicados desaparecen si solo usa rutas relativas.
Solo escribe:
[DllImport("MyAppDll.dll")] // relative path; just give the DLL's name
static extern bool MyGreatFunction(int myFirstParam, int mySecondParam);
Pero si eso no funciona por alguna razón, y necesita forzar a la aplicación a buscar en la DLL un directorio diferente, puede modificar la ruta de búsqueda predeterminada utilizando la SetDllDirectory
función .
Tenga en cuenta que, según la documentación:
Después de llamar SetDllDirectory
, la ruta de búsqueda estándar de DLL es:
- El directorio desde el que se cargó la aplicación.
- El directorio especificado por el
lpPathName
parámetro.
- El directorio del sistema. Use la
GetSystemDirectory
función para obtener la ruta de este directorio.
- El directorio del sistema de 16 bits. No hay ninguna función que obtenga la ruta de este directorio, pero se busca.
- El directorio de Windows. Use la
GetWindowsDirectory
función para obtener la ruta de este directorio.
- Los directorios que se enumeran en la
PATH
variable de entorno.
Por lo tanto, siempre que llame a esta función antes de llamar a la función importada de la DLL por primera vez, puede modificar la ruta de búsqueda predeterminada utilizada para ubicar las DLL. El beneficio, por supuesto, es que puede pasar un valor dinámico a esta función que se calcula en tiempo de ejecución. Eso no es posible con el DllImport
atributo, por lo que aún usará una ruta relativa (solo el nombre de la DLL) allí, y dependerá del nuevo orden de búsqueda para encontrarlo.
Tendrás que P / Invocar esta función. La declaración se ve así:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);