Use PowerShell to Troubleshoot Software Installation

Doctor Scripto

Summary: Use Windows PowerShell to troubleshoot software installation.

 

Hey, Scripting Guy! QuestionHey, Scripting Guy! I am having a problem troubleshooting the installation of an MSI package. I am using Group Policy to deploy the MSI package, and on some computers, it seems to work, but on other computers it fails. After having read your most recent series of articles about troubleshooting Windows, I thought I could use a trace log, but after spending more than an hour trying to click all of those little folders (why is there no search on the log name?), I could not find a trace log that seemed to make sense. Anyway, I guess I am asking you how to troubleshoot remote installation of a MSI package. Hope you can help.

—LT

 

Hey, Scripting Guy! AnswerHello LT,

Microsoft Scripting Guy Ed Wilson here. This morning, the Scripting Wife and I got to do something we have been looking forward to for nearly two months. When we were at Tech∙Ed 2011 in Atlanta, we got to meet a couple of scripters that work for a company that has a headquarters in the Charlotte area. We exchanged email, and this morning the Scripting Wife and I went to their office and made a three-hour “Introduction to Windows PowerShell” presentation. It was a lot of fun. One of the questions they had was related to troubleshooting remote systems.

LT, you are not alone in your queries. In addition to the customer I was talking to this morning, there was also a comment on Monday’s blog post from Klaus Schulte (winner of the Beginner division of the 2011 Scripting Games) asking about troubleshooting installation packages.

LT, there is a search for trace logs. It is called Windows PowerShell. I have given up attempting to navigate through the hundreds of logs in all the different folders (there are 492 logs on my Windows 7 Ultimate workstation). Instead, if I am searching for a log related to something, I use Windows PowerShell.

In Saturday’s Weekend Scripter article, I talked about working with Event Tracing for Windows (ETW) logs. I discussed how to enable and disable the logs, and how to use the Get-WinEvent cmdlet to find and to read the trace. Monday, I continued the ETW discussion by examining the datetime stamp that is generated for each event. Yesterday, I explored parsing the message property of the WMI Activity Trace log.

If I do not supply a value to the listlog parameter, an error appears. If I provide the name of a specific log, certain information about the log returns. If I use the * wildcard character, information about every log on the system is displayed in the Windows PowerShell console. If I use a more comprehensive wildcard character pattern, I can limit the number of logs that return. An example of searching for trace logs that relate to install is shown here:

PS C:\Windows\system32> Get-WinEvent -ListLog *install* -force | select logname

 

LogName                                                                                                                                     

——-                                                                                                                                      

Microsoft-Windows-AxInstallService/Log                                                                                                       

Microsoft-Windows-WPD-ClassInstaller/Analytic                                                                                               

Microsoft-Windows-WPD-ClassInstaller/Operational                                                                                             

 

I can use the same technique to search for logs that relate to msi. In the following output, only one log relates to MSI, but it is associated with AppLocker. Therefore, it will not pick up any trace information from a generic MSI installation:

PS C:\Windows\system32> Get-WinEvent -ListLog *msi* -force | select logname

 

LogName                                                                                                                                     

——-                                                                                                                                     

Microsoft-Windows-AppLocker/MSI and Script                  

 

At times, either I cannot find a trace log that I like, or I grow impatient from the search and then use one of my favorite tricks: query all the logs at once. Sure, it is inefficient, but if I am working locally, it is not a big deal. However, it can take a very long time for the command to complete (on my workstation, it takes nearly four minutes to complete the command). The thing to keep in mind is that after the first portion of time—it might be seconds or a minute or so depending on how much data you are returning and how recent your time filter is—new information will no longer be returned to the screen. This is the time when the command is continuing to process log files, but there is no longer any data to return even though the filter coming after the command to return all the event logs is still working. The (inefficient) command to return log files that have a timestamp that occurs later than “7/11/11 10:35:08 pm” follows this paragraph. To make the information display a bit better, I send the information to a table. In the following command the Get-WinEvent cmdlet returns all information from all log files. The returned entries are piped to the Where-Object cmdlet (? Is an alias for the Where-Object cmdlet), which filters log entries after a specific time. The results are piped to the Format-Table cmdlet (ft is an alias for Format-Table cmdlet), and three properties are selected. The command is shown here:

