NGen: Creating Setup Projects
This is article 4 of 4 in the NGen: Walk-through Series .
The NGen technology is designed to be used during the installation phase of a managed application or library. This article will talk about the various installer technologies available, which one to choose, and how to invoke NGen given that installer technology.
Installer Toolsets
The fundamental thing to know before we take a look at installers is that NGen is a tool that can be run only with administrator privileges. A non-admin user cannot invoke NGen.exe. This means that any installer technology that cannot run with administrator privileges cannot be used to invoke NGen easily. Non-admin installer technologies like ClickOnce sometimes use an MSI wrapper to invoke administrator-only actions like NGen.
There are several tools available to create a Windows Installer file (MSI file) – Visual Studio Setup and Deployment Projects, Install Shield 2010 Limited Edition, Windows Installer XML Toolset (WiX), etc. This MSDN article gives a breakdown of how these tools compare: https://msdn.microsoft.com/en-us/library/ee721500(v=VS.100).aspx. For a simple project which just installs a few binaries, the Visual Studio Deployment Project is easy to ramp up on and can quickly produce a workable package. However, for production quality applications, WiX tends to be the installer toolset of choice. Among other benefits, WiX has MSBuild support (which implies you don’t need to install Visual Studio in order to create a setup package) and stores all data in XML files (which makes it easily editable).
The rest of this article will focus on using NGen via the WiX toolset.
Further Reading
1> Using NGen Custom Action in Visual Studio Deployment Projects: https://msdn.microsoft.com/en-us/library/3hwzzhyd.aspx
Getting Started with WiX
Assuming you have Visual Studio 2010 installed, the next step is to install WiX 3.5 from https://wix.sourceforge.net/releases/3.5.1419.0.
This version is officially the one used for Visual Studio 2010 RC, but it will work against Visual Studio 2010 RTM as well. The version of WiX that is supported on Visual Studio 2010 RTM is scheduled to release soon.
The walk through below assumes that a Visual Studio project for a basic Windows Forms application called HelloWinForm exists already. To create the WiX project that will install this application, in your Visual Studio solution, in Solution Explorer right click on the solution, Add a New Project and under the Windows Installer XML template select the Setup Project.
Screenshot 1: Selecting a Setup Project
Next, in Solution Explorer, under WixProject1 right click on the References node and choose Add Reference. In the Projects tab, select the project named HelloWinForm. This will ensure that the HelloWinForm project will build prior to the WixProject1, and the input to WixProject1 is the output of the HelloWinForm project.
WixProject1 will now contain a default .WXS file which will need some modifications before you can build successfully. This XML file will have several TODOs that will need to be adjusted. Under the Component tag, add a File tag which looks like this –
<File Id="WindowsFormsApplication1File" Name="$(var.HelloWinform.TargetFileName)" Source="$(var.HelloWinform.TargetPath)" DiskId="1" KeyPath="yes">
Further Reading
1> Getting the latest updates for WiX: https://wix.sourceforge.net/
2> Using WiX in Visual Studio to create a basic setup package: All Programs -> Windows Installer XML Toolset 3.5 -> WiX Documentation. Go to Using WiX in Visual Studio -> Creating a Simple Setup.
Adding NGen steps to the WiX Project
Now that we have a basic WiX project working without NGen, the next phase is to incorporate NGen into this project so we can NGen the binaries produced in the HelloWinForm project.
In Solution Explorer, right click on the References node and choose Add Reference. In the Browse tab, find WixNetFxExtension.dll under the bin directory (the full path will likely be something like C:\Program Files\Windows Installer XML v3.5\bin\WixNetFxExtension.dll), and click Add. Add an XML namespace called netfx by changing the Wix tag in the WXS file as shown below.
Before: <Wix xmlns="https://schemas.microsoft.com/wix/2006/wi" >
After: <Wix xmlns="https://schemas.microsoft.com/wix/2006/wi" xmlns:netfx ="https://schemas.microsoft.com/wix/NetFxExtension" >
This will enable intellisense for the netfx namespace.
The next step is to enable NGen installation for the binary that is built in the HelloWinForm project. To do that, add the following line under the File element.
<netfx:NativeImage Id="WindowsFormsApplication1File.exe" Platform="32bit" Priority="1" Dependencies="no" />
Detailed documentation for the WiX schemas can be found via the Windows start menu, All Programs -> Windows Installer XML Toolset 3.5 -> WiX Documentation. Information about the NetFx namespace lives under Windows Installer XML (WiX) Help -> WiX Schema References -> Netfx Schema -> NativeImage Element (Netfx Extension).
The resulting WXS file will look as follows –
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="https://schemas.microsoft.com/wix/2006/wi" xmlns:netfx ="https://schemas.microsoft.com/wix/NetFxExtension" >
<Product Id="3645a635-5cb6-48da-8a2a-6d9bd9778aee" Name="Wix35Project1" Language="1033" Version="1.0.0.0" Manufacturer="Wix35Project1" UpgradeCode="2abe811c-b331-4ca3-94b1-2bfd652a280a">
<Package InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLLOCATION" Name="Wix35Project1">
<Component Id="ProductComponent" Guid="13b3ea27-e675-4e39-b225-62b67d2255d0">
<File Id="WindowsFormsApplication1File" Name="$(var.HelloWinform.TargetFileName)" Source="$(var.HelloWinform.TargetPath)" DiskId="1" KeyPath="yes">
<netfx:NativeImage Id="WindowsFormsApplication1File.exe" Platform="32bit" Priority="1" Debug="yes" Dependencies="no" />
</File>
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id="ProductFeature" Title="Wix35Project1" Level="1">
<ComponentRef Id="ProductComponent" />
</Feature>
</Product>
</Wix>
Specifying a priority of 0 ensures that the native image compilation will be done synchronously when the installer is running. Specifying a priority value of 1, 2 or 3 will make the compilation occur in the background. Priority 1 has the effect that assemblies are immediately compiled in the background, priority 2 means the assemblies will be compiled after the priority 1 assemblies are done, and priority 3 assemblies are compiled at machine idle time. If no priority value is specified, the priority will default to be 3. The WiX toolset will issue an “ngen install” or “ngen uninstall” action depending on whether the resulting MSI is being used to install the application or remove it from the machine. The toolset will always issue an “ngen update /queue” as the last command, in order to trigger the NGen service to recompile any native images that may be out of date.
Further Reading
1> How to NGen files in an MSI-based setup package using WiX: https://blogs.msdn.com/astebner/archive/2007/03/03/how-to-ngen-files-in-an-msi-based-setup-package-using-wix.aspx
2> Introducing NGen Support in WiX: https://installing.blogspot.com/2006/06/ngen-support-in-wix.html
3> Synchronous versus Asynchronous Native Image compilation: https://msdn.microsoft.com/en-us/library/ms165074(v=VS.80).aspx
4> Installing file into the GAC using WiX: https://blogs.msdn.com/astebner/archive/2007/06/21/3450539.aspx
Wrapping it up!
That summarizes the very basics of using the Windows Installer XML toolset to invoke NGen.exe in an installer for your application. This article hopefully articulates the various steps needed to get the environment setup, and points out nuances along the way. We’d love to hear what you think! Have you used WiX in the past to enable NGen in your installer? If not, what technology do you use? How was your experience? Please use the comments section below for any feedback and questions.
Janine Zhang, Pracheeti Nagarkar
CLR Team
Comments
- Anonymous
June 25, 2014
Just what I needed to enable ngen in our app. Thanks!