注入和修改 C# 可执行文件
Injecting and modifying C# executable
我想问问是否有可能以某种方式将 C# 代码注入到现有的 *.exe 文件中,该文件也是用 C# 编写的,而无需反编译。
换句话说,我正在尝试对现有的 C# 程序进行 "extension",但我想修改它而不用 "base" 代码(.* exe文件)。
有什么办法可以做到吗?或者是否需要反编译过程来修改基本代码的方法,类 and/or 添加扩展等?
您可以使用 Mono.Cecil or Microsoft CCI project 等框架来实现它。这些框架允许您阅读 &modify/inject IL。但是学习那些框架和IL代码的用法并不容易。
认为有可用的库 FluentIL which is build on top of Mono.Cecil 为 IL 代码提供 C# 包装器。它不会反编译程序集而是加载它,注入程序集可以 writes/generates 一个带有注入代码的新程序集。
这是我用来在项目汇编post 编译中参数用[NotNull]
标记的方法中注入"Null Checking code" 的示例。
var assembly = AssemblyDefinition.ReadAssembly(SourceAssemblyPath);
var module = assembly.MainModule;
var q = from type in module.Types
from method in type.Methods
from parameter in method.Parameters
where parameter.HasCustomAttributes
from attribute in parameter.CustomAttributes
where attribute.AttributeType.FullName == NotNullAttribute.FullName
select new { Method = method, Parameter = parameter };
foreach (var item in q)
{
item.Method.InsertBefore()
.Ldarg(item.Parameter.Name)
.IfNull()
.Throw<ArgumentNullException>()
.EndIf();
}
SourceAssemblyPath = SourceAssemblyPath.Replace("\debug\", "\release\");
assembly.Write(SourceAssemblyPath, new WriterParameters { WriteSymbols = false });
我想问问是否有可能以某种方式将 C# 代码注入到现有的 *.exe 文件中,该文件也是用 C# 编写的,而无需反编译。
换句话说,我正在尝试对现有的 C# 程序进行 "extension",但我想修改它而不用 "base" 代码(.* exe文件)。
有什么办法可以做到吗?或者是否需要反编译过程来修改基本代码的方法,类 and/or 添加扩展等?
您可以使用 Mono.Cecil or Microsoft CCI project 等框架来实现它。这些框架允许您阅读 &modify/inject IL。但是学习那些框架和IL代码的用法并不容易。
认为有可用的库 FluentIL which is build on top of Mono.Cecil 为 IL 代码提供 C# 包装器。它不会反编译程序集而是加载它,注入程序集可以 writes/generates 一个带有注入代码的新程序集。
这是我用来在项目汇编post 编译中参数用[NotNull]
标记的方法中注入"Null Checking code" 的示例。
var assembly = AssemblyDefinition.ReadAssembly(SourceAssemblyPath);
var module = assembly.MainModule;
var q = from type in module.Types
from method in type.Methods
from parameter in method.Parameters
where parameter.HasCustomAttributes
from attribute in parameter.CustomAttributes
where attribute.AttributeType.FullName == NotNullAttribute.FullName
select new { Method = method, Parameter = parameter };
foreach (var item in q)
{
item.Method.InsertBefore()
.Ldarg(item.Parameter.Name)
.IfNull()
.Throw<ArgumentNullException>()
.EndIf();
}
SourceAssemblyPath = SourceAssemblyPath.Replace("\debug\", "\release\");
assembly.Write(SourceAssemblyPath, new WriterParameters { WriteSymbols = false });