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

C# 从C动态调用非托管代码#,c#,dll,pinvoke,marshalling,unmanaged,C#,Dll,Pinvoke,Marshalling,Unmanaged,一般来说,我需要能够从编译时不知道的任何DLL调用任何非托管函数 我看到的所有文章(像这样)都建议使用委托,但我不知道在编译时调用哪个函数,甚至不知道它需要哪些参数和多少参数 基本上我有一个用户输入,比如:调用“Kernel32.dll”函数“DeleteFile”参数[“C:\testfile.txt”] 请你至少建议一下如何用谷歌搜索它好吗?“动态”这个词没用 这项任务本身有点疯狂,因为它实际上是一个大学项目。我不确定它在现实生活中是否有用 var dll = "kernel32.dll";

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

我看到的所有文章(像这样)都建议使用委托,但我不知道在编译时调用哪个函数,甚至不知道它需要哪些参数和多少参数

基本上我有一个用户输入,比如:调用“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(?????));

不确定最终目标是什么,但我会采取稍微不同的方法。在.NET中,编译器是一种可以使用的服务,因此您可以动态生成程序集,然后加载并使用它。所以你的程序本质上是一个“生成器”,你把输入翻译成代码,编译,加载,运行。你可以用roslyn来做这件事。

我也同意roslyn的想法,但是当我看到“动态”“p/Invoke”时,我想到了一个好的
系统。反射。发射:

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/COD>,并在调用完成时处理它。因为这是卸载生成的动态程序集的唯一方法。

最终目标只是调用非托管DLL而不描述委托,因为我不知道函数签名。我同意这种方法。您最初解释它的方式在许多层面上都是一个巨大的安全缺陷。Net中的任何内容都不允许您执行可能导致堆栈溢出的操作。除非您知道本机方法的参数和类型,否则无法动态执行此操作。你希望你的用户提供并知道这一点吗?是的,用户实际上是程序员,因为我创建了一个编译器。。问题是,用户可以在我的C#运行时之外执行任何WinAPI调用可能重复的@KeithNicholas,因为这个问题看起来更“动态”。所以这确实是重复的,但问题并没有完全解决。我甚至可以让用户提供参数类型列表,但我无法在运行时创建“非泛型”委托..非常感谢George!这正是我一直在寻找的!