Application vendors who compose their applications from multiple MSI packages should find this blog interesting. Currently Windows Installer does not provide a mechanism for installing multiple packages in a single transaction. This blog will talk about how Windows Installer has exposed the ability for multiple packages and patches to be part of a single transaction. Please go through the attached slide deck to get a high level overview of what problem space this new functionality addresses.
During this phase, Windows Installer analyzes the MSI package and the machine state and composes the list of operations that need to be performed to the system to install the package. Costing is an example of an activity that is run during this phase.
During this phase, Windows Installer uses the list of operations created in the acquisition phase to change the system. As it is making those changes, it also creates a list of undo operations that it can use if the install fails. Copying the files, updating the registry keys and such are the activities performed in execution phase.
This is the time when the transaction is committed to the system. For example, committing the assemblies to the GAC, or running the commit custom actions constitute this phase. Note that this is a point of no return. Any failures here are not guaranteed to be undone.
Windows Installer supports transactional installs because it can rollback a transaction upon failure. That’s primarily because, it stores off undo operations for any changes that it makes to the system.
In this section I will use several walkthroughs to bring forth how the new MsiBeginTransaction and MsiEndTransaction API work.
1. A setup author who wants to install multiple MSI packages as part of installing a single logical product, would request the Windows Installer service to start a transaction by calling the new MsiBeginTransaction API. By calling this API, the setup author requests Windows Installer to install subsequent packages as part of the transaction that was started by the call to MsiBeginTransaction.
2. The setup.exe that started the transaction now calls MsiInstallProduct.
3. Windows Installer runs the acquisition and execution phases to the MSI package that was requested to be installed. The net effect of this is:
a. Costing actions like CostInitialize, FileCost, CostFinalize, InstallValidate are run on a per-package basis.
b. When script execution actions like InstallExecute, InstallExecuteAgain, or InstallFinalize are run, the machine state is altered, files are copied/patched/upgraded, registry keys installed/modified and the product is published.
4. Windows Installer defers the commit phase for the package until a later point of time. What this means is that if there are any assemblies or commit custom actions in this package, they will not be run now.
5. The setup.exe can queue up more packages/patches to this transaction by calling API like MsiInstallProduct, MsiApplyMultiplePatches, etc.
6. If the setup.exe is done with installing the product, it then calls MsiEndTransaction to commit and complete the transaction. At this point the commit phases of each of the packages is run in the order in which their install requests were made in steps 2 and 5 above.
This walkthrough summarizes the following aspects a multi-package transaction:
1. Acquisition and execution phases are run on a per-package basis.
2. Acquisition and execution happens right away. I.e., when a call to MsiInstallProduct returns successfully while running a multi-package transaction, you know that acquisition and execution phases were complete for that package.
3. Commit level dependencies cannot exist between packages that are part of a multi-package transaction.
4. Commit phases of all the packages that are part of a transaction are run in FIFO order. i.e., commit phase of the first package on which MsiInstallProduct was called will be run first before moving onto the commit phase of the second package.
1. A setup.exe calls MsiBeginTransaction API.
2. The setup.exe that started the transaction now calls MsiInstallProduct to install Required.msi. Let us assume this call succeeded.
3. Setup.exe now calls MsiInstallProduct to install AnotherRequired.msi. Let us assume this call also succeeds.
4. Now while doing some other work on its own, let us assume that the setup.exe determines that it should rollback the transaction. At this point, Setup.exe calls MsiEndTransaction to rollback and end the transaction.
5. At this point, Windows Installer will run the rollback operations of both AnotherRequired.msi and Required.msi in that order.
This walkthrough summarizes that:
1. Rollback can be deferred.
2. Rollback operations are executed in LIFO order.
3. The same setup.exe now calls MsiInstallProduct to install optional.msi.
4. While installing optional.msi, let us assume Windows Installer encounters an error. This error could be either because, user canceled the install or because of some other reason altogether. In any case, Windows Installer rolls back the install of optional.msi.
5. Based on the return code from MsiInstallProduct, Setup.exe learns that there was a failure while installing optional.msi. However, it chooses to continue the product install and disregard the failure due to the optional package.
6. Setup.exe now calls MsiInstallProduct to install AnotherRequired.msi. Let us assume this call succeeds.
7. When Setup.exe is done with installing the product, it calls MsiEndTransaction to commit the transaction. At this point, Windows Installer will run the commit phases of both Required.msi and AnotherRequired.msi.
This walkthrough summarizes that every package/patch install run during a multi-package transaction is optional. Failures in those API will not rollback the entire transaction.
Subsequent blogs will attempt to capture other areas of the multi-package transaction.
[Author: Hemchander Sannidhanam]This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm.