Simple Script to find MSI errors

Here’s a simple PowerScript to pull out MSI errors out of the EventViewer and the MSI logs.

Baiscally the script first clears the log file then clears everything out of the Temp directory. Next the script prompts for the admin to start the installation, once you are done installing the program click ok to continue. The script will then collect the error messages from the MSI logs and the last three windows installer entries from the EventViewer. If there are no errors then it will return sucessful installs entries from the Event Viewer and nothing from the logs. In short this script is just a time saver from having to dig though the event logs and the temp directory for the msi logs and then having to go through those long MSI logs. Troubleshooting the error codes will still need to happen outside of the script.

Be sure to enable Windows Installer logging before beginning. This can be set with the following PowerShell command line.

Set-ItemProperty -path “HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer” -name “Logging” -value voicewarmup

Here’s the final code:

MSIErrorExtractor.ps1

?View Code POWERSHELL
 
Clear-Content errors.txt
 
get-Childitem $env:Temp | remove-Item -force
 
$a = new-object -comobject wscript.shell
$b = $a.popup("Please run installation and click ok once installation is complete",0,"Waiting for MSI Installation and User Input",1)
 
Get-EventLog Application | ? {$_.Source -eq "MSIInstaller" } |  Select-Object TimeGenerated,Source, EntryType, Message -First 3| Format-List | out-file errors.txt
#-and $_.EntryType -eq "Error"
 
filter finderrors { if ($_.contains("Error")) {$_}}
Get-Content $env:temp\MSI*.log | finderrors | Out-File -Append errors.txt | notepad errors.txt

PowerShell 2.0 Release Candidate for Windows Vista and Server 2008

Still waiting for PowerShell 2.0 for Windows XP and Server 2003, but this is a good start.

Read more from the source: http://blogs.msdn.com/powershell/archive/2009/08/14/powershell-2-0-for-windows-vista-and-windows-server-2008-release-candidate.aspx

Download here: https://connect.microsoft.com/windowsmanagement/Downloads

 

Modifying the MS Print webpage for Internet Printing

By default the Internet Printing web-page only displays 10 printers at a time. In our environment we have over 1600 printers and it would take forever to find the printer you need. By modifying a single line in the following file you can change the maximum number or printers to display per page.

C:\WINNT\Web\Printers\ipp_0001.asp

Change the following line to any number that fits your need.

Const iPrinterLength = 2000

Additionally I removed the Status Column to speed up the time to process the webpage