Get-WinEvent | ? {$_.TimeCreated -gt “7/11/11 10:35:08 pm” } | ft logname, id, message

 

The following figure illustrates running the command in the Windows PowerShell ISE and displays the associated output.

Image of command running in Windows PowerShell ISE and associated output

If I want to tighten up the output and create a more efficient use of the space in my output pane in the Windows PowerShell ISE, I can add the autosize parameter to the Format-Table cmdlet. In addition, I can display the entire message if I use the wrap parameter. However, when I add these parameters to the previous command, it will take the most of the time (five minutes or so) the command runs before displaying output. This is because to calculate the amount of space to allocate for the columns, Windows PowerShell needs to look at all of the data. This reduces the efficiency of the streaming behavior that I took advantage of earlier. The revised command is shown here:

Get-WinEvent | ? {$_.TimeCreated -gt “7/11/11 10:35:08 pm” } | ft logname, id, message -AutoSize –wrap

Clearly, a more efficient method of working with log files is required. 

For more information about using the FilterHashTable parameter, see Use a PowerShell Cmdlet to Filter Event Log for Easy Parsing and Use PowerShell to Parse Saved Event Logs for Errors. For more information about improving the performance of event log queries, see How to Improve the Performance of a PowerShell Event Log Query. For issues surrounding working remotely with Windows Vista and Windows XP event logs, refer to Discover How to Filter Remote Event Log Entries in Windows Vista

The following table is copied from my Use PowerShell to Parse Saved Event Logs for Errors Hey, Scripting Guy! Blog post from January 2011.

Event Log Viewer name

FilterHashTable parameter key name

Log Name

LogName

Source

ProviderName

Event ID

ID

Level

Level

User

UserID

Op Code

*

Logged

*

Task Category

*

Keywords

*

Computer

N/A use –ComputerName parameter

Details

Data

 

If I attempt to use my trick of using the Get-Winevent cmdlet to list all log entries, and I use a FilterHashTable to attempt to filter based on time at the Get-Winevent cmdlet instead of on the other side of the pipeline, an error returns that states I must specify either a log, provider, or path. The command and associated error appear here:

PS C:\Windows\system32> Get-WinEvent -FilterHashTable @{StartTime = “7/11/11 10:35:08 pm”}

Get-WinEvent : You must specify at least one Log, Provider or Path key-value pair.

At line:1 char:13

+ Get-WinEvent <<<<  -FilterHashTable @{StartTime = “7/11/11 10:35:08 pm”}

    + CategoryInfo          : InvalidArgument: (:) [Get-WinEvent], Exception

    + FullyQualifiedErrorId : LogProviderOrPathNeeded,Microsoft.PowerShell.Commands.GetWinEventCommand

 

I decide to modify the command to use a wildcard character for the logname key for the FilterHashTable. The command works great and returns data nearly immediately:

Get-WinEvent -FilterHashtable @{StartTime = “7/11/11 10:35:08 pm”; LogName = “*”}

 

The nice thing about the above command is it returns information from multiple logs and multiple providers. This is useful, for example, when troubleshooting installation problems that may be unrelated to the actual installer. To check a specific installation, it may be useful to filter based on not only the time, but also on the provider. For MSI installed software, the provider is the msiInstaller provider. The following command is broken at the pipe character for readability purposes. In reality it is a single command:

Get-WinEvent -FilterHashtable @{StartTime = “7/11/11 10:35:08 pm”; ProviderName = “msiInstaller”} |

ft logname, id, message -AutoSize –wrap

The command and associated output appear in the following figure.

Image of command and associated output

 

LT, that is all there is to using Windows PowerShell to look at Windows Installer logging. Troubleshooting Windows week will continue tomorrow.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

 

 

0 comments

Discussion is closed.

Feedback usabilla icon