pixel - Fotolia

Tip

How to use PowerShell to troubleshoot Windows desktops

When IT uses remote access to troubleshoot a user's desktop, it prevents the user from working. PowerShell, however, allows IT to fix a problem without disturbing the user.

As an IT professional, it is common for you to use remote connection tools such as TeamViewer to connect to end-user devices and troubleshoot issues. This is a fine way to address problems that stop users from performing necessary and time-sensitive tasks.

A remote connection, however, is invasive to end users and typically forces them to stop working to let you investigate the issue. As a result, if end users encounter issues they can continue to work through, it may be preferable for you to connect to a user's device using a Command-line interface (CLI), such as PowerShell, to troubleshoot an issue.

Using a CLI allows users to continue to work while you troubleshoot. If you know how to use PowerShell, you can troubleshoot a Windows desktop either locally or remotely using native cmdlets.

How to use PowerShell remoting

The most common PowerShell commands are Enter-PSSession and Invoke-Command. Both use Windows Remote Management in the background to connect and run commands or scripts.

For instance, to check if chrome.exe is running on a remote machine, you can run:

PS C:\> Invoke-Command -ComputerName TestMachine -ScriptBlock {Get-Process chrome.exe }

View Windows processes

Oftentimes, when troubleshooting client machines, it is necessary to view and kill Windows processes that are running.

For instance, a user may need to kill outlook.exe because the window is not responding. Those who know how to use PowerShell to do this will enter Stop-Process -Force.

PS C:\> Stop-Process -Name outlook.exe -Force

If you must find processes that a particular user is running, you can filter through the UserName property. In this example, you want to find any process running under Dan:

PS C:\> Get-Process -IncludeUserName | Where-Object {$_.UserName -eq 'Dan'}

Handles

WS(K)

CPU(s)

Id

UserName

Process Name

481

79696

230.53

9728

Dan

Adobe CEF Helper

384

21696

.67

25888

Dan

Adobe CEF Helper

64

2928

.16

1672

Dan

CC Library

64

2812

.22

13992

Dan

CCXProcess

299

76184

5.84

336

Dan

Chrome

345

113572

31.08

772

Dan

Chrome

395

162504

42.19

3508

Dan

Chrome

333

150896

58.61

3532

Dan

Chrome

Test network port availability

Imagine a client machine has an issue connecting to a specific web application on port 8080. One easy method to find out if that machine can connect to that port is to use the cmdlet Test-NetConnection. This cmdlet tests the connection against specific ports to see if they are listening on remote endpoints.

PS C:\> Test-NetConnection -ComputerName testserver -Port 8080

WARNING: TCP connect to (172.16.52.11 : 8080) failed

ComputerName: testserver
RemoteAddress: 172.16.52.11
RemotePort: 8080
InterfaceAlias: Ethernet
SourceAddress: 172.16.48.10
PingSucceeded: True
PingReplyDetails (RTT): 0 ms
TcpTestSucceeded: False

The test failed on port 8080 for the hostname testserver. This cmdlet also performs a ping test to see if the Internet Control Message Protocol can reach the port. This helps ensure the machine is accessible on the network.

Work with software installations

When you use the Windows graphical user interface, you can view installed applications with the Add and Remove programs function. In PowerShell, you can do this with the Get-Package command.

To view any software installed containing the name Adobe, run this command on machines running PowerShell Version 5 or above:

PS C:\> Get-Package -name *Adobe*

Name

Version

Source

Provider name

Adobe CS6 64-bit              

1.2.0           

C:\Program Files (x86)\Adobe\...

Msi

In addition, you can uninstall software with the Uninstall-Package command.

PS C:\> Get-Package -Name 'adobe air' | Uninstall-Package

Name

Version

Adobe AIR

31.0.0.96

How to use PowerShell to search events

The Windows event log allows you to see the events logged on a given system. In PowerShell, the Get-WinEvent cmdlet is the best way to do this. Even better, with a CLI, you can search for what you want easier and faster than you would using Windows Event Viewer.

