4

我的应用没有安装程序。它是可移植的,但我需要ngen.exe在它上面运行,因为它在启动时运行。

是否建议ngen.exe在应用程序的第一次运行时自动运行?以后会不会出问题?有内置的方法吗?

4

2 回答 2

6

是否建议在第一次运行应用程序时自动运行 ngen.exe?

我从未读过或听过任何这样的建议,但这是一个有趣的想法。

我说去测试它是否适合您的情况(就您的“便携式”/“无安装程序”要求而言,这很有趣)。

有内置的方法吗?

在第一次运行应用程序时没有内置的方式来运行 NGen;但它可以按照下面的 PoC 演示来完成。

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 文档中提到的这一职责……

当原始程序集或其依赖项之一得到服务时,需要重新生成图像。

...这应该可以通过一些更高级的自我生成逻辑来管理。

于 2014-05-19T02:49:15.643 回答
1

如果您使用的是 dotNEt > 4.5

public App(){
    ProfileOptimization.SetProfileRoot(@"C:\MyApp");
    ProfileOptimization.StartProfile("Start.Profile");
}

把它放在你程序的最开始。配置文件是在您的应用程序第一次启动/配置文件丢失时创建的。MSDN

于 2014-05-19T15:41:51.180 回答