动态执行还是静态使用DllImport,各有优点,不在这里评论了。
希望有什么意见或者建议与我联系,我在QQ群:2514097 跟10987609。
原代码如下:
using
System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Reflection.Emit;
public class DllCaller : IDisposable
... {
[DllImport("Kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("Kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("Kernel32.dll")]
static extern bool FreeLibrary(IntPtr hModule);
private IntPtr libPtr;
private MethodInfo method;
/**//// <param name="dllFile">DLL文件的位置</param>
/// <param name="functionName">函数名,注意带字符串的函数分W版跟A版</param>
/// <param name="result">返回的数类型,如果返回void,使用typeof(void)</param>
/// <param name="args">参数列表</param>
/// <remarks>
/// 注意:为了方便使用,返回类型跟参数类型都用一个实例表示,实例值没影响。
/// 例如:用true,false表示bool; 0表示int; (byte)0表示byte, IntPtr.Zero表示指针等
/// </remarks>
/// <example>
/// int MessageBox(
/// HWND hWnd,
/// LPCTSTR lpText,
/// LPCTSTR lpCaption,
/// UINT uType
/// );
/// DllCaller MessageBox = new DllCaller(
/// "user32.dll", "MessageBoxW", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)0
/// );
/// </example>
public DllCaller(string dllFile, string functionName, object result, params object[] args)
...{
if (dllFile == null) throw new ArgumentNullException();
if (functionName == null) throw new ArgumentNullException();
this.libPtr = LoadLibrary(dllFile);
if (this.libPtr == IntPtr.Zero) throw new DllNotFoundException(dllFile);
IntPtr procPtr = GetProcAddress(this.libPtr, functionName);
if (procPtr == IntPtr.Zero) throw new EntryPointNotFoundException(functionName);
AssemblyName asmName = new AssemblyName();
asmName.Name = "DynamicAssembly";
AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run);
ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule("DynamicModule");
Type resultType = (result == typeof(void) ? typeof(void) : result.GetType());
Type[] argTypes = new Type[args.Length];
for (int i = 0; i < args.Length; i++)
argTypes[i] = args[i].GetType();
MethodBuilder funBuilder = modBuilder.DefineGlobalMethod(
functionName,
MethodAttributes.Public | MethodAttributes.Static,
resultType,
argTypes
);
ILGenerator ilGen = funBuilder.GetILGenerator();
for (int i = 0; i < args.Length; i++)
ilGen.Emit(OpCodes.Ldarg, i);
if (IntPtr.Size == 4)
ilGen.Emit(OpCodes.Ldc_I4, (int)procPtr);
else if (IntPtr.Size == 8)
ilGen.Emit(OpCodes.Ldc_I8, (long)procPtr);
ilGen.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, resultType, argTypes);
ilGen.Emit(OpCodes.Ret);
modBuilder.CreateGlobalFunctions();
this.method = modBuilder.GetMethod(functionName);
}
public object Call(params object[] args)
...{
return this.method.Invoke(null, args);
}
public void Dispose()
...{
if (this.method != null)
...{
if (this.libPtr != IntPtr.Zero)
FreeLibrary(this.libPtr);
this.libPtr = IntPtr.Zero;
this.method = null;
GC.SuppressFinalize(this);
}
}
~DllCaller()
...{
this.Dispose();
}
}
public class MarshalBuffer : IDisposable
... {
public static MarshalBuffer FromString(string Text)
...{
MarshalBuffer buffer = new MarshalBuffer();
buffer.ptr = Marshal.StringToCoTaskMemUni(Text);
return buffer;
}
public IntPtr ptr;
private MarshalBuffer() ...{ }
public MarshalBuffer(int cb)
...{
this.ptr = Marshal.AllocHGlobal(cb);
}
public void Dispose()
...{
if (ptr != IntPtr.Zero)
...{
Marshal.FreeHGlobal(ptr);
this.ptr = IntPtr.Zero;
}
}
~MarshalBuffer()
...{
this.Dispose();
GC.SuppressFinalize(this);
}
public override string ToString()
...{
return Marshal.PtrToStringUni(this.ptr);
}
public int this[int Index]
...{
get ...{ return Marshal.ReadInt32(this.ptr, Index * 4); }
set ...{ Marshal.WriteInt32(this.ptr, Index * 4, value); }
}
}
class Test
... {
public static void DrawScreenTest()
...{
DllCaller getdc = new DllCaller("user32.dll", "GetDC", IntPtr.Zero, IntPtr.Zero);
DllCaller textout = new DllCaller("gdi32.dll", "TextOutW", false, IntPtr.Zero, 0, 0, IntPtr.Zero, 0);
IntPtr dc = (IntPtr)getdc.Call(IntPtr.Zero);
MarshalBuffer text = MarshalBuffer.FromString("Hello World");
Random rand = new Random();
for (int i = 0; i < 100; i++)
textout.Call(dc, rand.Next(1024), rand.Next(768), text.ptr, "Hello World".Length);
}
public static void GetComputerNameTest()
...{
MarshalBuffer text = new MarshalBuffer(100);
MarshalBuffer len = new MarshalBuffer(4);
len[0] = 50;
DllCaller getComName = new DllCaller("kernel32.dll", "GetComputerNameW", false, IntPtr.Zero, IntPtr.Zero);
getComName.Call(text.ptr, len.ptr);
Console.WriteLine(text.ToString());
Console.WriteLine(len[0]);
}
static void Main()
...{
DrawScreenTest();
GetComputerNameTest();
}
}
using System.Runtime.InteropServices;
using System.Reflection;
using System.Reflection.Emit;
public class DllCaller : IDisposable
... {
[DllImport("Kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("Kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("Kernel32.dll")]
static extern bool FreeLibrary(IntPtr hModule);
private IntPtr libPtr;
private MethodInfo method;
/**//// <param name="dllFile">DLL文件的位置</param>
/// <param name="functionName">函数名,注意带字符串的函数分W版跟A版</param>
/// <param name="result">返回的数类型,如果返回void,使用typeof(void)</param>
/// <param name="args">参数列表</param>
/// <remarks>
/// 注意:为了方便使用,返回类型跟参数类型都用一个实例表示,实例值没影响。
/// 例如:用true,false表示bool; 0表示int; (byte)0表示byte, IntPtr.Zero表示指针等
/// </remarks>
/// <example>
/// int MessageBox(
/// HWND hWnd,
/// LPCTSTR lpText,
/// LPCTSTR lpCaption,
/// UINT uType
/// );
/// DllCaller MessageBox = new DllCaller(
/// "user32.dll", "MessageBoxW", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)0
/// );
/// </example>
public DllCaller(string dllFile, string functionName, object result, params object[] args)
...{
if (dllFile == null) throw new ArgumentNullException();
if (functionName == null) throw new ArgumentNullException();
this.libPtr = LoadLibrary(dllFile);
if (this.libPtr == IntPtr.Zero) throw new DllNotFoundException(dllFile);
IntPtr procPtr = GetProcAddress(this.libPtr, functionName);
if (procPtr == IntPtr.Zero) throw new EntryPointNotFoundException(functionName);
AssemblyName asmName = new AssemblyName();
asmName.Name = "DynamicAssembly";
AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run);
ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule("DynamicModule");
Type resultType = (result == typeof(void) ? typeof(void) : result.GetType());
Type[] argTypes = new Type[args.Length];
for (int i = 0; i < args.Length; i++)
argTypes[i] = args[i].GetType();
MethodBuilder funBuilder = modBuilder.DefineGlobalMethod(
functionName,
MethodAttributes.Public | MethodAttributes.Static,
resultType,
argTypes
);
ILGenerator ilGen = funBuilder.GetILGenerator();
for (int i = 0; i < args.Length; i++)
ilGen.Emit(OpCodes.Ldarg, i);
if (IntPtr.Size == 4)
ilGen.Emit(OpCodes.Ldc_I4, (int)procPtr);
else if (IntPtr.Size == 8)
ilGen.Emit(OpCodes.Ldc_I8, (long)procPtr);
ilGen.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, resultType, argTypes);
ilGen.Emit(OpCodes.Ret);
modBuilder.CreateGlobalFunctions();
this.method = modBuilder.GetMethod(functionName);
}
public object Call(params object[] args)
...{
return this.method.Invoke(null, args);
}
public void Dispose()
...{
if (this.method != null)
...{
if (this.libPtr != IntPtr.Zero)
FreeLibrary(this.libPtr);
this.libPtr = IntPtr.Zero;
this.method = null;
GC.SuppressFinalize(this);
}
}
~DllCaller()
...{
this.Dispose();
}
}
public class MarshalBuffer : IDisposable
... {
public static MarshalBuffer FromString(string Text)
...{
MarshalBuffer buffer = new MarshalBuffer();
buffer.ptr = Marshal.StringToCoTaskMemUni(Text);
return buffer;
}
public IntPtr ptr;
private MarshalBuffer() ...{ }
public MarshalBuffer(int cb)
...{
this.ptr = Marshal.AllocHGlobal(cb);
}
public void Dispose()
...{
if (ptr != IntPtr.Zero)
...{
Marshal.FreeHGlobal(ptr);
this.ptr = IntPtr.Zero;
}
}
~MarshalBuffer()
...{
this.Dispose();
GC.SuppressFinalize(this);
}
public override string ToString()
...{
return Marshal.PtrToStringUni(this.ptr);
}
public int this[int Index]
...{
get ...{ return Marshal.ReadInt32(this.ptr, Index * 4); }
set ...{ Marshal.WriteInt32(this.ptr, Index * 4, value); }
}
}
class Test
... {
public static void DrawScreenTest()
...{
DllCaller getdc = new DllCaller("user32.dll", "GetDC", IntPtr.Zero, IntPtr.Zero);
DllCaller textout = new DllCaller("gdi32.dll", "TextOutW", false, IntPtr.Zero, 0, 0, IntPtr.Zero, 0);
IntPtr dc = (IntPtr)getdc.Call(IntPtr.Zero);
MarshalBuffer text = MarshalBuffer.FromString("Hello World");
Random rand = new Random();
for (int i = 0; i < 100; i++)
textout.Call(dc, rand.Next(1024), rand.Next(768), text.ptr, "Hello World".Length);
}
public static void GetComputerNameTest()
...{
MarshalBuffer text = new MarshalBuffer(100);
MarshalBuffer len = new MarshalBuffer(4);
len[0] = 50;
DllCaller getComName = new DllCaller("kernel32.dll", "GetComputerNameW", false, IntPtr.Zero, IntPtr.Zero);
getComName.Call(text.ptr, len.ptr);
Console.WriteLine(text.ToString());
Console.WriteLine(len[0]);
}
static void Main()
...{
DrawScreenTest();
GetComputerNameTest();
}
}