Categories
Best Practices Windows Installer, Application Compatibility and Deployments

How to add Assemblies to Global Assembly Cache (GAC)

Installation of assemblies should not be dealt using gacutil.exe (Custom action) in an application installation suite. Gacutil is not designed to be used during installation. Gacutil.exe works, but it is a developer tool, and developer tools go into SDKs and not runtime packages typically. It isn’t really appropriate to put more tools into the runtime because that causes it to get larger, which makes it more difficult for applications to redistribute because of increased download, size, etc.

In general, installing an assembly to the GAC is an application deployment activity, and is most often done during application setup. One should use Windows Installer to install your application. Starting with version 2.0, Windows Installer has built-in functionality to install assemblies to the GAC – the MsiAssembly and MsiAssemblyName tables in particular. Its always better to use a MSI as an installer and directly authoring files, registry and GAC installation steps using built-in Windows Installer functionality instead of using a batch script, regsvr32 and Gacutil. We can gain a lot of benefits from using an MSI (clean rollback; uninstall, serviceability, deployment options, etc). Therefore we should use this built-in functionality to handle GAC installation and un-installation.

This means that if we want to obtain Windows Vista Logo certification for our application, we should use Windows Installer and the built-in GAC installation functionality for our setup.

Reference: Aaron Stebner’s WebLog

Categories
How-to Windows Installer, Application Compatibility and Deployments

Basics and Introduction to .NET Framework Assemblies

An Assembly is a logical unit of code. Assembly physically exist as DLLs or EXEs. One assembly can contain one or more files. The constituent files can include any file types like image files, text files etc. along with DLLs or EXEs. When you compile your source code by default the exe/dll generated is actually an assembly, Unless your code is bundled as assembly it can not be used in any other application. Every assembly file contains information about itself. This information is called as Assembly Manifest.

What is assembly manifest?

Assembly manifest is a data structure which stores information about an assembly. This information is stored within the assembly file(DLL/EXE) itself. The information includes version information, list of constituent files etc.

What is private and shared assembly?

The assembly which is used only by a single application is called as private assembly. Suppose you created a DLL which encapsulates your business logic. This DLL will be used by your client application only and not by any other application. In order to run the application properly your DLL must reside in the same folder in which the client application is installed. Thus the assembly is private to your application.

Suppose that you are creating a general purpose DLL which provides functionality which will be used by variety of applications. Now, instead of each client application having its own copy of DLL you can place the DLL in ‘global assembly cache’. Such assemblies are called as shared assemblies.

What is Global Assembly Cache?

Global assembly cache is nothing but a special disk folder where all the shared assemblies will be kept. It is located under <drive>:\WinNT\Assembly folder.

How assemblies avoid DLL Hell?

As stated earlier most of the assemblies are private. Hence each client application refers assemblies from its own installation folder. So, even though there are multiple versions of same assembly they will not conflict with each other. Consider following example:

  • You created assembly Assembly1
  • You also created a client application which uses Assembly1 say Client1
  • You installed the client in C:\MyApp1 and also placed Assembly1 in this folder
  • After some days you changed Assembly1
  • You now created another application Client2 which uses this changed Assembly1
  • You installed Client2 in C:\MyApp2 and also placed changed Assembly1 in this folder
  • Since both the clients are referring to their own versions of Assembly1 everything goes on smoothly

Now consider the case when you develop assembly that is shared one. In this case it is important to know how assemblies are versioned. All assemblies has a version number in the form: major.minor.build.revision. If you change the original assembly the changed version will be considered compatible with existing one if the major and minor versions of both the assemblies match. When the client application requests assembly the requested version number is matched against available versions and the version matching major and minor version numbers and having most latest build and revision number are supplied.

Categories
Microsoft Windows Installer, Application Compatibility and Deployments

How to check an Executable for Manifests and Digital Signing?

To avoid UAC prompts for applications on launch, there exists a manifest file which contains key information on the privileges. Many times, these manifest files are present along with the executable in the same directory. For example: Altair.exe will have a manifest file called Altair.exe.manifest in the same directory. There can also be cases where the manifest is embedded in the exe itself. In this case, identifying the launch condition for this exe involves a lot of research.

Here is a simple executable which will help research those launch conditions.

Sigcheck.exe is an executable from the Sysinternals team that enables you to check whether a file has been digitally signed. The -m switch allows you to view any manifest within the file. All we need to do is run this sigcheck.exe with -m switch along with the executable, the full manifest will be displayed on the command prompt window.

If the XML manifest is going to prompt an elevation then there will be a tag “requiredExecutionLevel” set to “requireAdministrator”.

You can then re-create a manifest on these 3 categories:

  • Runasinvoker
  • Runasadmin
  • Runwithleastprivilages

