我的应用没有安装程序。它是可移植的,但我需要ngen.exe
在它上面运行,因为它在启动时运行。
是否建议ngen.exe
在应用程序的第一次运行时自动运行?以后会不会出问题?有内置的方法吗?
我从未读过或听过任何这样的建议,但这是一个有趣的想法。
我说去测试它是否适合您的情况(就您的“便携式”/“无安装程序”要求而言,这很有趣)。
在第一次运行应用程序时没有内置的方式来运行 NGen;但它可以按照下面的 PoC 演示来完成。
以下 PoC 代码包含来自相关 SO answer 的代码。
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
namespace SelfNgenPoC
{
class Program
{
static void Main(string[] args)
{
/*
* Check whether the app has been NGen'd with code adapted from
* https://stackoverflow.com/a/20593260/1810429, which also outlines
* an alternative approach - by running...
* ngen.exe display <assemblyPath>
* ...and checking the result - 0 if the app is already NGen'd and
* -1 if it is not.
*/
Process process = Process.GetCurrentProcess();
ProcessModule[] modules = new ProcessModule[process.Modules.Count];
process.Modules.CopyTo(modules, 0);
var niQuery =
from m in modules
where m.FileName.Contains(@"\" + process.ProcessName + ".ni")
select m.FileName;
bool ni = niQuery.Count() > 0 ? true : false;
// FORNOW: for PoC debugging and sanity checking
if (ni)
Console.WriteLine("Native Image: " + niQuery.ElementAt(0));
else
Console.WriteLine("IL Image: " + process.MainModule.FileName);
/*
* NGen the app if not.
*/
if (!ni)
{
// FORNOW: for PoC debugging and sanity checking
Console.WriteLine("The app is not NGen'd.");
Console.WriteLine("NGen'ing the app...");
var assemblyPath = process.MainModule.FileName;
ProcessStartInfo startInfo = new ProcessStartInfo();
// TODO: Determine the path to (the appropriate version of)
// ngen.exe.
// FORNOW: Just use a hardcoded path to ngen.exe for PoC.
startInfo.FileName =
@"C:\Windows\Microsoft.NET\Framework\v4.0.30319\ngen.exe";
startInfo.Arguments = "install \"" + assemblyPath + "\"";
// TBD: process options that you think make sense
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
try
{
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// TBD: error handling that you think makes sense - e.g.
// logging or displaying the error, moving on regardless
// etcetera.
}
}
else
{
// FORNOW: for PoC debugging and sanity checking
Console.WriteLine("The app is already NGen'd.");
}
/*
* Carry on with whatever your app does.
*/
}
}
}
C:\bin\SelfNgenPoC>.\SelfNgenPoC.exe
IL Image: C:\bin\SelfNgenPoC.exe
The app is not NGen'd.
NGen'ing the app...
Microsoft (R) CLR Native Image Generator - Version 4.0.30319.18408
Copyright (c) Microsoft Corporation. All rights reserved.
1> Compiling assembly C:\bin\SelfNgenPoC.exe (CLR v4.0.30319) ...
C:\bin\SelfNgenPoC>
C:\bin\SelfNgenPoC>.\SelfNgenPoC.exe
Native Image: C:\Windows\assembly\NativeImages_v4.0.30319_32\SelfNgenPoC\a461633
0444188e116025424c70d15f1\SelfNgenPoC.ni.exe
The app is already NGen'd.
C:\SelfNgenPoC>
一个程序集对 NGen 是否有意义取决于许多因素,您可以在MSDN 博客文章、 MSDN 上的NGen 文档、较早但相关的“MSDN 杂志”文章以及其他地方查看这些因素。
最终,只有您对您的应用有足够的了解,才能确定它是否对 NGen(任何、部分或全部)程序集有意义。
假设它在您的情况下确实有意义,我不认为它会根据您的描述引起任何明显的问题。
请务必牢记标准 NGen 职责——尤其是 NGen MSDN 文档中提到的这一职责……
当原始程序集或其依赖项之一得到服务时,需要重新生成图像。
...这应该可以通过一些更高级的自我生成逻辑来管理。
如果您使用的是 dotNEt > 4.5
public App(){
ProfileOptimization.SetProfileRoot(@"C:\MyApp");
ProfileOptimization.StartProfile("Start.Profile");
}
把它放在你程序的最开始。配置文件是在您的应用程序第一次启动/配置文件丢失时创建的。MSDN