2010-03-09 19 views
10

Tengo una aplicación existente que P/invoca a una DLL que reside en el mismo directorio que la propia aplicación.Ruta de búsqueda DLL dinámica de P/Invoke

Ahora (debido a que Canon produce una de las API más complicadas), necesito admitir dos versiones de esta API y determinar en tiempo de ejecución cuál debo usar (antigua o nueva). Dado que los archivos DLL tienen el mismo nombre (el primero carga otros archivos DLL con los mismos nombres, así que el cambio de nombre del primero no me ayudará). Debo guardarlos en directorios diferentes.

De ahí mi pregunta: ¿qué opciones tengo para controlar qué directorio utiliza la DLL dada en una declaración DllImport?

creo que puedo empezar por intentar cualquiera de estas dos ideas:

1) el uso "SetDllDirectory" para establecer mi directorio deseado antes de hacer el primer P/Invoke y luego reiniciarlo después.

2) Cargue la DLL deseada manualmente usando "LoadLibraryEx" y espero que eso sea suficiente.

¿Pero hay algo más ".NET: ish way" para probar primero?

ACTUALIZACIÓN: Me doy cuenta de que puedo rellenar todo el acceso a los archivos DLL en dos ensamblados .Net separados y luego colocar cada uno de ellos en un directorio separado con los archivos API correspondientes. Luego puedo cargar el ensamblado .Net apropiado dinámicamente y la carga de la DLL correcta ocurrirá automáticamente. ¿Alguna razón que no debería funcionar?

Puedo pensar en una: ¿cómo voy a depurar esto? ¿Es posible decirle a Visual Studio que un ensamblado (contenido en mi solución) se colocará en un subdirectorio y se depurará desde allí?

Respuesta

9

Mis condolencias, he visto una de las API y fue hecho malísimos. El problema más grande es que tendrá que ser capaz de convencer a Windows para encontrar la DLL. No estarán en su directorio .exe por lo que el valor predeterminado no funcionará. Usar SetDllDirectory() funcionaría, usando Environment.CurrentDirectory también. LoadLibrary no puede funcionar, el Marshaller P/Invoke usará LoadLibrary.

Si se trata de una opción, puede usar nombres diferentes para las dos declaraciones P/Invocar, utilizando diferentes argumentos para el constructor DllImport() y utilizando el atributo EntryPoint. No suena como que va a volar.

+1

Por el momento, le doy un +1 por sus condolencias, realmente lo necesitaba, habiendo estado expuesto a sus API varias veces durante los últimos seis años con desastres cada vez ... –

1

Su primera opción (P/Invoke con SetDllDirectory) es la opción que personalmente prefiero. Desafortunadamente, no hay una forma de ".NETish" para manejar la carga de archivos DLL nativos ... lo cual tiene sentido.

2

Creo que la segunda opción funcionará, pero requerirá escribir una gran cantidad de código para administrar la carga dll en .net.

Primero, uno podría funcionar también, pero a mí tampoco me gusta.

Aquí está mi sugerencia: puede especificar ruta completa (y puede ser relativa) en DllImport [DllImport(@"C:\dll\a32.dll"]

+0

El problema es el directorio en el que se ejecuta la DLL, no la carga de las DLL en sí, creo. – Tanzelax

Cuestiones relacionadas