当使用Reflection.Emit
在运行时构建程序集时,我想在保存到光盘之前验证程序集 MSIL。像PEVerify但在运行时。有这样的API吗?
4 回答
peverify.exe 似乎是 c:\Windows\Microsoft.NET\Framework\v4.0.30319\peverify.dll (或 c:\Windows\Microsoft.NET\Framework\v2.0.50727\peverify.dll对于CLR 2.0),这是一个原生DLL(实际上peverify.exe也是原生的)
我没有在任何地方看到此文档,因此它可能不是公共 API。您可以使用Dependency Walker之类的东西从该 DLL 中找出导出的函数,但我认为只调用 peverify.exe 会更简单。
编辑:轶事证据:
- 在编译器步骤中,Boo 实际上调用 peverify.exe。
- Nemerle在其测试中调用 peverify.exe。
- Castle.DynamicProxy在其测试中调用 peverify.exe。
除了使用 PEVerify,您还可以使用 ILSpy 的反编译器作为进程内解决方案,如下所述:http: //www.codeproject.com/Tips/659692/Automated-MSIL-PE-verification-using-ILSpy
文章摘要如下:
- 收集相关 DLL 以从您的测试项目中引用,或者在这种情况下从运行时 IL 检查器中引用
- 遍历方法以使用 Mono.Cecil 进行验证
- 对于每个方法,将其添加到执行验证的 ICSharpCode.Decompiler 中定义的 AstBuilder。例如。
var context = new DecompilerContext(method.Module) { CurrentType = method.DeclaringType };
var astBuilder = new AstBuilder(context);
astBuilder.AddMethod(method);
性能方面,我没有检查哪种方法更快。虽然这个方法是进程内的,但它可能会更慢,因为抽象语法树是在验证 IL 时构建的(我必须设置一个性能测试来检查这个理论)。
正如上面文章中所指出的,我发现 ILSpy 反编译器比 PEVerify 更可靠,在一个实例中,PEVerify 声明一个程序集是有效的,而 ILSpy 正确地给出了一个漂亮的堆栈跟踪,表明我的生成错误。
调用 peverify 确实可能是最好的方法,但 peverify 位于许多不同的目录中,具体取决于 .NET 的运行版本。您可以尝试枚举所有这些路径并检查最新的路径,但在最后一次计数 IIRC 中这至少是 6 条不同的路径,并且不是跨平台的,即。不包括单声道。
我最近发现我可以只链接到 Microsoft.Build.Tasks 程序集,然后创建 Microsoft.Build.Tasks.GetFrameworkSdkPath 的实例并调用 Path 属性。我注意到一个奇怪的行为是第一次访问路径会引发异常,但是如果您只是吞下该异常,则可以从那时起访问该路径。
Peverify.exe 然后是 Path.Combine(new GetFrameworkSdkPath().Path, "bin\peverify")。
调试 LCG允许您在运行时使用 Windbg 调试生成的代码。
也许它可以帮助你。