With a CLI, you can search for what you want easier and faster than you would using Windows Event Viewer.

In the following example, you are trying to find any errors in the application log for events in the last hour for Group Policy Services. To do this, you can use a hash table with the logname -- application -- providername -- Group Policy Services -- and the start time. You only want to see the time the event was created and the message in it, so you use the Select-Object cmdlet.

PS C:\> Get-WinEvent -FilterHashtable @{Logname="Application"; ProviderName="Group Policy Services"; StartTime=(Get-Date).AddHours(-2)} | Select-Object -Property ti
mecreated,message | Format-List

TimeCreated : 12/4/2018 2:36:07 PM
Message: The computer 'test' preference item in the test {69F49340-0D18-434D-A112-F82A688D1E42}' Group Policy Object did not apply because it failed with error code '0x80070424. The specified service does not exist as an installed service.' This error was suppressed.

Performance counters

When it comes to troubleshooting performance issues in Windows, counters have long been the method for getting the data you need to fix an issue. If you know how to use PowerShell, you can not only view what counters are available, but you can also start them with the cmdlet Get-Counter.

To view all the possible counters on a local system, run:

PS C:\> Get-Counter -ListSet * | Select-Object Countersetname | Sort-Object -Property Countersetname

One interesting counter is User Input Delay per Process, which provides the number of milliseconds a system takes to respond to a user interacting with an application.

PS C:\> $Counter = Get-Counter -ListSet 'User Input Delay per Process'
PS C:\> $Counter.Counter
\User Input Delay per Process(*)\Max Input Delay

If you run Get-Counter against that count sample, you can see all of the processes running in your local machine.

PS C:\> Get-Counter -Counter '\User Input Delay per Process(*)\Max Input Delay' -MaxSamples 5

Timestamp

Counter Samples

12/5/2018 7:37:20 AM

\\TestMachine\user input delay per process(0:6980 <outlook.exe>)\max input delay: 0

 

\\TestMachine\user input delay per process(0:2992 <networklicenseserver.exe>)\max input delay : 0

 

\\TestMachine\user input delay per process(0:3992 <svchost.exe>)\max input delay : 0

Now you can find the counter sample -- process name -- to use for your counter. In this example, you use outlook.exe and a PowerShell object to make viewing the samples easier:

PS C:\> Get-Counter -Counter '\\TestMachine\user input delay per process(1:14156 <outlook.exe>)\max input delay' -MaxSamples 100 | ForEach {
>>      $_.CounterSamples | ForEach {
>>          [pscustomobject]@{
>>              TimeStamp = $_.TimeStamp
>>              Path = $_.Path
>>              Value = $_.CookedValue
>>          }
>>      }
>>  }

Time Stamp

Path

Value

12/5/2018 7:40:10 AM

\\TestMachine\user input delay per process(1:14156 <outlook.exe>)\max input delay

0

12/5/2018 7:40:11 AM

\\TestMachine\user input delay per process(1:14156 <outlook.exe>)\max input delay

0

12/5/2018 7:40:12 AM

\\TestMachine\user input delay per process(1:14156 <outlook.exe>)\max input delay

0

12/5/2018 7:40:13 AM

\\TestMachine\user input delay per process(1:14156 <outlook.exe>)\max input delay

0

12/5/2018 7:40:14 AM

\\TestMachine\user input delay per process(1:14156 <outlook.exe>)\max input delay

0

12/5/2018 7:40:15 AM

\\TestMachine\user input delay per process(1:14156 <outlook.exe>)\max input delay

16

12/5/2018 7:40:16 AM

\\TestMachine\user input delay per process(1:14156 <outlook.exe>)\max input delay

16

12/5/2018 7:40:17 AM

\\TestMachine\user input delay per process(1:14156 <outlook.exe>)\max input delay

31

Dig Deeper on Desktop management

Virtual Desktop
SearchWindowsServer
Close