Its advised to use Run as Invoker for manifests (Launch condition).

Signcheck.exe can be downloaded here.

Categories
How-to Microsoft

How to Handle .NET Framework Native Images in Software MSI Installation Packages?

When you find in a file which is suffixed by “.ni” in an application capture (For eg: Aclayers.ni.dll), this is an indication that it is a native image for an assembly. (The base assembly can be found in the application installation directory). These files cannot be added directly to the MSI package. Instead, it needs to be done through a .NET executable(ngen.exe).
In this below article, we look at the basics and implementation of this process.

Overview of Native Image Generator:

The Native Image Generator (ngen.exe) creates a native image from a managed assembly and installs it into the native image cache on the local computer. The native image cache is a reserved area of the global assembly cache. Once you create a native image for an assembly, the runtime automatically uses that native image each time it runs the assembly. You do not have to perform any additional procedures to cause the runtime to use a native image. Running Ngen.exe on an assembly allows the assembly to load and execute faster, because it restores code and data structures from the native image cache rather than generating them dynamically.

How Native Generator Works

Ngen.exe does not use standard assembly probing rules to locate the assemblies you specify on the command line. Ngen.exe looks only in the current directory for assemblies that you specify. Therefore, to allow Ngen.exe to locate your assemblies, you should either set your working directory to the directory that contains the assemblies you want to create native images for or specify exact paths to the assemblies.

This tool can be located at <drive>:\WINNT\Microsoft.NET\Framework\<version>\ngen.exe

This tool is used to create a native Image from a .NET assembly and installs it into the native image cache on that computer. Since assembly image is present on the local machine cache loading of the assembly becomes faster because .NET reads data from the native image than generating them dynamically (JIT). Pre-compiling assemblies with Ngen.exe can improve the startup time for applications, because much of the work required to execute code has been done in advance.

The default usage for NGen is extremely simple: ngen install aclayer.dll

This will generate native images for aclayer.dll and all of its dependencies and create a native image for this dll in C:\Winnt\Assembly\Native Images as aclayer.ni.dll.

This process can be quite slow. For larger applications you may wish to use the /queue option which will queue up aclayer.dll, and all of its dependencies, so that they will be converted by the Native Image Service. This will happen in the background, at the service’s earliest convenience. Once the native image is generated it will be stored in the native image cache and used automatically.

Usage:

While Installing:
Identify the Assembly which creates these native images, mention the same path in these scripts. Example: C:\Program FIles\DWG TrueView 2008\AcLayer.dll. For multiple assemblies use the function mentioned.

Use this script in your MSI Package.

Option Explicit
Dim wshShell, ngen, FSO, windir, assembly,PrgFiles
Set wshShell = CreateObject(“WScript.Shell”)
Set FSO = CreateObject(“Scripting.FileSystemObject”)
windir = wshShell.ExpandEnvironmentStrings(“%Windir%”)
PrgFiles = wshShell.ExpandEnvironmentStrings(“%ProgramFiles%”)
ngen = windir & “\Microsoft.NET\Framework\v2.0.50727\ngen.exe”

if FSO.FileExists(ngen) then
assembly=chr(34) & PrgFiles & “\DWG TrueView 2008\AcLayer.dll” & chr(34)
Generate(assembly)
end if

set FSO = nothing
set wshShell = nothing

Function Generate (Byval file)
Dim strCmd,wshShell1
Set wshShell1 = CreateObject(“WScript.Shell”)
strCmd= chr(34) & ngen & chr(34) & ” install ” & file
wshShell1.run strCmd,0
Set WshShell1 = nothing
End function

While Un-Installing:

Option Explicit
Dim wshShell, ngen, FSO, windir, assembly,PrgFiles
Set wshShell = CreateObject(“WScript.Shell”)
Set FSO = CreateObject(“Scripting.FileSystemObject”)
windir = wshShell.ExpandEnvironmentStrings(“%Windir%”)
PrgFiles = wshShell.ExpandEnvironmentStrings(“%ProgramFiles%”)
ngen = windir & “\Microsoft.NET\Framework\v2.0.50727\ngen.exe”

if FSO.FileExists(ngen) then
assembly=chr(34) & PrgFiles & “\DWG TrueView 2008\AcLayer.dll” & chr(34)
DeleteImages(assembly)
end if

Function DeleteImages (Byval file)
Dim strCmd,wshShell1
Set wshShell1 = CreateObject(“WScript.Shell”)
strCmd= chr(34) & ngen & chr(34) & ” uninstall ” & file
wshShell1.run strCmd,1
Set WshShell1 = nothing
End function

Note: To run Ngen.exe, you must have administrative privileges. Hence, run this CA in deferred/System Context mode.