Install-MSIProduct / Uninstall-MSIProduct retrieve action result ?

Topics: Comments
Dec 10, 2014 at 11:07 AM

How can I get the install / uninstall action result ?

MSI has a wide range of return codes, where is that available ?

Dec 13, 2014 at 5:29 AM
Any installer errors are returned to the error pipeline as with any cmdlets, so you could check the $error variable and get the error code from that.
Marked as answer by heaths on 12/12/2014 at 9:29 PM
Jan 9, 2015 at 1:05 PM
I can see in your source you write a Win32Exception(3010) object to the warning pipe if a system reboot is required.
Shall I capture this exception via a WarningVariable ? There is probably a chance multiple objects to the warning pipe written.
Have you might thought some different approach to detect this reboot request ?
Jan 12, 2015 at 4:29 AM
What if I returned some sort of Result object that contained the raw error code and whether to reboot or not?
Jan 13, 2015 at 4:46 PM
Yes, by adding -PassThru you return a ProductInstallation object, however I have no attribute found holding these information.
Jan 14, 2015 at 7:49 AM
Right. Such functionality doesn't exist. I was asking if that would be suitable. :)
Jan 14, 2015 at 1:06 PM
Yes, that would be facilitate to communicate with other scripts. There could be three MSI return codes related to reboot, such as
  • 1641 # A restart is required to complete the installation. This message indicates success.
  • 3010 # A restart is required to complete the installation. This message indicates success.
  • 5100 # The user's computer does not meet system requirements OR yet a concurent installer is running
    if (PendingFiles)
Could you estimate a milestone when this Result object will be available ?

Jan 14, 2015 at 4:54 PM
There's also 1310, though you can't do much with it.

Right now I'm revamping for a major release and considering oneget/chocolatey only, so it might be a few weeks since I have some other things I need to finish as well.

Feb 25, 2015 at 10:44 AM
Edited Feb 25, 2015 at 10:45 AM
Howdy !

Do you have a road map for the following versions ? I guess being able to communicate with other processes would be an advantage, e.g. returning the MSI code and the reboot request (in a single object).

Best Regards,
Feb 26, 2015 at 6:50 AM
I could probably do a one-off for now as I'm involved with a lot of other projects currently and haven't had time to finish the major upgrade to this project.

Regarding 5100, that's actually an error code that we (VS Setup team) defined that indicates any block has occurred. It still exists today but wrapped as an HRESULT. Technically, it formats as simply "Asia" and is entirely proprietary so it won't indicate a reboot is required here. I will return the raw error codes, though. I'm just considering whether to return one Result object for each install or all up for the entire cmdlets.
Mar 22, 2015 at 12:20 AM
Does this work: ?

I played around with a bunch of different options and ultimately went with a separate variable name (much like -ev or -wv) because piping a new object breaks the old convention (not to mention my unit and functional tests that caught the change in behavior). It also supports a "+" character to "append" results (basically, once a reboot is initiated or required the variable / properties will always be true - at least within the same session).

So you can still capture errors (separately, if desired as in the following example) and the operation result without trawling through the errors:
install-msiproduct -chain 1.msi, 2.msi -resultvariable installResult -ev installErrors
if (-not $installErrors.count -and $installResult.RebootRequired) {
  # reboot
To note, if RebootInitiated is $true RebootRequired will be too (to make it easy to check for one).

If that satisfies your requirements, I'll prop this last version of 2.x (will be 2.3.1) and merge it into the 3.x branch for future versions.
Apr 29, 2015 at 1:16 PM
I created a test MSI package of IE 11 to assure a system reboot will be required at the end of installation.
Even though the MSI required a system reboot and I chose "Restart Later" the .RebootRequired was False, so there was no warning.
Install-MSIProduct P:\IE11-Setup-Full.msi -resultvariable installResult -ev installErrors
if (-not $installErrors.Count -and $installResult.RebootRequired)
  Write-Warning "IE 11 installed and reboot required."
I can send you the test package if you need.
Aug 15, 2015 at 6:03 PM
Edited Aug 15, 2015 at 6:05 PM
I just tried it with a product that runs ScheduleReboot and it worked fine. Since IE11 is not Windows Installer based, are you sure that it told Windows Installer itself it needs a reboot? If you look at the MSI log, it should return 3010. Also, since you didn't provide -Chain - which is the only time the code passes REBOOT=ReallySuppress - and you didn't mention your machine rebooted automatically (which it would by default if Windows Installer were told a reboot was required), I'm guessing the problem is in your package.

Here are my results
PS> install-msiproduct .\bin\Reboot.msi -chain -ResultVariable rv
WARNING: Could not create a system restore point: Access is denied
WARNING: The requested operation is successful. Changes will not be effective until the system is rebooted
PS> $rv

RebootInitiated RebootRequired
--------------- --------------
          False           True
See commit 91e13e3c0c90798aec14d1a142177b9c35d64ad4 for my sample, and check that however you're installing IE11 within Windows Installer is correctly handling reboots as Windows Installer knows. For example, if you're running the IE11 EXE installer as a custom action, you have to run ScheduleReboot yourself.

There is no universal way in Windows to record reboots required, and each package manager including wusa.exe has its own way of recording that reboots are required. Since these cmdlets are focused on Windows Installer, it only cares if Windows Installer itself requires (or initiates) a reboot.