Let me start by giving a bit of background about myself as it will help to give context and legitimacy to this post, I hope. I have a background as a software developer, having written my first code in 1980, but in 1995 I became involved with products from a company called Citrix and I’ve been troubleshooting problems with them, or more precisely, mostly with the applications delivered on top of them, ever since.
This used to be a manual affair which is tedious, boring and error prone so being the inherently lazy person I am, I’ve been trying to simplify, accelerate and automate the troubleshooting where possible and practical, by using PowerShell.
This article shares some of my success in this area and I hope will encourage you to be a more efficient trouble-shooter so that you have more time available for fun things (although to me personally, that is quite often more troubleshooting or PowerShell development)!
Below, I present a list of the PowerShell commands for troubleshooting I find the most useful and use most frequently.
WMI, or CIM (pronounced “See Eye Em”) as the PowerShell cmdlets morphed to in version 3.0, is a great yet simple and generic method to get information about all kinds of things from one or more computers.
For instance, you can get detailed information about processes, services, disks, networks, memory, processors, batteries, etc, etc. In addition, some companies, such as Citrix, add their own WMI providers to give access to information that would otherwise need a proprietary API or executable to retrieve.
For example, this command will get operating system details and installation and last boot times (fig. 1):
Fig. 1: The Get-CimInstance Command delivers as output information about operating systems, which are displayed in table form
A lot of my consultancy engagements include health checking of various components. The way I gather a large amount of information about the desktops and servers I am checking, which I can use when I am not on site or have access to the customer systems, is to use a script I wrote that queries almost fifty CIM classes from a list of computers specified on the command line, or via text file. You can download the script for free from my GitHub repository.
The script writes the results to csv files making it easy to compare results from different machines, e.g. to check consistency and help spot anomalies.
There can be incredibly useful information contained in the Windows event log when troubleshooting issues such as slow logon.
But knowing where to look can be problematic since on recent operating systems there are upwards of 300 different active event logs where crucial information could be hiding – not just in the System or Application events logs like in the old days.
Using PowerShell, we can easily search for specific events
in a certain time range
containing specific text or
a combination of the above
which is much easier, quicker and scalable than manually running event viewer and trawling through a myriad of events.
For instance, here is an example of using a hash table argument, also known as a dictionary, to retrieve account lockout events in the last twelve hours from a remote domain controller including the computer the lockout was caused from (figure 2 and 3):
Fig. 2: The Get-WinEvent Command delivers as output information about account lockout events in the last twelve hours from a remote domain controller, which are displayed in table form
Fig. 3: Screenshot of the Windows Event properties
Note in the command how we use the “Properties” array returned by Get-WinEvent to extract specific fields so that we don’t have to parse the full text of the event log entry (figure 4).
Fig 4: The Get-WinEvent Command described in the text selects only the first  and second  field of the EventData set
Again, there’s a script I use almost daily to retrieve all events from all enabled event logs in a given time period, such as a user logon, to look for clues/reasons for errors or slow performance. You can download it from my GitHub repository.
Consider the scenario where users on a specific computer complain about poor performance but when you try to remote to that machine with mstsc or similar, your logon hangs.
Wouldn’t it be nice to have a low-overhead method of remoting to that device for interactive, or automated, troubleshooting like one can do with telnet or ssh to *nix machines (e.g. using the great free tool PuTTY)?
Entering the PowerShell Command Enter-PSSession gives a command line interface onto the remote computer, that is if PowerShell remoting is enabled via GPO or manually via “winrm quickconfig” or Enable-PSRemoting -Force.
This allows troubleshooting and remediation such as looking for the highest consumers of CPU or memory via Get-Process (alias ps) and terminating them if that is appropriate via Stop-Process (alias kill).
How do you test if a specific web server is up and running? Ping? No! Ping merely tests if ICMP replies are enabled, and indirectly tests name resolution if not using an IP address – it does not confirm whether there is a process listening on a specific port on the remote machine and firewalls allow the connection.
In pre-PowerShell days I would use telnet.exe for this port testing but now PowerShell provides the Test-NetConnection command (alias tnc) which allows checking of a specific port on a machine (and route tracing too), as shown in figure 5:
Fig. 5: Test-NetConnection can be used to query information about a specific port on a machine
In addition, because it returns a PowerShell object or a Boolean, it is easy to incorporate into scripts without having to parse command output from the likes of ping.exe which we used to have to do in the bad old days.
This is the odd one out in this list because it is not available by default: One has to have the ActiveDirectory PowerShell module installed although that is very simple via the “Add-WindowsFeature RSAT-AD-PowerShell” command (run elevated).
Many vendors have PowerShell modules to allow you to interface and automate their technology – I use ones from VMware and Citrix daily for instance.
Get-ADUser and associated cmdlets, such as Get-ADGroupMember, allow us to check, and change, AD information and is particularly useful for querying large numbers of objects and producing a report (see Export-CSV later).
Here is an example of counting how many accounts have a home drive set to “H:” which we might need if we are performing some maintenance – we could change the home drive just as easily (figure 6):
Fig. 6: Get-ADUser can be used to easily retrieve information about users in Active Directory
I also find it very useful when on customer systems, and they haven’t given me access to AD Users and Computers, but I need to check properties for a user such as group membership.
Frequently we need to check that critical processes are running or investigate processes that we don’t recognize. Whilst Task Manager and SysInternals Process Explorer are useful tools, we can check, and fix, a lot of issues with the Get-Process (alias ps) cmdlet.
Here is an example that shows all processes that are running from folders that have “Citrix” in the name, sorted on ascending start times of that process, which allows us to determine if the process started at boot, user logon, etc. (figure 7):
Fig. 8: Get-Process can be used to filter for processes that contain ‘VMware’ in their company name and to display specific information about them
Fig. 9: The company name can usually be found in the property details of an .exe file in the entry “Copyright”
Chances are that you have actually been using this command without even realizing, especially if you are coming from a command prompt, if you have been using “dir” in a PowerShell prompt, as that is an alias for Get-ChildItem.
As the name suggests, Get-ChildItem gives us information about the child items, and their children and so on if we specify -recurse, of a parent where the parent could be a local or remote file system folder, a registry key, a certificate store, etc (hint: run Get-PSDrive to see what PowerShell drives are available).
Here is an example that shows details in the given folder and children, including any hidden ones which the -force enables, for any file that exceeds 100MB in size, sorted in descending size order.
Fig. 10: Retrieving details in a given folder and children for any file that exceeds 100MB in size, sorted in descending size order with the Get-ChildItem command
This one is slightly different to the others I have presented thus far in that it doesn’t directly assist troubleshooting but what it does give us is detailed help such as usage, parameters and examples for cmdlets, covering both built in modules and ones you subsequently install.
This, coupled with Get-Command to see what commands are provided with a specific module or are concerned with networks, drives, etc, allows unfamiliar commands to be used quickly without having to resort to one’s favorite web search engine.
I usually use it with -ShowWindow to show the help in a separate text window and -Online is useful to go to a web page with the latest information which sometimes also has extra information and links to related items.
Remember that you can tab through the available arguments or use ctrl space to show them all and that script authors like myself will add the required comments to our scripts so that Get-Help works with them as well.
This cmdlet in Windows PowerShell allows object data output by PowerShell cmdlets, functions or scripts to be easily presented in an onscreen grid view which is then sortable and filterable without requiring any software, other than PowerShell (and .NET) to be installed.
Selected items can even be returned by it for further use in scripts, e.g. to choose an item from a list, or just sent to the clipboard (via the -passthru argument).
Here is a one-liner I use frequently to get today’s IIS log file into a grid view, so I can look for errors, slow response times, etc. :
Fig. 11: The Out-GridView command lets you format the data you queried with PowerShell in a clear grid
And figure 12 shows the one line I had selected when I clicked the “OK” button in the grid view which was put into the clipboard by Set-Clipboard (alias scb) so it can be pasted into my troubleshooting/healthcheck notes (what do you mean, you still use pen and paper!).
Fig. 12: Output of the before mentioned command.
Last but not least, Export-CSV is a built-in cmdlet that allows us to write any PowerShell objects, such as the output from cmdlets previously presented like Get-Process, to a correctly formatted CSV file so that they can be examined, filtered, sorted, etc in Microsoft Excel, Google Sheets or even brought back into PowerShell via Import-CSV for further processing.
Fig. 13: Exporting data retrieved with PowerShell into a .csv file
Note the use of -NoTypeInformation which prevents a line of property types being output to the csv which confuses Excel although is easily deleted. You can also use -Append to append new objects to an existing csv file although the columns should match between old and new.
I use Export-Csv a lot for “poor man’s reporting” where PowerShell scripts running via regular scheduled tasks collate data from various sources, produce CSV files and email them to “interested” parties via Send-MailMessage (which requires access to an SMTP mail server).
Lastly, if you are using a Dutch locale, you probably want to use -delimiter ‘;’ since they use semicolons in their Comma Separated Values files – a fact that took me a while to figure out when working for a Dutch based company!
Well that’s all for now folks. Please note: there is no order to this – very arbitrary – list in the same way there wouldn’t be an order to tools in your workman’s toolbox – if you need to undo a screw then you are unlikely to pull a hammer out as your first choice (unless you are Jeremy Clarkson of course).
https://www.scriptrunner.com/wp-content/uploads/2020/11/windows-prozesse-powershell.png10001000Thomas Jooshttps://www.scriptrunner.com/wp-content/uploads/2018/05/ScriptRunner_Logo_RGB-300x45.pngThomas Joos2020-11-11 10:30:112021-01-07 16:43:43Display, retrieve, and terminate Windows processes with PowerShell