How to Interpret Windows Installer Logs

[Updated: 4 April 2007]

If you have a problem with the Windows Installer or an MSI package you're installing, it's a sure bet that you will be told by some smart person to "enable logging".

That's great advice, except ... what do you do with the log once you get it? A common technique is to open it in Notepad and scroll up and down aimlessly, hoping to spot the "cause of your problem" section. While this is a very popular approach, it rarely yields good results. In this post, I'll walk you through the contents of a typical log so that next time you have an Installer problem you'll be in a better position to troubleshoot it yourself.

"Enable Logging"
First things first. If you are to take your smart friend's advice, you need to know how to generate a log. There are a number of ways to do this:

If you can install the MSI package from the command-line, even if only for troubleshooting, then this is a very easy way to generate a log. Simply use the "/l" switch during install:

msiexec /i SomeApp.msi /l*vx %temp%\SomeApp.log

Using the "*vx" modifier gives the most detail possible - you should always use this when troubleshooting.

Registry or Group Policy
If you cannot run the package from the command-line, then enable logging directly in the registry or via Group Policy, as described in KB223300: How to enable Windows Installer logging.

MsiLogging and MsiLogFileLocation properties
With MSI 4.0 these two properties can be set in the Property table of a package to enable logging and specify the log location. See MsiLogging Property for more details.

Installer API
If you are developing an Installer-aware application, you can use the MsiEnableLog API to enable logging for the lifetime of the calling process.

With so many ways to do this, it should be obvious that the Installer team take logging very seriously, and as you'll see the Installer logs a lot of information. Also, with all those methods available to you, you've really got no excuse for not using logging.

Log Contents
Once you have a log, here's what to expect it to contain:

General Contents
By default logs will contain things such as:

  • Most errors that occurred during the install including all Windows Installer errors that generate a user dialog.
  • Which custom actions were run.
  • Whether a reboot was requested and completed.
  • Values of Installer Properties, including details of any changes.
  • The source location.
  • Whether the user cancelled the install.
  • Where an install stopped.
  • Whether an install rolled back.
  • Client and Server information

The Windows Installer runs an installation in two distinct processes: Client and Server. These terms are intended to be used in the COM sense where the client and server are just different processes and not in the sense of distinct client and server computers on the network. The same log file will show information from both processes.

An action by the client process is denoted in the log by "(c)":

MSI (c) (C0:6C) [22:17:24:911]: SHELL32::SHGetFolderPath returned: C:\Users\Admin\AppData\Roaming

An action by the server process is denoted in the log by "(s)":

MSI (s) (38:90) [22:18:04:544]: Doing action: LaunchConditions

The "(30:90)" notation represent the "(processID:threadID)" that generated the entry. Only the last 2 (hexadecimal) digits of the process and thread IDs are given. For example, (30:90) could be generated by process ID 130 and thread ID 290. The time of the log entry is shown next in square brackets.

The log file will first show the client process as dialogs collect user information. After the user information is collected, it is time to do the setup work and the installation switches to the server process. For installations run with no visible UI, the client process is skipped:

MSI (c) (E4:F0) [22:52:31:105]: Client-side and UI is none or basic: Running entire install on the server.

The beginning of the server process looks very similar to the beginning of the client process. The service must re-evaluate all of the settings, to prevent a user from performing insecure operations. All of the private properties, policies, and other installation state settings must be re-evaluated.

Error Codes
The Installer logs a lot of useful information in the form of 'error' codes. Sometimes these are genuine errors, but often they are simply for information purposes and do not indicate a real problem. Full details of all codes can be found in the MSDN Library or the Windows Installer SDK.

As an example, take the following entry from the annotated log below:

MSI (c) (C0:6C) [22:17:24:953]: Note: 1: 1402 2: HKEY_CURRENT_USER\Software\Microsoft\MS Setup (ACME)\User Info 3: 2

The SDK defines the code 1402 as:

Could not open key: [2]. System error [3].

Thus we would read the log entry as:

Could not open key: HKEY_CURRENT_USER\Software\Microsoft\MS Setup (ACME)\User Info. System error 2.

System error codes can be found in the Platform SDK file Winerror.h or using the Net HelpMsg command:

In this case error code '2' resolves to "The system cannot find the file specified."

C:\>net helpmsg 2

The system cannot find the file specified.

Return Values
After each action the Installer will record the 'return value' in the log. This is an indicator of the success or otherwise of the action. Possible values are:

Value Meaning
0 Action was invoked, but did not run (not necessarily a bad thing, maybe there was nothing for it to do)
1 Action was a success
2 Action was cancelled by user
3 An unrecoverable error has occurred
4 The installation was suspended awaiting a reboot

Simply searching for the phrase "Return Value 3" can be a quick way of pinpointing the errors in a log. This isn't guaranteed to lead to the source of a problem as some problems are quite subtle, but it's good first step. It may also break down in localised setup scenarios.

Annotated Verbose Installer Log
Here is an annotated Installer log to use as a reference during your own troubleshooting:

Annotated Windows Installer Log (.docx)

Annotated Windows Installer Log (.pdf)

This log was generated by installing the Debugging Tools for Windows on Windows Vista Ultimate (so MSI 4.0).

Installer logs tend to contain a lot of repeated entries. For example, all file copy operations look alike. So to make understanding the log easier most of the repetition is omitted and only useful examples of each entry type are shown; the original log contained over 5900 entries, but this reduced log contains around 1000. This is a lot less, but is still too much for a simple blog post, hence the downloadable file.

If you've used Installer logging before, then you probably read to this point thinking "why not just use Wilogutl?". It's a good question and the reason I think you should work with the logs directly is encapsulated in number 1 rule of using the Windows Installer:

Rule 1: Learn the Windows Installer Technology

The importance of this rule cannot be overstated. If you only follow one rule, this is the one to choose.

Microsoft Product Support often speak to Installer users who are installing packages which they created with a sophisticated high-level re-packaging tool, without any understanding of how the Installer actually works. While these tools are excellent at what they do and they abstract the user from the details on a day-to-day basis, the lack of Installer knowledge becomes a real problem when the package does not work as expected. Setup authoring is not simply about copying files. The Installer offers extensive functionality and complexity; understand it before you start authoring packages.

Reading through a lot of logs and using them to troubleshoot real problems is a great way to learn about how the Installer works. Obviously, once you're confident with the underlying technology you can return to using helpful tools to do the work for you.

If you are wondering what on Earth "Wilogutl" is, then have a look here:

Wilogutl.exe assists the analysis of log files from a Windows Installer installation, and it displays suggested solutions to errors that are found in a log file.

I won't discuss how to use Wilogutl here, but may do so in a future post.