In general I need to be able to invoke any unmanaged function from any DLL which I don't know at the compile time.
All the articles I seen (like this https://blogs.msdn.microsoft.com/jonathanswift/2006/10/03/dynamically-calling-an-unmanaged-dll-from-net-c/) suggest using delegates but I don't know at the compile time which function I gonna invoke and even which and how many parameters it requires.
Basically I have a user input like: call "Kernel32.dll" function "DeleteFile" arguments ["C:\testfile.txt"].
Could you please advice at least how to google it? The word "dynamically" doesn't help..
The task itself is a bit crazy just because actually it's a university project. Not sure it can be useful in real life..
var dll = "kernel32.dll";
var fun = "DeleteFile";
var args = new object[] { "C:\\dev\\test.txt" };
IntPtr pDll = NativeMethods.LoadLibrary(dll);
IntPtr pFun = NativeMethods.GetProcAddress(pDll, fun);
// How can I call it in a different way, without having a delegate?
Marshal.GetDelegateForFunctionPointer(pFun, typeof(?????));
I also agree with idea of Roslyn, but when I see "Dynamic" and "P/Invoke", good old System.Reflection.Emit
comes to mind:
var asmName = new AssemblyName("Win32");
var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run);
var modBuilder = asmBuilder.DefineDynamicModule("Win32", emitSymbolInfo: false);
var typeBuilder = modBuilder.DefineType("Win32.User32", TypeAttributes.Class | TypeAttributes.Public);
// Optional: Use if you need to set properties on DllImportAttribute
var dllImportCtor = typeof(DllImportAttribute).GetConstructor(new Type[] { typeof(string) });
var dllImportBuilder = new CustomAttributeBuilder(dllImportCtor, new object[] { "user32.dll" });
var pinvokeBuilder = typeBuilder.DefinePInvokeMethod(
name: "ShowMessageBox",
dllName: "user32.dll",
entryName: "MessageBoxW",
attributes: MethodAttributes.Static | MethodAttributes.Public,
callingConvention: CallingConventions.Standard,
returnType: typeof(int), // typeof(void) if there is no return value.
// TODO: Construct this array from user input somehow:
parameterTypes: new Type[] { typeof(IntPtr), typeof(string), typeof(string), typeof(uint) },
nativeCallConv: CallingConvention.Winapi,
nativeCharSet: CharSet.Unicode);
pinvokeBuilder.SetCustomAttribute(dllImportBuilder);
Type user32Type = typeBuilder.CreateType();
const uint MB_YESNOCANCEL = 3;
user32Type
.GetMethod("ShowMessageBox", BindingFlags.Static | BindingFlags.Public)
// TODO: User input goes here:
.Invoke(null, new object[] { IntPtr.Zero, "Message Text", "Message Caption", MB_YESNOCANCEL });
Not pretty, I know. Just my $0.02.
WARNING: If this code is going to be called multiple times in a long running application, consider creating a new AppDoman
each time, and disposing it when call is done; because this is the only way to unload generated dynamic assembly.