Contents
- Package definition
- Package structure
- Package internal information
- Merge Module
- Files
- Registries
- INI Files
- Shortcuts
- Fonts
- Services
- ODBC (Open DataBase Connectivity)
- System variables
- Properties
- Running custom code from the package
- Custom Actions
- System Search
- Upgrades
- Patching
- Upgrading
- De-hardcoding and Variabilization
- De-hardcoding
- Variabilization
- Vendor MSI
- Definition
- Seller Vendor Customization
- Direct vendor MSI
- Vendor MSI hidden in setup
- Vendor MSI with patch
- Modify an MSI vendor, from cab outside to cab inside, etc.
- Msiexec.exe commands
- Installing a package
- Repairing a package
- Uninstalling a package
- Administrative Installation
- Creating logs
- Applying a patch over a MSI
- Installation with MST
- Active-Setup Mechanism
Registries
Registries are a database that keeps different settings of the operating system.
They contain information and settings for all hardware devices, software products from the system, users, etc. When a user modifies certain settings from the Control Panel, extensions, system policies, or from other installed applications, those modifications are found inside registries.
The structure of the registries
Registries are divided into a number of logical sections or “keys”. They will have the name by which they were accessed with Windows API -- it starts with “HKEY”(Abbreviation from “Handle to Key”); often they are abbreviated with a name formed of 3-4 letters which starts with “HK”. The Windows operating system contains two hives: HKEY_LOCAL_MACHINE and HKEY_USERS, just for easy access to the information the Registry Editor shows 5 hives:
- HKEY_CLASSES_ROOT
- HKEY_CURRENT_USER
- HKEY_LOCAL_MACHINE
- HKEY_USERS
- HKEY_CURRENT_CONFIG
Each of those “keys” is divided into “subkeys”, which can contain other subkeys. Also, any key can contain entrances with different values.
The values of those entrances can be as following:
- String
- Binary
- DWORD (a number between 0 and 4.294.967.295[232-1])
- Multi-String
- Expandable
Registry keys are specified with a syntax similar to Windows paths, using backslashes to indicate the hierarchical level.
For example, HKEY_LOCAL_MACHINE\Software\Microsoft\Windows refers to the “Windows” subkey of the “Microsoft” subkey of the “Software” subkey of the HKEY_LOCAL_MACHINE key.
Values are not referenced by this syntax. Value names can contain “\”, leading to ambiguities when referenced using the above syntax.
The HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER nodes have a similar structure, the applications look for their settings in the keys HKEY_CURRENT_USER\Software\Vendor’s name\Version\Settings name and if the settings are not found, they then search in the same location but using HKEY_LOCAL_MACHINE.
When writing the settings, the procedure is reversed - the settings are first written in HKEY_LOCAL_MACHINE, but if they do not have rights to write here, then the setting gets stored in HKEY_CURRENT_USER.
HKEY_CLASSES_ROOT
Abbreviated HKCR, HKEY_CLASSES_ROOT stores information about registered applications, including file associations (extensions), and registries that help record the files used by applications.
Starting with Windows 2000, HKCR is a compilation of HKCU\Software\Classes and HKLM\Software\Classes.
If a certain value is in both subkeys, then the one in HKCU\Software\Classes is used.
Any change in HKEY_CLASSES_ROOT actually occurs in the corresponding CLASSES subkeys (either HKCU or HKLM). The same rule applies the other way around.
If a certain value is in both subkeys, then the one in HKCU\Software\Classes is used.
Any change in HKEY_CLASSES_ROOT actually occurs in the corresponding CLASSES subkeys (either HKCU or HKLM). The same rule applies the other way around.
HKEY_CLASSES_ROOT contains two types of data:
1. Keys and values that associate extensions with various programs (extension - a series of keys that begin with a period, except for the first key with *. These keys can contain any number of characters.)
2. The configuration data of COMs, Visual Basic programs, etc.
This configuration data uses:
- Program Identifiers (ProgID) - subkeys in HKEY_CLASSES_ROOT that define actions that can be performed by various programs on a file: bat file, doc file, inifile. Some identifiers associate programs with COMs.
- Other classes of information that uniquely identify a COM, such as an ActiveX control (CLSID, Interface, TypeLib, AppId, etc.). Ex: HKCR\ CLSID contains all class identifiers. Each identifier is a unique number of 16 bytes.
HKEY_CURRENT_USER
Abbreviated HKCU, HKEY_CURRENT_USER stores settings that are specific to the user currently logged in to the machine. HKCU is a mirror of the current user’s registry in HKEY_USERS.
HKEY_LOCAL_MACHINE
Abbreviated HKLM, HKEY_LOCAL_MACHINE stores settings that apply to all users on that machine. This key is found in the %SystemRoot%\System32\Config\system file on the NT-based version of Windows. Hardware information is located under the SYSTEM key.
HKEY_USERS
Abbreviated HKU, HKEY_USERS stores the corresponding HKEY_CURRENT_USER subkeys for each user registered on the machine.
Under HKEY_USERS, you can see which settings are applied for all users on the machine, while HKEY_CURRENT_USER only shows a small portion of the HKEY_USERS hive -- the portion for the current logged in user.
HKEY_CURRENT_CONFIG
Abbreviated HKCC, HKEY_CURRENT_CONFIG stores information during run; the information in this section is not permanently stored on the hard disk, but regenerated when the system starts.
Editing registry
Manual editing
You can manually edit the Registry using the regedit.exe or regedt32.exe programs. Note that negligent editing of registries often leads to irreversible errors, so it is recommended to always have a backup of them.
Command-line editing
You can manipulate the Registry from the command line using the reg.exe utility-- which is included within Windows and can be downloaded separately.
A reg file (a standard file for storing the registry that can be edited) can be imported from the command line, using the syntax “Regedit /s file”, where /s leads to the addition without asking the user for input (silent).
If the /s parameter is omitted, then the user will need to confirm the operation.
When using the /s regedit parameter, it does not return an error code if the operation fails as reg.exe does.
Registry permissions can also be manipulated through the command line using the subinacle.exe utility.
For example:
subinacl.exe /keyreg HKEY_LOCAL_MACHINE\software /grant = Administrator
Gives full access to the administrator account on these keys.
Script editing
Some languages, such as VBScript, provide functions for editing/manipulating the registry.
To add a registry key with VBScript, you must use the RegWrite function:
Set WshShell = WScript.CreateObject(“WScript.Shell”)
WshShell.RegWrite “HKCU\KeyName\”,””, “REG_SZ”
To delete a registry key with VBScript, you must use the RegDelete function:
Set objShell = Wscript.CreateObject(“Wscript.Shell”)
objhell.RegDelete “HKCU\Control Panel\Desktop\MyValue”
To read a registry key with VBScript, you must use the RegRead function:
strLogonServer = “HKEY_CURRENT_USER\Volatile Environment\LOGONSERVER”
strDNSdomain = “HKEY_CURRENT_USER\Volatile Environment\USERDNSDOMAIN”
Set objShell = WScript.CreateObject(“WScript.Shell”)
WScript.Echo “Logon server: “ objShell.RegRead(strLogonServer)
WScript.Echo “DNS domain: “ objShell.RegRead(strDNSdomain)
Location of registries
The Registry is stored in several files. Depending on the version of Windows you’re using, there are different files and different locations on the machine.
In Windows, the following files that store registry can be found in %SystemRoot%\System32\Config:
- Sam - HKEY_LOCAL_MACHINE\SAM
- Security - HKEY_LOCAL_MACHINE\SECURITY
- Software - HKEY_LOCAL_MACHINE\SOFTWARE
- System - HKEY_LOCAL_MACHINE\SYSTEM
- Default - HKEY_USERS\Default
- Userdiff
The following files are found in the specific directory of each user:
%UserProfile%\Ntuser.dat - HKEY_USERS\<User SID>
%UserProfile%\Local Settings\Application Data\Microsoft\Windows\Usrclass.dat - HKEY_USERS\<User SID> _Classes
Registry specific tables
In MSI, you have two series of tables for Registry:
- specific tables that register COMs and extensions (AppId, Class, Extension, MIME, ProgId, TypeLib, Verb) and
- tables that add Services, drivers or ODBCs (ODBCAttribute, ODBCDriver, ODBCDataSource, ODBCSourceAtribute, ODBCTranslator, ServiceInstall).
The Registry table contains the rest of the registry that cannot be included in the tables mentioned above.
When populating registry tables, it is important to try to minimize the number of registries placed in the Registry table and maximize the use of advertised tables.
Windows Installer does not distinguish between the various keys in the registry table and cannot use the internal logic needed to take advantage of some Windows Installer advantages (such as “advertising” for example).
The tables containing the registry are interconnected and dependent on each other as seen on the diagram below. The figure also shows the Component, Feature, File and Icon tables. They are not part of the group of tables that contain the registry, but are entered in the schema to highlight the logic of the schema
Later in this book, we will discuss the second series of tables.
Extension
The Extension table contains information about file name extension servers that must be generated as a part of product advertisement.
Columns:
Extension
- the extension associated with this entry
- must not exceed 255 characters
- the dot does not appear in the name of the extension
ProgId
- program ID associated with this extension
- external keys in the ProgId table
Feature
- foreign key in the Feature table
Component
- foreign key in the Component table
- this column controls the installation of the extension
MIME
- foreign key in the MIME table
- the content type associated with this extension
ProgId
This table associates program identifiers with class identifiers.
ProgID columns:
ProgId - program id or version-independent program id.
The progId will be written to the registry only if that progid has an associated CLSID (Class table, ProgId_Default column) or if the progid has an associated extension (Extension table, ProgId_ column), and that extension has an associated verb (Verb table).
ProgId_Parent
- defined only for independent version program ids
- is a foreign key in the ProgId column.
ProgId_Parent is defined for the version-independent program IDs. This field is the foreign key in the ProgId column. To define an independent program ID, the ProgId_Parent field must be filled into the corresponding ProgId.
Version Independent Program IDs are written to the registry only when they function in association with a CLSID. The ProgId’s child no longer needs to be associated with its CLSID (Class_ column in the ProgId table), only the parent needs to be associated with the CLSID.
Observation: The ProgId table only knows how to register one child of a ProgId. If a ProgId has more than one child and you try to register all of them in the table, you will see that the table records only one child. If you have this situation, register only one child in the table, and associate the other children with CLSID in the table and the HKCR registry\product_name\CurVer write it from the Registry table.
Class
- a foreign key in the Class table
- this column must be null for an independent program id version
The Class_ column is the foreign key in the Class table. This column must be Null for a version independent program ID (ProgId son).
If this field is Null, the program ID will be registered via the Extension table (ProgId_ column), if that extension has an associated verb (Verb table). ProgIds registered in this way do not know how to register ProgId son
Description - a short description associated with this program id
Icon
- foreign key in table Icon
- specify the icon associated with this program id
- this column must be empty for an independent program id version
IconIndex
- the icon index
- this column must be null for an independent program id version
Verb
This table associates various actions with the extensions in the Extension table.
Verb columns:
The Extension_ column represents the extension associated with that verb. This field is the foreign key in the Extension table.
The Verb column represents the verb associated with the respective extension. The following equivalent registry is written:
HKEY_CLASSES_ROOT\ProgId_name\shell\verb_name
The Command column represents the text displayed by the context menu of the extension (right click on the extension: e.g. Open, Edit, Print).
Argument column - in this field you can define a property in the MSI -- the value of the property will be written in the registry.
The following equivalent registry is written in:
HKEY_CLASSES_ROOT\ProgId_name\shell\verb_name
This registry has the value: the keypath file on the component to which the argument value extension belongs to.
For example, if the default registry has the value:
“C:\Program Files\ABC\abc.exe” “%1” “C:\Program Files\ABC\abc.exe”
Then “C:\Program Files\ABC\abc.exe” is the path to the keypath file on the component that belongs to the extension, and “%1” “C:\Program Files\ABC\abc.exe” is the argument.
Observation: If you write [!Filename] in the registry (in the Argument column), it will write a long path. It seems that the installer does not know how to read the shortcut in this column, although its type is Formatted.
The Sequence column represents the sequence of commands associated with an extension. The verb with the smallest sequence becomes the default verb of that extension.
It appears in the registry as follows:
HKEY_CLASSES_ROOT\program_name\shell
Note: This table is referenced by the standard RegisterExtens and UnregisterExtensionInfo actions.
TypeLib
This table provides information for registering type libraries.
LibID | Language | Component | Version | Description | Directory | Feature | Cost |
TypeLib columns:
The LibID GUID column identifies the TypeLib. In the registry it is written at the location:
HKEY_CLASSES_ROOT\typelib\{Identificator_TypeLib}
The Language column represents the language of Typelib. It must be a non-negative number (e.g. 0, 1).
The Version column represents the typelib version. “Minor version” and “Major version” are 4-byte encodings. “Minor version” is represented by the last 8 bits. “Major version” is represented by the 16 bits located in the middle.
Example:
If the version of a Typelib is 1.2 in the table we will write the value 258 for the following reasons:
- 2 in binary (base 2) is 10
- 1 in binary is 1
So in 4-byte transcription it would be: 00000000 00000000 00000001 00000010. If you turn this number into base 10, it will result in 258, the value to be written in the table (in the Version column).
In the registry, it will be written as follows:
HKEY_CLASSES_ROOT\typelib\{Identificator_TypeLib}\Typelib_Version
The Directory_ column is the foreign key in the first column of the Directory table. In the registry, it will be written as follows:
HKEY_CLASSES_ROOT\typelib\{Identificator_TypeLib}\ Typelib_Version\HELPDIR
The Feature_ column is the foreign key in the first column of the Feature table. This column specifies the Feature that must be installed for a TypeLib to be operational.
The Component_ column is the foreign key in the first column of the Component table. This column identifies the component whose keypath is the typelib to be registered. In the registry, it is written to the key <default> from the location:
HKEY_CLASSES_ROOT\typelib\{Identificator_TypeLib}\Typelib_version\0\Win32
The <default> registry in the above location has the value: path to the file that is the keypath of the component.
The Description column represents the description of the Typelib. In the registry, it is written in the key <default> from the location:
HKEY_CLASSES_ROOT\typelib\{Identificator_TypeLib}\Typelib_version
The Cost column represents the cost associated with registering a Typelib in bytes. This field must be a positive or null number.
Remarks:
- This table is referenced by the standard actions RegisterTypeLibraries and UnregisterTypeLibraries. The standard RegisterTypeLibraries custom action needs the typelib language (Language column in the TypeLib table) to be defined correctly, otherwise, the installer will fail to register the Typelib.
- It is possible to register a Typelib without mentioning its version in the table. If you have a TypeLib with version c.0 (letter.0), you can register it from the table. You can leave the Version column Null. The installer ignores what is completed in this column. No matter what you write in this column, the registry is populated with what you need (i.e. the actual version of Typelib).
- If you fill in a description that is different from the one in the ActiveX file in the Typelib table (in the Description column), the registry will be populated with the description from the ActiveX file -- so practically the Description column is ignored.
- If we do not specify the directory that Typelib belongs to in the Directory_ column, then the HELPDIR key will have no value. So, this column must be filled. The installer will not ignore this column.
MIME
This table associates a “MIME context type” with a CLSID or extension.
The ContentType column represents the MIME content identifier. It normally appears as a type/format.
The Extension_ column is the foreign key in the Extension table and associates a MIME with an extension.
The CLSID column can be a foreign key in the CLSID table or it can be a CLSID that already exists on the machine.
In the registry it is written at:
HKCR\MIME\Database\Content Type\[MIME_Name]
HKCR\MIME\Database\Content Type\[MIME_Name]\Extension
If MIME is associated with a CLSID, the CLSID will be created at the HKCR\MIME\Database\Content Type\[MIME_Name] location.
Remarks:
- A MIME must have an associated extension (Extension_ column) to be written to the registry.
- This table is referenced by the standard registerMIMEInfo and UnregisterMIMEInfo custom actions.
SelfReg
This table provides information for self-registering files.
File_ - External key into the first column of the File table indicating the module that needs to be registered.
Cost - The cost of registering the module in bytes. This must be a non-negative number.
Class
This table provides information for registering class identifiers or COM objects
CLSID | Context | Component | Description | AppID | FileTypeMask | Icon | IconIndex | DefInprocHandler | Argument | Feature | Attributes |
A class will not be registered on the machine if one of the CLSID, Context, Component_ and Feature_ fields is not present.
The CLSID column in the table will write the following registry key on the machine:
HKCR\CLSID\<GUID>
The ProgId_Default column represents the Program ID associated with the CLSID. This column is the foreign key in the ProgID table.
The key will be created in the registry:
HKCR\CLSID\<GUID>\ProgID
A <default> key with the name of the ProgID in the ProgID table will be written in the ProgID key.
The Description column represents the description associated with the CLSID. In the registry, the associated key is the following:
HKCR\CLSID\<GUID>\<default>
The <default> key has the value in the Description column.
Note: The son of ProgID in the ProgID table will be written in the registry under the following key:
HKCR\CLSID\<GUID>\VersionIndependentProgID\<default>
The Context column will write one of the following keys, depending on the context:
HKCR\CLSID\<GUID>\LocalServer (16-bit)
HKCR\CLSID\<GUID>\LocalServer32 (32-bit)
HKCR\CLSID\<GUID>\InprocServer (16-bit)
HKCR\CLSID\<GUID>\ InprocServer32 (32-bit)
The AppId_ column contains a foreign key from the AppId table. It appears in the registry as follows:
HKCR\CLSID\<GUID>\APPID
The AppID registry key has the following value: The AppId GUID in the AppId table.
The FileTypeMask column appears in the registry in the following key:
HKCR\FileType\<GUID>
If there are several patterns, they must be delimited by a semicolon (;) , and numeric subkeys will be generated dynamically: 0,1,2, etc.
The Icon_ column represents the icon associated with the CLSID ( which represents a foreign key in the Icon table, where the icons are registered binary as streams). It appears in the registry as follows:
HKCR\CLSID\<GUID>\DefaultIcon
The <default> key in the path above will have the following value:
C:\WINDOWS\Installer\[ProductCode]\icon_name_from_Icon_Table, IconIndex
The IconIndex column represents the icon index. It can be NULL, and there must only be positive numbers.
The Feature column represents the Feature to which the CLSID belongs (foreign key in the Feature table).
The Component_ column specifies the component to which the respective class belongs to. The keypath on this component represents the file in which that class will type.
DefInprocHandler column - this field must be Null if in the Context field we have InprocServer or InprocServer32 (if it is not Null, we will have validation errors). This field can have the following values:
Value | Description |
Non-numeric value | The installer treats a non-numeric value from the DefInprocHandler field as a system file that serves as the “process handler” specified by the registry key: HKCR\CLSID\<GUID>\InprocHandler32 |
Null | The Argument and DefInprocHandler fields can be Null for LocalServer and LocalServer32 contexts. |
1 | The default 16-bit process handler (ole2.dll); In the registry, the default key in HKCR\CLSID\<GUID>\InprocHandler will have the value ole2.dll. |
2 | The default 32-bit process handler (ole32.dll); The default registry key in HKCR\CLSID\<GUID>\InprocHandler32 will have the value ole32.dll. |
3 | It will create both the 16-bit and the 32-bit process handler; The registry keys are: HKCR\CLSID\<GUID>\InprocHandler and HKCR\CLSID\<GUID>\InprocHandler32 |
Argument column - an argument appears at a CLSID only if the context of that class is LocalServer or LocalServer32 (otherwise validation errors will occur). In this field, you can add a defined property in the MSI which will write in the following registry key:
HKCR\CLSID\<GUID>\LocalServer
or
HKCR\CLSID\<GUID>\LocalServer32
Remarks:
- If in the context of a class we have LocalServer or LocalServer32, then the value of the default registry in HKCR\CLSID\<GUID>\LocalServer or HKCR\CLSID\<GUID>\LocalServer32 will be the shortcut to the file that is a keypath on the component (in which case, the attribute of the respective class is set to 0)
- If in the context of a class, we have InprocServer or InprocServer32, then the default registry value in HKCR\CLSID\<GUID>\InprocServer or HKCR\CLSID\<GUID>\InprocServer32 will be a long path to the file that is a keypath on the component.
- If you write [!Filename] in the Arguments column, then a long path will be written in the registry.
Attributes column - if this field is set to 0 or Null, then the registry will be written with the keypath to the file. If the field is set to 1, then only the name of the file will be written in the registry.
AppId
To register an AppID in the registry, it is enough for a single field to be filled in, namely the AppId field (it is the only field in this table that cannot be Null). However, the AppID must be associated with a CLSID (the AppId column in the Class table must be completed).
The AppID table is used to register various configurations for DCOMs
AppID | RemoteServerName | LocalService | ServiceParameters | DllSurrogate | ActivateAtStorage | RunAsInteractiveUser |
AppId column - appears in the registry: HKCR\AppID\<GUID_AppID>\ and in the key GUID_AppID in HKCR\CLSID\<GUID_CLSID>\ (The AppId is associated with the CLSID in the Class table, the AppId column).
Observation: In order for an AppId to be registered in the HKCR\AppID\<GUID_AppID>\ registry key, that AppId must be associated with a CLSID in the Class table (AppId column).
RemoteServerName column - in this field you can add the value of a property. The RemoteServerName key is written to HKCR\AppID\<GUID_AppID>\.
LocalService column - in the registry, the LocalService key will be written in HKCR\AppID\<GUID_AppID>\.
ServiceParameters column - in the registry, the ServiceParameters key will be written in HKCR \ AppID \ <GUID_AppID> \.
DllSurrogate column - the DllSurrogate key will be written to HKCR\AppID\<GUID_AppID>\ in the registers.
ActivateAtStorage column - in the registry, the ActivateAtStorage key will be written in HKCR\AppID\<GUID_AppID>\. If the value of this field is 0, the ActivateAtStorage key will not be written to the registry. If the value of this field is 1, the ActivateAtStorage key will take the value Y (“ActivateAtStorage” = “Y”).
RunAsInteractiveUser column - the RunAs key will be written to HKCR\AppID\<GUID_AppID>\ in the registry. If the value of this field is 0, the RunAs key will not be written to the registry. If the value of this field is 1, the RunAs key will take the value InteractiveUser (“RunAs” = “Interactive User”).
Observation: The AppId table does not know how to register the Default key in HKCR\AppID\<GUID_AppID>\. If this key has a certain value, you must register it from the Registry table.
Registry
This table contains the registry information required for the applications.
Registry Table Columns:
Registry - the primary key that uniquely identifies the line
Root
- the predefined section of the registry
- Root can have one of the following values:
0 = HKEY_CLASSES_ROOT
1 = HKEY_CURRENT_USER
2 = HKEY_LOCAL_MACHINE
3 = HKEY_USERS
Key - the path of the registry to be created
Name
- the name of the register to be created
- If this column is null, the date in the Value column is written in the default register of this register.
Value - the data contained in the register
Component
- foreign key in the Component table
- this component controls the creation of the register
RemoveRegistry
RemoveRegistry contains information that the application needs to delete during installation.
RemoveRegistry Columns:
RemoveRegistry - unique identifier for the line
Component
- the foreign key in the Component table
- this component controls the deletion of the register referred to in the entry
Root - can have one of the following values:
0 = HKEY_CLASSES_ROOT
1 = HKEY_CURRENT_USER
2 = HKEY_LOCAL_MACHINE
3 = HKEY_USERS
Key - the path of the registry to be deleted
Name - the name of the registry to be deleted
Advanced Installer offers an easy way to add/edit your registry entries from the Registry Page.