A section of the orginal ipp_0001.asp looked like this…

    For Each objPrinter In objPrinters

        If i > iRevEnd Then Exit For

        If i > iRevStart Then
            iPrinters = iPrinters + 1

            ReDim Preserve rgPrinters(ADSI_PRINTER_ATTRIBUTES, iPrinters)
            rgPrinters(ADSI_PRINTER_STATUS, iPrinters) = objPrinter.Status
            If Err.Number = &H80070005 Then    ‘Access Denied
                Err.Clear
                rgPrinters(ADSI_PRINTER_NAME, iPrinters) = objPrinter.Name
                rgPrinters(ADSI_PRINTER_ACCESS, iPrinters) = PRINTER_ACCESS_DENIED
                rgPrinters(ADSI_PRINTER_LOCATION, iPrinters) = “”
                rgPrinters(ADSI_PRINTER_MODEL, iPrinters) = “”
                rgPrinters(ADSI_PRINTER_COMMENT, iPrinters) = “<a href=””ipp_0001.asp?v=1&startid=” &_
                    CStr (iStart) & “&endid=” & CStr (iEnd) & “””>” & L_AccessDenied_Text & “</a>”

                rgPrinters(ADSI_PRINTER_JOBS, iPrinters) = 0
            Else
                If Err.Number <> 0 Then
                    Err.Clear
                    rgPrinters(ADSI_PRINTER_NAME, iPrinters) = objPrinter.Name
                    rgPrinters(ADSI_PRINTER_ACCESS, iPrinters) = PRINTER_OPENING
                    rgPrinters(ADSI_PRINTER_LOCATION, iPrinters) = “”
                    rgPrinters(ADSI_PRINTER_MODEL, iPrinters) = “”
                    rgPrinters(ADSI_PRINTER_COMMENT, iPrinters) = L_Opening_Text
                    rgPrinters(ADSI_PRINTER_JOBS, iPrinters) = 0
                Else
                    dwStatus = objPrinter.Status
                    If objPrinter.Attributes And &H400 Then dwStatus = dwStatus Or &H80

                    rgPrinters(ADSI_PRINTER_NAME, iPrinters) = GetFriendlyName (objPrinter.PrinterName, strServerName)
                    rgPrinters(ADSI_PRINTER_STATUS, iPrinters) = dwStatus
                    rgPrinters(ADSI_PRINTER_LOCATION, iPrinters) = strCleanString (objPrinter.Location)
                    rgPrinters(ADSI_PRINTER_MODEL, iPrinters) = strCleanString (objPrinter.Model)
                    rgPrinters(ADSI_PRINTER_COMMENT, iPrinters) = strCleanString (objPrinter.Description)
                    rgPrinters(ADSI_PRINTER_JOBS, iPrinters) = objPrinter.JobCount
                    If Err Then Exit Function

                    rgPrinters(ADSI_PRINTER_ACCESS, iPrinters) = PRINTER_OK
                End If
            End If
        End If

        i = i + 1
    Next

After removing the Status lines this was the final code of that section looked like this…

    For Each objPrinter In objPrinters

        If i > iRevEnd Then Exit For

        If i > iRevStart Then
            iPrinters = iPrinters + 1

            ReDim Preserve rgPrinters(ADSI_PRINTER_ATTRIBUTES, iPrinters)
            If Err.Number = &H80070005 Then    ‘Access Denied
                Err.Clear
                rgPrinters(ADSI_PRINTER_NAME, iPrinters) = objPrinter.Name
                rgPrinters(ADSI_PRINTER_ACCESS, iPrinters) = PRINTER_ACCESS_DENIED
                rgPrinters(ADSI_PRINTER_LOCATION, iPrinters) = “”
                rgPrinters(ADSI_PRINTER_MODEL, iPrinters) = “”
                rgPrinters(ADSI_PRINTER_COMMENT, iPrinters) = “<a href=””ipp_0001.asp?v=1&startid=” &_
                    CStr (iStart) & “&endid=” & CStr (iEnd) & “””>” & L_AccessDenied_Text & “</a>”

            Else
                If Err.Number <> 0 Then
                    Err.Clear
                    rgPrinters(ADSI_PRINTER_NAME, iPrinters) = objPrinter.Name
                    rgPrinters(ADSI_PRINTER_ACCESS, iPrinters) = PRINTER_OPENING
                    rgPrinters(ADSI_PRINTER_LOCATION, iPrinters) = “”
                    rgPrinters(ADSI_PRINTER_MODEL, iPrinters) = “”
                    rgPrinters(ADSI_PRINTER_COMMENT, iPrinters) = L_Opening_Text
                Else

                    rgPrinters(ADSI_PRINTER_NAME, iPrinters) = GetFriendlyName (objPrinter.PrinterName, strServerName)
                    rgPrinters(ADSI_PRINTER_LOCATION, iPrinters) = strCleanString (objPrinter.Location)
                    rgPrinters(ADSI_PRINTER_MODEL, iPrinters) = strCleanString (objPrinter.Model)
                    rgPrinters(ADSI_PRINTER_COMMENT, iPrinters) = strCleanString (objPrinter.Description)
                    If Err Then Exit Function

                    rgPrinters(ADSI_PRINTER_ACCESS, iPrinters) = PRINTER_OK
                End If
            End If
        End If

        i = i + 1
    Next