Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly NGen .NET application during installation

I'm using Inno Setup to generate setup program for my application, and I would like to write a script to NGen my application during installation. I want the code to be able to NGen files targeting x86, x64, or AnyCPU. I want to be able to NGen on 32bit and 64bit systems. How can I achieve this?

I've found a couple of helpful links:
Getting the .NET Framework directory path
http://nsis.sourceforge.net/Get_directory_of_installed_.NET_runtime
Where I've found it is a quite complex problem - there can be up to 4 different versions of NGen application:

  1. for CLR 2.0 and 32bit systems
  2. for CLR 2.0 and 64bit systems
  3. for CLR 4.0 and 32bit systems
  4. for CLR 4.0 and 64bit systems

And it is even more complicated by the fact the application can target 32bit CPU and run on 64bit system.


So what came to my mind was a function looking like this:

function NGenFile(file: String; targetCPU: TTargetCPU; targetCLR: TTargetCLR): Boolean;

and call it somewhere in [Code] after successful isntallation:

NGenFile(ExpandConstant('{app}\application.exe'), tcpu64, tclr20);
NGenFile(ExpandConstant('{app}\library1.dll'), tcpu64, tclr40);
NGenFile(ExpandConstant('{app}\library2.dll'), tcpu32, tclr20);
NGenFile(ExpandConstant('{app}\library3.dll'), tcpu32, tclr40);
NGenFile(ExpandConstant('{app}\library4.dll'), tcpuAny, tclr20);
NGenFile(ExpandConstant('{app}\library5.dll'), tcpuAny, tclr40);

And it would work like this:

  1. application.exe (tcpu64, tclr20)
    On 64bit system it would generate native image targeting 64bit CPU and CLR 2.0, Result := True
    On 32bit system it wouldn't do anything, Result := False

  2. library1.dll (tcpu64, tclr40)
    On 64bit system it would generate native image targeting 64bit CPU and CLR 4.0, Result := True
    On 32bit system it wouldn't do anything, Result := False

  3. library2.dll (tcpu32, tclr20)
    On 64bit system it would generate native image targeting 32bit CPU and CLR 2.0, Result := True
    On 32bit system it would do the same as on 64bit system

  4. library3.dll (tcpu32, tclr40)
    On 64bit system it would generate native image targeting 32bit CPU and CLR 4.0, Result := True
    On 32bit system it would do the same as on 64bit system

  5. library4.dll (tcpuAny, tclr20)
    On 64bit system it would generate native image targeting 64bit CPU and CLR 2.0, Result := True
    On 32bit system it would generate native image targeting 32bit CPU and CLR 2.0, Result := True

  6. library5.dll (tcpuAny, tclr40)
    On 64bit system it would generate native image targeting 64bit CPU and CLR 4.0, Result := True
    On 32bit system it would generate native image targeting 32bit CPU and CLR 4.0, Result := True


So to make it work, I need to know 4 different paths to .NET runtime directory. This is what I've found:

  1. 32bit system CLR 2.0
    Get value of "InstallRoot" in "HKLM\Software\Microsoft\.NETFramework", save to value1
    Get name of first value in "HKLM\Software\Microsoft\.NETFramework\Policy\v2.0", save to value2
    value1 + "v2.0." + value2 + "\ngen.exe" => win
    Example: "c:\Windows\Microsoft.NET\Framework\v2.0.50727\ngen.exe"
    I assume this will work the same on 32bit and 64bit systems

  2. 32bit system CLR 4.0
    Get value of "InstallRoot" in "HKLM\Software\Microsoft\.NETFramework", save to value1
    Get name of first value in "HKLM\Software\Microsoft\.NETFramework\Policy\v4.0", save to value2
    value1 + "v4.0." + value2 + "\ngen.exe" => win
    Example: "c:\Windows\Microsoft.NET\Framework\v4.0.30319\ngen.exe"
    I assume this will work the same on 32bit and 64bit systems

  3. 64bit system CLR 2.0
    How to get InstallRoot for 64bit .NET Framework?
    Example: "c:\Windows\Microsoft.NET\Framework64\v2.0.50727\ngen.exe"

  4. 64bit system CLR 4.0
    How to get InstallRoot for 64bit .NET Framework?
    Example: "c:\Windows\Microsoft.NET\Framework64\v4.0.30319\ngen.exe"

I'm actually not sure if the "InstallRoot" value on 64bit systems would point to InstallRoot of 32bit .NET, or 64bit .NET, so are the first 2 methods reliable for any system? And how would look like the second 2 methods? Is there any simpler way to achieve all of this?

like image 614
Paya Avatar asked Oct 14 '22 18:10

Paya


1 Answers

What version of InnoSetup are you using? In the version I use (5.4.0a), there are already constants for to find the .NET root directory. From the InnoSetup help:

{dotnet20} .NET Framework version 2.0 root directory. {dotnet20} is equivalent to {dotnet2032} unless the install is running in 64-bit mode, in which case it is equivalent to {dotnet2064}.

An exception will be raised if an attempt is made to expand this constant on a system with no .NET Framework version 2.0 present.

{dotnet2032} 32-bit .NET Framework version 2.0 root directory.

An exception will be raised if an attempt is made to expand this constant on a system with no .NET Framework version 2.0 present.

{dotnet2064} 64-bit Windows only: 64-bit .NET Framework version 2.0 root directory.

An exception will be raised if an attempt is made to expand this constant on a system with no .NET Framework version 2.0 present.

{dotnet40} .NET Framework version 4.0 root directory. {dotnet40} is equivalent to {dotnet4032} unless the install is running in 64-bit mode, in which case it is equivalent to {dotnet4064}.

An exception will be raised if an attempt is made to expand this constant on a system with no .NET Framework version 4.0 present.

{dotnet4032} 32-bit .NET Framework version 4.0 root directory.

An exception will be raised if an attempt is made to expand this constant on a system with no .NET Framework version 4.0 present.

{dotnet4064} 64-bit Windows only: 64-bit .NET Framework version 4.0 root directory.

An exception will be raised if an attempt is made to expand this constant on a system with no .NET Framework version 4.0 present.

like image 138
mirtheil Avatar answered Oct 16 '22 16:10

mirtheil