2010-05-12 4 views
6

J'utilise une DLL externe non gérée à l'aide de PInvoke et de l'attribut DllImport. par exemple.Attribution dynamique de l'attribut DllImport

[DllImport("mcs_apiD.dll", CharSet = CharSet.Auto)] 
private static extern byte start_api(byte pid, byte stat, byte dbg, byte ka); 

Je me demande s'il est possible de modifier les détails du fichier dll (mcs_apiD.dll dans cet exemple) dynmically d'une certaine manière, si, par exemple, je voulais construire contre une autre version dll

Répondre

2

vous pouvez Ne changez pas le nom de la DLL mais vous pouvez modifier le chemin de la bibliothèque en cours de chargement (comme en le lisant depuis le registre ou un fichier de configuration) et le charger manuellement avec la fonction LoadLibrary de kernel32: see my answer there.

+0

Ok. Mais dans mon exemple j'ai spécifié un prototype de fonction spécifique pour que je puisse correctement marsarchiser les paramètres, certaines des fonctions api ont des structures complexes en tant que paramètres. Comment ferais-je cela en travaillant de cette manière? – user226356

+0

si les paramètres changent d'une version de la DLL à l'autre, vous n'avez pas de chance avec la méthode que j'ai mentionné –

5

Oui, cela est possible, vous devrez faire une partie du travail effectué par le P/Invoke marshaller. Chargement de la DLL et recherche du point d'entrée de la fonction exportée. Commencez en déclarant un délégué dont la signature correspond à la fonction exportée:

private delegate byte start_api(byte pid, byte stat, byte dbg, byte ka); 

Ensuite, utilisez le code comme ceci:

using System.ComponentModel; 
using System.Runtime.InteropServices; 
    ... 

    static IntPtr dllHandle; 
    ... 
     if (dllHandle == IntPtr.Zero) { 
      dllHandle = LoadLibrary("mcs_apiD.dll"); 
      if (dllHandle == IntPtr.Zero) throw new Win32Exception(); 
     } 
     IntPtr addr = GetProcAddress(dllHandle, "[email protected]"); 
     if (addr == IntPtr.Zero) throw new Win32Exception(); 
     var func = (start_api)Marshal.GetDelegateForFunctionPointer(addr, typeof(start_api)); 
     var retval = func(1, 2, 3, 4); 
    ... 
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr LoadLibrary(string name); 
    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] 
    private static extern IntPtr GetProcAddress(IntPtr hModule, string name); 

Beaucoup de façons de se tromper bien sûr. Notez que vous devez utiliser le nom exporté réel de la DLL, vous ne recevez plus l'aide du marshaller P/Invoke pour aider à la décoration de nom. Utilisez dumpbin.exe/exports sur la DLL si vous ne savez pas à quoi ressemble le nom de l'exportation.

+0

en effet, avec 1 type de délégué par version de l'API DLL combinée avec GetProcAddress, vous aurez votre sortie de –

+0

Il existe un article de blog Microsoft à ce sujet sur: http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_ .aspx – Deanna