Get-MsiExitCodeMessage: Get message for MSI exit code by reading it from msimsg.dll

Topics: Archive - Toolkit Extensions
Jul 31, 2014 at 3:29 AM
Edited Jul 31, 2014 at 3:34 AM
This function uses Write-Log and Write-ErrorStack functions posted in another thread in Toolkit Extensions.

You can use this function in the Execute-Process function in the following manner to automatically translate all MSI exit codes:
    Write-Log -Message "Execution failed with exit code [$returnCode]" -Component ${CmdletName} -Severity 3
    If ($FilePath -match 'msiexec')
        Get-MsiExitCodeMessage -MsiErrorCode $returnCode
Function Get-MsiExitCodeMessage
        Get message for MSI error code
        Get message for MSI error code by reading it from msimsg.dll
    .PARAMETER MsiErrorCode
        MSI error code
        Get-MsiExitCodeMessage -MsiErrorCode 1618
        ${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
        $MsiErrorCodeMsgSource = @"
        /// Get error message from msimsg.dll resource dll
        using System;
        using System.Text;
        using System.Runtime.InteropServices;
        public class MsiErrorCode
            public static string GetMessageFromMsiErrCode(uint errCode) 
                string libPath = "msimsg.dll";
                IntPtr hModuleInstance = LoadLibraryEx(libPath, IntPtr.Zero, LoadLibraryFlags.LOAD_LIBRARY_AS_DATAFILE);
                StringBuilder sb = new StringBuilder(255);
                LoadString(hModuleInstance, errCode, sb, sb.Capacity + 1);
                return sb.ToString();
            static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, LoadLibraryFlags dwFlags);
            enum LoadLibraryFlags : uint
                DONT_RESOLVE_DLL_REFERENCES         = 0x00000001,
                LOAD_IGNORE_CODE_AUTHZ_LEVEL        = 0x00000010,
                LOAD_LIBRARY_AS_DATAFILE            = 0x00000002,
                LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE  = 0x00000040,
                LOAD_LIBRARY_AS_IMAGE_RESOURCE      = 0x00000020,
                LOAD_WITH_ALTERED_SEARCH_PATH       = 0x00000008
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            static extern int LoadString(IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax);

        If (-not ([System.Management.Automation.PSTypeName]'MsiErrorCode').Type)
            Add-Type -TypeDefinition $MsiErrorCodeMsgSource -Language CSharp
            Write-Log -Message "Get message for MSI error code [$MsiErrorCode]" -Component ${CmdletName} -Severity 1
            [string]$MsiErrorCodeMsg = [MsiErrorCode]::GetMessageFromMsiErrCode($MsiErrorCode)
            Write-Output $MsiErrorCodeMsg
            Write-Log -Message "Failed to get message for MSI error code `n$(Write-ErrorStack)" -Component ${CmdletName} -Severity 3