深入本机影像生成器(Ngen.exe)工具使用方法详解
程序员文章站
2024-03-02 21:07:46
先介绍一点背景知识;.net程序在运行时会实时(jit)编译,将.net程序文件编译成cpu认识的汇编机器码。实时编译需要消耗额外的cpu和内存资源,这对于服务器端程序是无...
先介绍一点背景知识;.net程序在运行时会实时(jit)编译,将.net程序文件编译成cpu认识的汇编机器码。实时编译需要消耗额外的cpu和内存资源,这对于服务器端程序是无关紧要的,因为实时编译只在程序第一次运行时编译,之后就不需要再做了;如果你在做的是一个较大的winform程序或者silverlight等客户端程序时就需要考虑提前编译了。
.net framework安装目录下(类似c:\windows\microsoft.net\framework\v4.0.30319)有一个ngen.exe工具,就是做这件事儿的。这个程序是一个控制台程序,最常用的使用方法如下:
生成文件filepath的native code使用下面命令:
ngen install filepath
卸载文件filepath的native code使用下面命令
ngen uninstall filepath
本文主要就用这两种用法,有关这个工具更多的参数和介绍,请参考msdn。
客户端程序我们必然要制作安装包,我的思路是在安装程序时就做本机映象的生成操作;我们可以在安装程序中添加一步自定义操作来做这件事情。
如果你对本文的话题感兴趣,不妨按照下面步骤试一下。
1. 新建解决方案,名字随意
2. 在新解决方案中添加一个winform项目,假定我们要对这个winform项目生成的可执行文件做本机映象生成操作;这只是一个演示,所以这个项目什么都不做
3. 在这个解决方案中添加一个名字为ngeninstaller的类库项目,并新建一个installer class;
在新建的ngeninstaller类中添加在安装时使用ngen安装程序的功能代码。
4. 代码实现很简单就是使用process执行ngen程序来完成安装。需要注意的时,具体让ngen安装那些文件时通过context.parameters[“ngen1|2|3”]传进来的,这个参数需要在制作安装包的自定义步骤中设置。
实现代码:
using system;
using system.collections;
using system.collections.generic;
using system.componentmodel;
using system.configuration.install;
using system.linq;
using system.runtime.interopservices;
using system.io;
using system.diagnostics;
namespace ngeninstaller
{
[runinstaller(true)]
public partial class ngeninstaller : system.configuration.install.installer
{
public ngeninstaller()
{
initializecomponent();
}
public override void install(idictionary statesaver)
{
ngenfile(installtypes.install);
}
public override void uninstall(idictionary savedstate)
{
ngenfile(installtypes.uninstall);
}
private enum installtypes
{
install,
uninstall
}
private void ngenfile(installtypes options)
{
string envdir = runtimeenvironment.getruntimedirectory();
string ngenpath = path.combine(envdir, "ngen.exe");
string exepath = context.parameters["assemblypath"];
string appdir = path.getdirectoryname(exepath);
int i = 1;
do {
string filekey = "ngen" + i;
//需要生成本机映象的程序集名字,配置在ngen1...5,6的配置中
if (context.parameters.containskey(filekey))
{
string ngenfilename = context.parameters["ngen" + i];
string filefullname = path.combine(appdir, ngenfilename);
string argument = (options == installtypes.install ? "install" : "uninstall") + " \"" + filefullname + "\"";
process ngenprocess = new process();
ngenprocess.startinfo.filename = ngenpath;
ngenprocess.startinfo.arguments = argument;
ngenprocess.startinfo.createnowindow = true;
ngenprocess.startinfo.windowstyle = processwindowstyle.hidden;
ngenprocess.start();
ngenprocess.waitforexit();
i++;
}
else {
break;
}
}
while (true);
}
}
}
这个类库中只有这一个类,完成我们要的操作
5. 最后一步是制作安装程序,在解决方案中添加安装项目
.net framework安装目录下(类似c:\windows\microsoft.net\framework\v4.0.30319)有一个ngen.exe工具,就是做这件事儿的。这个程序是一个控制台程序,最常用的使用方法如下:
生成文件filepath的native code使用下面命令:
复制代码 代码如下:
ngen install filepath
卸载文件filepath的native code使用下面命令
复制代码 代码如下:
ngen uninstall filepath
本文主要就用这两种用法,有关这个工具更多的参数和介绍,请参考msdn。
客户端程序我们必然要制作安装包,我的思路是在安装程序时就做本机映象的生成操作;我们可以在安装程序中添加一步自定义操作来做这件事情。
如果你对本文的话题感兴趣,不妨按照下面步骤试一下。
1. 新建解决方案,名字随意
2. 在新解决方案中添加一个winform项目,假定我们要对这个winform项目生成的可执行文件做本机映象生成操作;这只是一个演示,所以这个项目什么都不做
3. 在这个解决方案中添加一个名字为ngeninstaller的类库项目,并新建一个installer class;
在新建的ngeninstaller类中添加在安装时使用ngen安装程序的功能代码。
4. 代码实现很简单就是使用process执行ngen程序来完成安装。需要注意的时,具体让ngen安装那些文件时通过context.parameters[“ngen1|2|3”]传进来的,这个参数需要在制作安装包的自定义步骤中设置。
实现代码:
复制代码 代码如下:
using system;
using system.collections;
using system.collections.generic;
using system.componentmodel;
using system.configuration.install;
using system.linq;
using system.runtime.interopservices;
using system.io;
using system.diagnostics;
namespace ngeninstaller
{
[runinstaller(true)]
public partial class ngeninstaller : system.configuration.install.installer
{
public ngeninstaller()
{
initializecomponent();
}
public override void install(idictionary statesaver)
{
ngenfile(installtypes.install);
}
public override void uninstall(idictionary savedstate)
{
ngenfile(installtypes.uninstall);
}
private enum installtypes
{
install,
uninstall
}
private void ngenfile(installtypes options)
{
string envdir = runtimeenvironment.getruntimedirectory();
string ngenpath = path.combine(envdir, "ngen.exe");
string exepath = context.parameters["assemblypath"];
string appdir = path.getdirectoryname(exepath);
int i = 1;
do {
string filekey = "ngen" + i;
//需要生成本机映象的程序集名字,配置在ngen1...5,6的配置中
if (context.parameters.containskey(filekey))
{
string ngenfilename = context.parameters["ngen" + i];
string filefullname = path.combine(appdir, ngenfilename);
string argument = (options == installtypes.install ? "install" : "uninstall") + " \"" + filefullname + "\"";
process ngenprocess = new process();
ngenprocess.startinfo.filename = ngenpath;
ngenprocess.startinfo.arguments = argument;
ngenprocess.startinfo.createnowindow = true;
ngenprocess.startinfo.windowstyle = processwindowstyle.hidden;
ngenprocess.start();
ngenprocess.waitforexit();
i++;
}
else {
break;
}
}
while (true);
}
}
}
这个类库中只有这一个类,完成我们要的操作
5. 最后一步是制作安装程序,在解决方案中添加安装项目
添加安装程序之后右击安装项目添加项目输出,如下图所示
在添加项目输出的对话框中选择winforms项目和刚建的类库。
然后右击安装项目选择视图---自定操作打开自定义操作窗口,添加一个名字为“ngen生成本机映象”的自定义操作,在添加操作时要选择ngeninstaller项目输出 如下图:
然后将自定义操作的名字修改为“ngen生成本机代码”,如下图所示
然后右击新建的自定义操作,选择属性窗口,在属性窗口的customactiondata属性中添加需要操作的程序集,注意customactiondata是一个键值对,每个键值对以/开始
完成这一步就差不多了,你可以编译一下整个解决方案。运行安装项目生成的安装包。
6. 运行安装包,如果一切正常的话就做了本机映象生成了,可以通过ngen display filepath命令来验证native本机影响是否安装正常,如下命令行输出