My app doesn't have an installer. It is portable but I need to run ngen.exe
on it because it runs on startup.
Is it recommended to autorun ngen.exe
on the first run of the app? Will it cause any problems later? Is there a built in way to do it?
I have never read or heard any such recommendation, but it is an interesting idea.
I say go for it and test whether it works for your situation (which is interesting insofar as your "portable"/"no-installer" requirement).
There is not a built-in way to run NGen on the first run of an app; but it can be done as the PoC below demonstrates.
The following PoC code incorporates code from a related 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>
Whether it makes sense to NGen an assembly depends on many factors, which you can review in an MSDN blog post, NGen documentation on MSDN, an older but relevant "MSDN Magazine" article, and elsewhere.
Ultimately only you know enough about your app to determine whether it makes sense to NGen (any, some, or all of) its assemblies.
Assuming it does make sense in your situation, I don't expect it will cause any distinct problems based on what you have described.
Just be sure to keep standard NGen responsibilities in mind - particularly this one noted in the NGen MSDN documentation...
Images need to be regenerated when the original assembly or one of its dependencies is serviced.
...which should be manageable with a little fancier self-NGen'ing logic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With