Imposta l’attributo DllImport in modo dinamico

Sto facendo uso di una dll esterna non gestita utilizzando PInvoke e l’attributo DllImport. per esempio.

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

Mi chiedo se sia ansible modificare dynamicmente i dettagli del file dll (mcs_apiD.dll in questo esempio) in qualche modo, se ad esempio volessi build contro un’altra versione di dll

Sì, questo è ansible, dovrai fare parte del lavoro che fa il marshaller P / Invoke. Caricamento della DLL e ricerca del punto di ingresso della funzione esportata. Inizia dichiarando un delegato la cui firma corrisponde alla funzione esportata:

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

Quindi usa un codice come questo:

  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); 

Un sacco di modi per sbagliare, naturalmente. Si noti che è necessario utilizzare il nome esportato effettivo dalla DLL, non si ottiene più l’aiuto dal marshaller P / Invoke per aiutare con la decorazione del nome. Utilizzare dumpbin.exe / exports nella DLL se non si è certi del nome dell’esportazione.

non puoi cambiare il nome della DLL ma puoi modificare il percorso della libreria che viene caricata (come leggendola dal registro o da un file di configurazione) e caricarla manualmente con la funzione LoadLibrary kernel32: vedi la mia risposta lì .