Contents
![Book cover](png/msi_book_cover.png)
Debugging
It’s possible that the package we create has some issues: either it does not work properly, does not install, does not properly self-heals or self-repairs, or even fails to uninstall. So, here’s what we need to do when that happens.
Logs
First, we need to find the issue. The easiest way to determine where a package is cracking is to log in and read the log ( preferably at the time of the error as it will be easier to identify the cause then).
The msiexec.exe executable provides a parameter for creating logs, during any stage of the application (installation, repair, uninstallation). This is / l, with related sub-parameters.
![Windows Installer Help Windows Installer Help](png/windows-installer-help.png)
![Log File example Log File example](png/log-file-example.png)
Windows Installer also automatically creates package logs in the current user’s temp directory. But to do this, we need to set the value of two registries, namely:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE \ SOFTWARE \ Policies \ Microsoft \ Windows \ Installer]
“Debug” = dword: 00000007
“Logging” = “voicewarmupX”
Analyzing the log file
The installation of an MSI file takes a series of actions. These can be standard actions or custom actions. Each action performed has an associated Return Value. The possible return values are:
Value | Meaning |
0 | Action not executed |
1 | Success |
2 | User canceled |
3 | Fatal Error |
4 | Suspended, waiting for reboot |
Looking at the table above, you can see that a return value of 3 is useful. In the Notepad, use the Find command and search for value 3. You may find various instances of return value 3 in the log file, so you have to determine which one caused the installation to abort. To do that, when the return value 3 is found in the file, start reading upwards from the error in the log file and see what actually caused it.
If a fatal error occurs and the installation aborts, the MSI package initiates a rollback procedure. If the installation is unsuccessful, the installer automatically performs a rollback installation that returns the system to its original state.
By manually searching through the log file, you may encounter a bunch of continuous lines with FileRemove or ComponentUnregister.
Rollback is important because the fatal error that caused the install to fail typically occurs right before the rollback process begins. Also, you can simply search through the log for Rollback.
So, for each standard action or custom action executed, its return value is displayed in the log (e.g. Action ended 16:34:29: InstallFiles. Return value 1.).
In the example above, we see that the return value for the InstallFiles standard action was 1, meaning that the action completed successfully. If this action failed and caused an error, we would have a return value of 3 -- causing the rest of the installation to stop and the rollback process to begin (which would turn the system back to the same state it was before the installation began).
So, as a general rule, if an MSI installation fails, it’s recommended to first open the log, search for return value 3 and see where the log points.
Checking the Installation Status of Features and Components
The verbose log includes an entry for each feature and component the installation package may install. The log tells us what the state of a feature or component was prior to the installation, the state that was requested by the installation, and how the installer left the feature or component.
Features and components entries appear in the log as in the following example:
MSI (s) (C8:0C): Feature: myFeature; Installed: Absent; Request: Local; Action: Local
MSI (s) (C8:0C): Component: myComponent; Installed: Absent; Request: Local; Action: Local
In the verbose log, you will see that:
- The installation state of the feature and component was absent before running the package.
- The installation package requested a local installation of these features and components
- The feature and component were both installed locally.
The following table summarizes the possible component or feature states that can appear in the log:
Log entry | Value | Description |
Installed | Local | The component or feature is currently installed to run locally. |
Installed | Source | The component or feature is currently installed to run from source.|
Installed | Advertise | The feature is currently advertised. Only features can be advertised, components cannot. |
Installed | Absent | The component or feature is not currently installed. |
Request | Null | No request. |
Request | Absent | Installation requests the component or feature to be uninstalled. |
Request | Local | Installation requests the component or feature to be installed to run locally. |
Request | Source | Installation requests that the component or feature to be installed runs from source. |
Request | Advertised | Installation requests the feature to be installed as an advertised feature. |
Request | Reinstall | Installation requests the feature be reinstalled. Components do not use reinstall state. |
Request | Current | Installation requests the feature to be installed in the default authored install state. |
Action | Null | No action is done. |
Action | Absent | The installer actually uninstalls the component or feature. |
Action | Local | The installer installs the component or feature to run locally. |
Action | Source | The installer installs the component or feature to run from source. |
Action | Advertised | The installer installs the feature as an advertised feature. |
Action | Reinstall | The installer reinstalls the feature. |
Action | Current | The installer installs the feature in the default authored install state. |
Action | FileAbsent | The installer uninstalls the component's files and leaves all other resources of the component installed. |
In order to check for the features and components states, please search for the InstallValidate standard action. After the standard action is marked as the current action being executed, the features and components state are displayed on the following lines in the log.
Tips for log reading
The verbose log gives you useful information about the installation process. For example:
“Disallowing uninstallation of component: GUID’s component since another client exists”
This can happen if the same components are shared between multiple packages installed on the same machine. Windows Installer keeps a refCount of the components and does not allow removing them until all the applications that use them are removed.
Also, this may happen if you duplicate a project file (saved under a different name or by using the “copy-paste” method). It is strongly recommended to not do this because the created project will have the same GUIDs (Upgrade Code, Product Code, components ID) as the source/original project. To avoid this, you must use the Save as template option.
If there are files missing from the installation folder during an upgrade operation, search through the log for the following message:
“Disallowing installation of component: GUID’s component since the same component with higher versioned keyfile exists”
If you find it, this is the reason why your file is not copied on the target machine.
The upgrade process performs the following actions:
- Detect and completely remove older products. During this operation, the file will be removed from the machine.
- Install the new product. The file from the upgraded version will not be installed since its component was not marked for installation.
To overcome this behavior, you can enable the Always overwrite existing file option from the File Operations Tab of the File Properties.
“MSI (s): File: C:\MyApp\MyExe.exe; Won’t Overwrite; Existing file is of an equal version”
This indicates that the installation package will not overwrite the existing file since it is the same version as the one being installed.
For a comprehensive understanding on how to read a Windows Installer verbose log file, check out this article.
Event Viewer
A variant proposed by the operating system to detect where an application cracks, is the event viewer (Control Panel \ Administrative Tools).
![Event Viewer Event Viewer](png/event-viewer.png)
The errors made by our package can be identified quite quickly, looking at the time they appeared, or at the references to MsiInstaller.
For each error, the event viewer provides two entries.
The first window tells us which package the entry refers to, and the second one, what caused the error. Although they may seem difficult to read, the package is easily identified with the product code.