如何从资源中的 DLL 调用函数?
How do I call functions from a DLL in my resources?
所以我有这个 DLL 和另一个我认为被称为注入器/加载器的东西?它基本上将我的 DLL 加载到它自己的进程中,因此它将我的 DLL 加载到 "Injector.exe" 的进程中
在下面的示例中,它不是从资源中加载,而是从桌面加载,这里同样适用。
现在正在加载它,它实际上并没有调用任何函数,这就是我的问题所在。
我想在加载 DLL 时调用一些 Messagebox 函数。
据我所知,最合乎逻辑的方法是在 btnAssemblyLoad_Click
事件中执行此操作,因此当事件发生时,它会调用 DLL 中的函数。
问题是我不知道这会叫什么,我读了一些关于 "Reflection" 但我不确定这是我需要的东西。
我该如何处理?
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");
}
}
}
您需要调用非静态 class 的实例方法,见下文。
// 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);
一般来说,您正在构建的称为插件框架,互联网上有大量示例说明如何完成,您也可以根据需要利用现有框架。
您可以通过多种方式实现这一目标。
- 加载一个程序集,创建一个 class 的实例,使用反射找到所需的方法并调用它。
var assembly = Assembly.LoadFrom(DllFilePath);
var funcs = assembly.CreateInstance("MSgBOxDllCS.Funcs");
var method = funcs.GetType().GetMethod("CallMessageBox");
method.Invoke(funcs, null);
- 相同但使用动态对象,减少对反射成员的控制但看起来更好:
var assembly = Assembly.LoadFrom(DllFilePath);
dynamic funcs = assembly.CreateInstance("MSgBOxDllCS.Funcs");
funcs.CallMessageBox();
- 最后但并非最不重要的一点是,提取接口并将其放入单独的共享 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();
所以我有这个 DLL 和另一个我认为被称为注入器/加载器的东西?它基本上将我的 DLL 加载到它自己的进程中,因此它将我的 DLL 加载到 "Injector.exe" 的进程中 在下面的示例中,它不是从资源中加载,而是从桌面加载,这里同样适用。
现在正在加载它,它实际上并没有调用任何函数,这就是我的问题所在。
我想在加载 DLL 时调用一些 Messagebox 函数。
据我所知,最合乎逻辑的方法是在 btnAssemblyLoad_Click
事件中执行此操作,因此当事件发生时,它会调用 DLL 中的函数。
问题是我不知道这会叫什么,我读了一些关于 "Reflection" 但我不确定这是我需要的东西。
我该如何处理?
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");
}
}
}
您需要调用非静态 class 的实例方法,见下文。
// 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);
一般来说,您正在构建的称为插件框架,互联网上有大量示例说明如何完成,您也可以根据需要利用现有框架。
您可以通过多种方式实现这一目标。
- 加载一个程序集,创建一个 class 的实例,使用反射找到所需的方法并调用它。
var assembly = Assembly.LoadFrom(DllFilePath);
var funcs = assembly.CreateInstance("MSgBOxDllCS.Funcs");
var method = funcs.GetType().GetMethod("CallMessageBox");
method.Invoke(funcs, null);
- 相同但使用动态对象,减少对反射成员的控制但看起来更好:
var assembly = Assembly.LoadFrom(DllFilePath);
dynamic funcs = assembly.CreateInstance("MSgBOxDllCS.Funcs");
funcs.CallMessageBox();
- 最后但并非最不重要的一点是,提取接口并将其放入单独的共享 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();