.NET Assemblies: Basics and Packaging Techniques
In .NET, when an application is compiled, the output of the compilation produces what is known as an Assembly. Two types of assemblies can be produced by the compilation procedure. One is the executable file (*.exe) and the other is a dynamic link library file (*.dll). Basically the assembly is the unit of deployment in Microsoft .NET and it can be thought of as a collection of types and resources that form a logical unit of functionality.
An assembly is a self-describing entity. It contains all information about the types (classes) contained in the assembly, all external references needed for executing the assembly and so on. This is possible with an assembly manifest. The manifest contains assembly's identity and version information, a file table containing all files that make up the assembly and the assembly reference list for all external dependencies. Thus assemblies do not need to depend on the registry values for compilation or execution.
An assembly contains manifest data and one or more modules. Manifest data contains information about the assembly and other list of assemblies that it depends on. It also contains all the publicly exposed types and resources. An assembly contains various modules. Each module contains metadata and IL.
Assemblies can be viewed by application developers with the help of a tool called ildasm (IL Disassembler) provided by the .NET Framework.
Types of Assemblies
Private Assemblies
A private assembly is an assembly that is deployed with an application and is available only for that application. That is, other applications do not share the private assembly. Private assemblies are installed in a folder of the application's directory structure. Typically, this is the folder containing the application's executable file.
In this case, we keep the assemblies that make up an application in the application's directory, in a subdirectory of the application's directory. We can override where the CLR looks for an assembly by using the <codeBase> element in a configuration file.
Shared Assemblies
A shared assembly is an assembly available for use by multiple applications on the computer. To make the assembly global, it has to be put into the Global Assembly Cache. Each computer where the common language runtime is installed has a machine-wide code cache called the global assembly cache. The global assembly cache stores assemblies specifically for sharing by several applications on the computer.
In this case, we should share assemblies by installing them into the global assembly cache only when you need to. As a general guideline, we should keep assembly dependencies private and locate assemblies in the application directory unless sharing an assembly is explicitly required. This is achieved with the help of a global assembly cache provided by the .NET Framework.
Advantages of Using an Assembly
Assemblies are designed to simplify application deployment and to solve versioning problems that can occur with component-based applications. Many deployment problems have been solved by the use of assemblies in the .NET Framework. Because they are self-describing components that have no dependencies on registry entries, assemblies enable zero-impact application installation. They also simplify uninstalling and replicating applications.
To solve versioning problems, as well as the remaining problems that lead to DLL conflicts, the runtime uses assemblies to do the following:
- Enable developers to specify version rules between different software components.
- Provide the infrastructure to enforce versioning rules.
- Provide the infrastructure to allow multiple versions of a component to be run simultaneously (called side-by-side execution).
Introduction to Global Assembly Cache (GAC)
The GAC was originally called the Fusion cache and is currently implemented within Fusion.dll. This Global Assembly Cache stores .NET assemblies specifically designated to be shared by several applications on that computer.
Since the GAC is the machine-wide repository for shared assemblies, it is very easy to run into the problem of name collisions if these assemblies only had simple identities because they are developed independently by different vendors and even developers within an organization. Hence, when an assembly has to be put into the Global Assembly Cache it needs to be signed with a strong name.
A strong name contains the assembly's identity i.e. it's text name, version number, and culture information strengthened by a public key and a digital signature generated over the assembly. This is because the CLR verifies the strong name signature when the assembly is placed in the Global Assembly Cache.
Within each folder for a shared assembly, there is a sub folder named using the version and public key token components of the assembly e.g. 1.0.3300.0__b77a5c561934e089. Within this sub folder resides the actual assembly that is installed into the GAC. Note the __AssemblyInfo__.ini file that resides alongside each and every assembly file. This stores assembly properties like URL, MVID, DisplayName etc. For assemblies that have a native image installed, a CustomString property is also included.
Adding Assemblies Into an Application MSI
When creating .NET installations, the first thing you should do is set the preferences for the installation.
Setting .NET preferences for default project files
- In Windows Installer editor, click the Tools menu then select Options. The Wise Options dialog appears.
- Click the .NET Assemblies tab.
Note: Options on the .NET Assemblies tab are only available if you have the .NET Framework installed on your computer. - Fill out the tab as described below:
- Default Application Type. Select a default to use when you create a new .WSI project file:
- Win32 (non .NET). Select this option if your application is a standard Win32 application with no .NET assemblies.
- .NET Application. Select this option if your application contains only .NET elements.
- Mixed (.NET and Win32). Select this option if you have a mix of managed and unmanaged code in your application. This installs .NET assemblies so that they can be called as if they were COM components.
- Rescan COM interop registry keys on compile. Mark this check box to rescan these registry keys each time you compile your project file.
The scanning will still occur when the files are added to the installation as long as the Generate COM interop registry keys for .NET Assembly checkbox is selected for the assembly. If you have the rescan option marked, but the generate com interop isn't marked for a file then nothing will be scanned.
- Scan Dependencies. Select whether to Always Scan, Never Scan or Prompt to Scan the manifest for each .NET assembly you add. When you allow Wise for Windows Installer to scan the manifest, it prompts you to add dependencies that it finds in the manifest that are not in your installation.
- Rescan assembly dependencies on compile. Mark this check box to rescan your assemblies for new dependencies each time you compile.
- Default Application Type. Select a default to use when you create a new .WSI project file:
When you add .NET assemblies to your installation, you need to decide whether they are shared assemblies that should be installed to the Global Assembly Cache on the destination computer, or whether they are private assemblies to use with your application. You can install private assemblies to the application directory. The Global Assembly Cache folder only appears when you are working with a .NET or mixed (.NET and Win32) installation. If you are inserting a shared .NET assembly into the Global Assembly Cache, this must be a strongly named assembly. Add either the private or global assemblies on the Files page in Installation Expert. Then add details for the file.
Adding .NET assembly and manifest details for a file
- On the File page, select the file in the lower-right list box that you added to your installation; then click the Details button. The File Details dialog appears.
- Click the .NET tab. The information you add on this tab is used to populate the MsiAssembly and MsiAssemblyName tables in the MSI database.
- Fill in the tab as described below:
- Assembly Type. Select either .NET or Win32 assembly. If the file is not an assembly, select None.
- Manifest. Select the file that contains the manifest for this assembly. For .NET assemblies this is often the same as the file you are editing because most manifests are embedded in the assembly file or in one of the files in a multifile assembly. For Win32 files, the manifest file is often an external file with the same name plus ".manifest".
- Assembly Attributes. This list box displays this assembly file's name, publicKeyToken, and version attributes. If this information has not been filled in automatically, you must use the Add button to enter it. Enter the Name and Value for the assembly's name, publicKeyToken, and version.
- Show reference in Visual Studio .NET. Mark this to add a registry key that displays this assembly as a reference in Visual Studio on the destination computer. (Visual Studio .NET 2002 or later only.) This lets you pull the assembly into a Visual Studio project without having to browse for it.
- Execute Install method on this assembly. A .NET assembly can contain an install object that performs additional installation functions unique to the assembly. Mark this to execute this assembly's install object after the file is installed.
- Generate native-code version during installation. Mark this to run the Native Image Generator (ngen.exe) on the assembly after it is installed. The Native Image Generator precompiles portions of the assembly and caches it on the target computer so assemblies load and execute faster.
- Click OK.
Dealing with Assemblies which are Captured in a WSI While Snapshot
- Anything captured in GAC - one can create them by going to component and going to assembly table, Wise automatically creates an entry for them in assembly table.
- Anything in registry in HKCR\Clsid...with inprocserver as mscoree.dll - they are.net interoperable assemblies (.net assemblies that can be used with non dotnet languages like vbscript others) that are registered with regasm.exe. Although keeping registries for them would be a good option too., but should be aware that they are also .net assemblies.
- Anything captured in GAC Native images folder- they are dot assemblies registered with ngen.exe - native imgaes are created for faster execution of assemblies. One needs to delete these files from captured wsi and use ngen in custom action to create native images for these assemblies.
- Mshelp2 files captured- they are new type of help files (we will see extension like .hxn, hss) help file that can be used as url as well. we can see them when u install visual studio .net. One needs to delete all the references of these files in appdatafolder. Further, we will need to use custom actions and h2reg.ini and h2reg.exe to register these help files.
Copying assembly .dll files from the GAC folder
Step 1:
Create the following registry DWORD key to view the GAC in a folder format. Usually, it will be displayed in a catalog format.
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion] "DisableCacheViewer"=dword:00000001
Step 2:
Map a temporary drive say W to C:\ using subst w: C:\
now, just type W:\Winnt\Assembly in run prompt to view in folder format.
Now, we can copy the assembly dlls.
Do Not Use gacutil.exe to Add an Assembly to GAC
We should avoid using GACUtil to install assemblies to the GAC for the following reasons:
- Unless the /r option is used, there is no way to track installation references in the GAC.
- GACUtil.exe is part of the .NET Framework SDK and hence is not guaranteed to be on all target machines. Additionally, it is not marked as redistributable and hence you need to check the licensing to make sure you can package it up with your application's installation image.
- Installing using GACUtil.exe does not enable Auto-Repair if the assembly in the GAC is missing (Auto-Repair is possible only with Windows Installer).
Advantages of using Windows Installer to add an Assembly to GAC
These are the following advantages of using Windows Installer to install an assembly:
- It supports accurate reference counting based on installation, repair and removal of assemblies in the GAC.
- It supports Install-on-Demand of assemblies in the GAC. If an assembly was missing from the GAC and a user launches an application that requires that assembly, MSI will automatically install / re-install that assembly to the GAC.
- Rollback of unsuccessful installations, repairs and removals of assemblies in the GAC. Assemblies are added and removed from the GAC as a unit; that is, the files that constitute an assembly are always installed or removed together. This is due to the transactional model of the installation, which doesn't actually commit to the GAC until the end of the script so that rollback can remove the GAC assemblies.
Great Article!
Great Article!
Updating Assemblies
Updating Win32 Assemblies
Use the following guidelines when you update Win32 assemblies:
Updating .NET Framework Assemblies
Use the following guidelines when you update .NET Framework assemblies.
Source: MSDN
Microsoft MVP [Setup-Deploy]
Weblog: www.msigeek.com
Assembly Rollback Phenomenon
A two-step process extends the Windows Installer's transaction model to products containing common language runtime assemblies. This enables the installer to rollback unsuccessful installations and removals of assemblies.
During the first step, the Windows Installer uses the Microsoft .NET Framework to create one interface for each assembly. The Windows Installer uses as many interfaces as there are assemblies being installed. Committing an assembly using one of these interfaces only means that the assembly is ready to replace any existing assembly with the same name, it does not yet replace it. If the user cancels the installation, or if there is a fatal installation error, the Windows Installer can still rollback the assembly to its previous state by releasing these interfaces.
After the Windows Installer completes installing all assemblies and Windows Installer components, the installer may initiate the second step of the installation. The second step uses a separate function to do the final commit of all the new common language runtime assemblies. This replaces any existing assemblies with the same name.
Microsoft MVP [Setup-Deploy]
Weblog: www.msigeek.com
Benefits of metadata in .NET assemblies
Self-describing files
* Everything that is needed for interaction with another module
* Eliminates the need for user-written IDL files and header files
Easier interoperability and component design
* .NET languages describe their types automatically in a language neutral manner
* Can inherit code from a module in another language
* Create instances of and class written in a managed language
Metadata is extensible through attributes
* Attributes describe how types behave (e.g. [serializable]
* User-written attributes extend the metadata that a compiler would normally produce
Microsoft MVP [Setup-Deploy]
Weblog: www.msigeek.com
Side by Side Assembly
Side-by-side execution is the ability to store and execute multiple versions of an application or component on the same computer. This means that you can have multiple versions of the runtime, and multiple versions of applications and components that use a version of the runtime, on the same computer at the same time. Side-by-side execution gives you more control over what versions of a component an application binds to, and more control over what version of the runtime an application uses.
Support for side-by-side storage and execution of different versions of the same assembly is an integral part of strong naming and is built into the infrastructure of the runtime. Because the strong-named assembly's version number is part of its identity, the runtime can store multiple versions of the same assembly in the global assembly cache and load those assemblies at run time.
Source: MSDN
Microsoft MVP [Setup-Deploy]
Weblog: www.msigeek.com
Assembly Installation Mechanism
When installing assemblies to the global assembly cache, the installer cannot use the same directory structure and file version rules it uses when installing regular Windows Installer components. Regular Windows Installer components may be installed into multiple directory locations by different products. Assemblies can exist only once in the assembly cache. Assemblies are added and removed from the assembly cache atomically, and so the files comprising an assembly are always installed or removed together.
The Windows Installer uses a two-step transactional process to install products containing common language runtime assemblies. This enables the rollback of assembly installation and removal.
A two-step process extends the Windows Installer's transaction model to products containing common language runtime assemblies. This enables the installer to rollback unsuccessful installations and removals of assemblies.
During the first step, the Windows Installer uses the Microsoft .NET Framework to create one interface for each assembly. The Windows Installer uses as many interfaces as there are assemblies being installed. Committing an assembly using one of these interfaces only means that the assembly is ready to replace any existing assembly with the same name, it does not yet replace it. If the user cancels the installation, or if there is a fatal installation error, the Windows Installer can still rollback the assembly to its previous state by releasing these interfaces.
After the Windows Installer completes installing all assemblies and Windows Installer components, the installer may initiate the second step of the installation. The second step uses a separate function to do the final commit of all the new common language runtime assemblies. This replaces any existing assemblies with the same name.
Source : MSDN
Microsoft MVP [Setup-Deploy]
Weblog: www.msigeek.com
Real fruitful information..
Check this page on Assembly Installation and Management
Real fruitful information..
Cheers'
Viju
Microsoft MVP [Setup-Deploy]
Weblog: www.msigeek.com
Would you like to reply?
Login or Register to post your comment.