动态调用从C#非托管代码

问题描述 投票:1回答:2

总的来说,我需要能够从我不知道在编译时的任何DLL调用任何非托管函数。

所有我看到(这样https://blogs.msdn.microsoft.com/jonathanswift/2006/10/03/dynamically-calling-an-unmanaged-dll-from-net-c/)的文章建议使用委托,但我不知道在编译时哪个函数我该怎么调用,甚至它,以及它如何许多参数需要。

基本上我有等的用户输入:呼叫“的Kernel32.dll”功能“的DeleteFile”参数[“C:\ TESTFILE.TXT”]。

能否请您指点至少怎样谷歌呢? “动态”这个词并没有帮助..

任务本身是有点疯狂,只是因为它实际上是一所大学的项目。不知道它可以在现实生活中有用的..

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(?????));
c# dll pinvoke marshalling unmanaged
2个回答
3
投票

我也同意罗斯林的想法,但是当我看到“动态”和“P / Invoke的”,好老System.Reflection.Emit想到:

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

不漂亮,我知道了。只是我的$ 0.02。

警告:如果此代码将在长时间运行的应用程序中调用多次,可以考虑每次创建一个新的AppDoman和处置它,当调用完成;因为这是卸载生成的动态组件的唯一途径。


1
投票

不知道确切的最终目标是什么,但我会采取略有不同的方法。在.NET编译器都可以使用,这样你就可以动态地生成一个程序集,然后加载它,使用它的服务。所以,你的程序本质上是一个“发电机”你输入转换成代码,编译,加载,运行它。您可以使用罗斯林这一点。

© www.soinside.com 2019 - 2024. All rights reserved.