【问题标题】:How do I call functions from a DLL in my resources?如何从资源中的 DLL 调用函数?
【发布时间】:2017-04-27 12:34:22
【问题描述】:

所以我有这个 DLL 和另一个我认为被称为注入器/加载器的东西?它基本上将我的 DLL 加载到自身的进程中,因此它需要我的 DLL 并将其加载到“Injector.exe”的进程中 在下面的示例中,它不是从资源加载它,而是从桌面加载,同样的事情也适用于此。

现在它正在被加载,它并没有真正调用任何函数,这就是我的问题所在。

我想在加载 DLL 时调用一些 Messagebox 函数。

据我所知,最合乎逻辑的方法是在 btnAssemblyLoad_Click 事件中执行此操作,因此当事件发生时,它会调用 DLL 中的函数。 问题是我不知道这会叫什么,我读过一些关于“反射”的东西,但我不确定这是我需要的。

我应该怎么做?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AssemblyLoader
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            if(ofd.ShowDialog() == DialogResult.OK)
            {
                tbAssemblyLocation.Text = ofd.FileName;
            }
        }

        private void btnAssemblyLoad_Click(object sender, EventArgs e)
        {

            AssemblyName an = AssemblyName.GetAssemblyName(tbAssemblyLocation.Text);
            Assembly.Load(an);
        }
    }
}

DLL

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MSgBOxDllCS
{
    public class Funcs
    {
        public void CallMessageBox()
        {
            MessageBox.Show("Hello");

        }
    }
}

【问题讨论】:

    标签: c# dll .net-assembly messagebox loader


    【解决方案1】:

    你需要调用非静态类的实例方法,见下文。

    // Step 1: load assembly to memory
    var an = AssemblyName.GetAssemblyName(tbAssemblyLocation.Text);
    var assembly = Assembly.Load(an);
    
    // Step 2: get type from the assembly by name
    var type = assembly.GetType("MSgBOxDllCS.Funcs");
    
    // Step 3: get method of the type
    var method = type.GetMethod("CallMessageBox");
    
    // Step 4: create instance of the type
    var funcs = Activator.CreateInstance(type);
    
    // Step 5: invoke the instance method
    method.Invoke(funcs, null);
    

    一般来说,您正在构建的称为插件框架,互联网上有很多关于如何完成的示例,您也可以根据您的要求利用现有框架。

    【讨论】:

    • 这很有意义!它如何在方法上向我抛出此错误“对象引用未设置为对象的实例”。调用,这是因为我需要在资源中有 dll 吗?
    • 没关系!我对那个不好,所以问题是我向您展示的示例使用旧方法名,我必须在加载程序中更改它!一切正常!
    • 现在我将去阅读有关这些类和函数的更多信息,以充分了解我编写它们时发生的情况!
    • 在我的情况下它不会引发异常。带有要运行的代码的程序集应该引用所有必需的库,例如System.Windows.Forms.
    • 听起来不错!反射是一个非常强大的概念,但它确实会降低性能,因此缓存加载的类型总是一个好主意。
    【解决方案2】:

    有几种方法可以实现。

    1. 加载程序集,创建类的实例,使用反射找到所需的方法并调用它。
    var assembly = Assembly.LoadFrom(DllFilePath);
    var funcs = assembly.CreateInstance("MSgBOxDllCS.Funcs");
    var method = funcs.GetType().GetMethod("CallMessageBox");
    method.Invoke(funcs, null);
    
    1. 相同,但使用动态对象,对反射成员的控制较少,但看起来更好:
    var assembly = Assembly.LoadFrom(DllFilePath);
    dynamic funcs = assembly.CreateInstance("MSgBOxDllCS.Funcs");
    funcs.CallMessageBox();
    
    1. 最后但同样重要的是,提取一个接口并将其放入单独的共享 DLL 中。这种方法有助于摆脱反射调用,并且本质上是最可靠的:

    通用共享DLL:

    namespace Shared
    {
       public interface IFuncs
       {
          void CallMessageBox();
       }
    }
    

    要加载的DLL:

    namespace MSgBOxDllCS
    {
        public class Funcs : Shared.IFuncs
        {
            public void CallMessageBox()
            {
                MessageBox.Show("Hello");
            }
        }
    }
    

    加载器:

    var assembly = Assembly.LoadFrom(DllFilePath);
    var funcs = (Shared.IFuncs)assembly.CreateInstance("MSgBOxDllCS.Funcs");
    funcs.CallMessageBox();
    

    【讨论】:

    • 非常好!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    • 2011-02-19
    • 1970-01-01
    相关资源
    最近更新 更多