从 C# 方法,如何调用和运行 DLL,其中 DLL 名称来自 String 变量?

Posted

技术标签:

【中文标题】从 C# 方法,如何调用和运行 DLL,其中 DLL 名称来自 String 变量?【英文标题】:from a C# method, how to call and run a DLL, where the DLL name comes from a String variable? 【发布时间】:2012-10-10 15:16:10 【问题描述】:

我是 C#.NET 的新手。我正在编写一个需要调用和运行 DLL 文件的方法,其中 DLL 文件名来自 String 变量-

String[] spl;

String DLLfile = spl[0];

如何导入此 DLL 并从 DLL 中调用函数以获取返回值?我尝试了以下方式..

String DLLfile = "MyDLL.dll";

[DllImport(DLLfile, CallingConvention = CallingConvention.StdCall)]

但它不起作用,因为字符串应该是 'const string' 类型,而 'const string' 不支持变量。请帮我详细的程序。谢谢。

【问题讨论】:

DLL 的名称是否必须包含在字符串中?这似乎很危险,这样做的正当理由很少。 这个 dll 是另一个 .NET 程序集吗?或者可能是一个 c++ dll?甚至是 COM dll?。 @Ramhound 这样做的原因是您可以指定 DLL 的完整路径。否则,您将依赖于库搜索顺序。这是危险的。指定完整路径是避免危险的方法! 首先,请编辑您的问题,而不是在 cmets 中发布代码。 然后启动 Visual Studio 命令提示符并使用 DUMPBIN 获取 DLL 导出的函数列表。例如。 DUMPBIN /exports ABC.dll。您也可以为此使用Dependency Walker。 【参考方案1】:

对于本机 DLL,您可以创建以下静态类:

internal static class NativeWinAPI

    [DllImport("kernel32.dll")]
    internal static extern IntPtr LoadLibrary(string dllToLoad);

    [DllImport("kernel32.dll")]
    internal static extern bool FreeLibrary(IntPtr hModule);

    [DllImport("kernel32.dll")]
    internal static extern IntPtr GetProcAddress(IntPtr hModule,
        string procedureName);

然后按如下方式使用:

// DLLFileName is, say, "MyLibrary.dll"
IntPtr hLibrary = NativeWinAPI.LoadLibrary(DLLFileName);

if (hLibrary != IntPtr.Zero) // DLL is loaded successfully

    // FunctionName is, say, "MyFunctionName"
    IntPtr pointerToFunction = NativeWinAPI.GetProcAddress(hLibrary, FunctionName);

    if (pointerToFunction != IntPtr.Zero)
    
        MyFunctionDelegate function = (MyFunctionDelegate)Marshal.GetDelegateForFunctionPointer(
            pointerToFunction, typeof(MyFunctionDelegate));
        function(123);
    

    NativeWinAPI.FreeLibrary(hLibrary);

其中MyFunctionDelegatedelegate。例如:

delegate void MyFunctionDelegate(int i);

【讨论】:

【参考方案2】:

您可以使用LoadAssembly 方法和CreateInstance 方法来调用方法

        Assembly a = Assembly.Load("example");
        // Get the type to use.
        Type myType = a.GetType("Example");
        // Get the method to call.
        MethodInfo myMethod = myType.GetMethod("MethodA");
        // Create an instance. 
        object obj = Activator.CreateInstance(myType);
        // Execute the method.
        myMethod.Invoke(obj, null);

【讨论】:

问题清楚地表明上下文是非托管 DLL @DavidHeffernan,我不会说这么清楚。任何地方都没有提到它。 OP 在他的问题中没有说他正在尝试加载托管或非托管程序集。他谈到了一个DLL。我已经在这里看到了不知道如何在另一个托管程序集中引用托管程序集并试图使用 DllImport 属性的人提出的问题。他们可能甚至不知道托管代码和非托管代码之间的区别。 @DarinDimitrov 我用DllImport 来暗示原生DLL。 @DavidHeffernan,是的,我只是说我也犯过一次这个错误 :-) OP 没有参与这个讨论太糟糕了,好像他不太关心他的问题。 嗨,我尝试了你指定的所有方式......但无法加载程序集......是的,我对托管和非托管程序集不太了解。我正在动态获取 DLL 文件名、命名空间名称、类名和方法名,并且返回类型始终是 Double in Type。如果能详细说明如何动态运行DLL,对我有很大的帮助。

以上是关于从 C# 方法,如何调用和运行 DLL,其中 DLL 名称来自 String 变量?的主要内容,如果未能解决你的问题,请参考以下文章

java调用C#程序集

c#如何合并多个dll文件

从 C# 调用 COM dll,HRESULT 错误处理?

如何将整数从 C# 方法复制到本机 C DLL 函数

如何从 javascript 调用 user32.dll 方法

C# dll里main函数如何运行