Manage Processes using PowerShell

Publish Date: September 19, 2015

Manage Processes using PowerShell

You can use the Process cmdlets to manage local and remote processes with PowerShell. To find out all the PowerShell cmdlets that deal with Processes, use the following command.

PS D:\MyScripts> Get-Command -Noun Process

CommandType     Name                                               ModuleName
-----------     ----                                               ----------
Cmdlet          Debug-Process                                      Microsoft.PowerShell.Management
Cmdlet          Get-Process                                        Microsoft.PowerShell.Management
Cmdlet          Start-Process                                      Microsoft.PowerShell.Management
Cmdlet          Stop-Process                                       Microsoft.PowerShell.Management
Cmdlet          Wait-Process                                       Microsoft.PowerShell.Management

Getting Processes

To get the processes running on the a computer, you can use the Get-Process cmdlet with no parameters.

PS D:\MyScripts> Get-Process

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
     81       7     1072       2488    44     0.00   1532 armsvc
   3631     305   435092      69716  1158 8,057.39   1628 avp
    865     100    83640       4780   410    43.33   4696 avpui
     33       5     1984       2604    45     0.03  19300 cmd
     33       5     1988       2356    45     0.03  21380 cmd
    303      14     3360       4264    65     0.41   6080 LMS
   1482      29    11016      15444    65    63.58    780 lsass
   1105      35   181828     124952   335     7.64  18912 mstsc
     78       8     1416       6652    90     1.16  14464 notepad

[output cut]

You can get particular process by specifying their process names or process IDs. The following command gets the notepad process.

PS D:\MyScripts> Get-Process -Name notepad

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
     78       8     1416       6652    90     1.16  14464 notepad

The name parameter is default. You can omit the -Name keyword and directly type the name of process you want to list. The Get-Process cmdlet also accepts the wildcards (*) to refer multiple processes starting or ending with same name. For example, to get all the processes with the name starting with P, use the following command:

PS D:\MyScripts> Get-Process -Name p*

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    196      19     4952      11248   158     0.08   9420 plugin-container
    195      19     7148      13304   161     0.14  11712 plugin-container
    192      19     4832      10960   158     0.14  17264 plugin-container
    402      25   142392       5072   621     0.89  10248 powershell
    391      26   106664     111812   619     1.00  18060 powershell
    171      24    29872       3728   518     0.41   4884 PresentationFontCache
    350      38    41448      25448   287   431.80  21492 PRTG Enterprise Console
    457      30    16332      14292   130   856.50   2316 PRTG Probe
   1222      47    96172      28928   238   600.47   1948 PRTG Server

Remember that the process name for an executable never includes the “.exe” at the end of the executable name. The Get-Process cmdlet also accepts multiple comma-separated values for the Name parameter as shown below:

PS D:\MyScripts> Get-Process powershell, notepad

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
     78       8     1416       6652    90     1.16  14464 notepad
    402      25   142392       5072   621     0.89  10248 powershell
    373      25   104468     109768   619     1.08  18060 powershell

The following command gets all the processes that have a main window title, and it displays them in a table with the process ID and the process name.

PS D:\MyScripts> gps | ? {$_.mainWindowTitle} | ft Id, Name, mainWindowTitle -AutoSize

   Id Name                    MainWindowTitle
   -- ----                    ---------------
19404 chrome                  New Tab - Google Chrome
 2820 firefox                 TechTutsOnline - Mozilla Firefox
15236 OUTLOOK                 Microsoft Outlook
17360 powershell              Administrator: Windows PowerShell
10032 PRTG Enterprise Console  Enterprise Console
 10184 Ssms                    Microsoft SQL Server Management Studio (Administrator)

The mainWindowTitle is the property of System.Diagnostics.Process object that Get-Process cmdlet returns.

Getting Processes from Remote Computer

You can use the ComputerName parameter of Get-Process cmdlet to get processes from remote computers. For example, the following command gets the powershell processes running on the two remote computers (DC1 and DC2).

PS D:\MyScripts> Get-Process -Name powershell -ComputerName DC1, DC2

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    302      23    62964      66180   601            4580 powershell
    340      25    61488      65904   609            6120 powershell

The computer names are not displayed by default, but they are stored in the MachineName property of the process object. The following command uses the Format-Table cmdlet to display the ProcessName, Process ID, and MachineName properties of the process objects.

PS D:\MyScripts> Get-Process -Name powershell -ComputerName DC1, DC2 | Format-Table -Property ProcessName, ID, MachineName -AutoSize

ProcessName   Id MachineName
-----------   -- -----------
powershell  4580 DC1
powershell  6120 DC2

Stopping Processes

Windows PowerShell gives you Stop-Process cmdlet for stopping a process. The Stop-Process cmdlet takes a Name or ID to specify a process you want to stop. Your ability to stop processes depends on your permissions. Some processes cannot be stopped. For example, if you try to stop the antivirus process AVP (Kaspersky Antivirus), you get the error as shown below:

PS D:\MyScripts> Stop-Process -Name avp

Confirm
Are you sure you want to perform the Stop-Process operation on the following item: avp(1628)?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): Y
Stop-Process : Cannot stop process "avp (1628)" because of the following error: Access is denied
At line:1 char:1
+ Stop-Process -Name avp
+ ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (System.Diagnostics.Process (avp):Process) [Stop-Process], ProcessCommandException
    + FullyQualifiedErrorId : CouldNotStopProcess,Microsoft.PowerShell.Commands.StopProcessCommand

Windows PowerShell automatically added Confirm parameter since every Antivirus software is running under System Account privileges. This means whenever you try to stop any system service, PowerShell ask you to confirm, but if you do not have enough access on process, you will still not be able to stop the process. This is the reason I was not able to stop AVP process. Let’s try to stop a process which is running under my account, notepad for instance.

PS D:\MyScripts> Stop-Process -Name notepad

This time, PowerShell did not confirm whether you want to stop the process. It closed the notepad immediately. You can manually add Confirm parameter if you want PowerShell to display confirmation prompt as shown below:

PS D:\MyScripts> Stop-Process -Name notepad -Confirm

Confirm
Are you sure you want to perform this action?
Performing the operation "Stop-Process" on target "notepad (20944)".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):

Also note that you have many choices at confirmation prompt like Y, A, N, L, S but the default is Y (YES). This means if you do not type any choice and press Enter key, the Y will be considered by default.

Windows PowerShell can stop a process; it doesn’t seem interesting. You can always stop any process if it is responding. To make it more interesting lets find out a way to stop a process which is hung or not responding. To investigate what properties do Process object holds, use Get-Member cmdlet.

PS D:\MyScripts> Get-Process | Get-Member -MemberType Properties

   TypeName: System.Diagnostics.Process

Name                       MemberType     Definition
----                       ----------     ----------

[output cut]

PrivilegedProcessorTime    Property       timespan PrivilegedProcessorTime {get;}
ProcessName                Property       string ProcessName {get;}
ProcessorAffinity          Property       System.IntPtr ProcessorAffinity {get;set;}
Responding                 Property       bool Responding {get;}
SessionId                  Property       int SessionId {get;}

[output cut]

Because a Process object has a Responding property that is true when it is responding.

PS D:\MyScripts> (Get-Process notepad).Responding
True

When the process is no longer responding, the property returns False.  You can stop all non-responsive applications with the following command:

PS D:\MyScripts> (Get-Process notepad).Responding
False
PS D:\MyScripts> (Get-Process) | ?{$_.Responding -eq $false}

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
     82       8   323920     329256   405     4.77  14188 notepad

PS D:\MyScripts> Get-Process | Where-Object {$_.Responding -eq $false} | Stop-Process -Verbose
VERBOSE: Performing the operation "Stop-Process" on target "notepad (14188)".

The above example shows that notepad which has stopped responding in my computer, is closed by Stop-Process cmdlet.

One fact about Stop-Process cmdlet is that running Stop-Process command against any application is similar to opening Task Manager and selecting End Process option to forcefully close the application. The application is forcefully closed; means that any data which is not yet saved will be lost. For instance, if you run Stop-Process command against Microsoft Excel; any unsaved data in excel spreadsheet will be lost. Let’s consider another example of Microsoft Outlook which is most widely used email client in most of companies. If you always keep using Stop-Process against Microsoft Outlook, the data file (PST) will get corrupted and it will need a repair before it can be used again. We have to investigate some more safer solution of closing the application without killing the process itself. Let’s take a look at the members of Get-Process cmdlet.

PS D:\MyScripts> Get-Process | Get-Member -MemberType Method

   TypeName: System.Diagnostics.Process

Name                      MemberType Definition
----                      ---------- ----------
BeginErrorReadLine        Method     void BeginErrorReadLine()
BeginOutputReadLine       Method     void BeginOutputReadLine()
CancelErrorRead           Method     void CancelErrorRead()
CancelOutputRead          Method     void CancelOutputRead()
Close                     Method     void Close()
CloseMainWindow           Method     bool CloseMainWindow()
CreateObjRef              Method     System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Dispose                   Method     void Dispose(), void IDisposable.Dispose()
Equals                    Method     bool Equals(System.Object obj)
GetHashCode               Method     int GetHashCode()
GetLifetimeService        Method     System.Object GetLifetimeService()
GetType                   Method     type GetType()
InitializeLifetimeService Method     System.Object InitializeLifetimeService()
Kill                      Method     void Kill()
Refresh                   Method     void Refresh()
Start                     Method     bool Start()
ToString                  Method     string ToString()
WaitForExit               Method     bool WaitForExit(int milliseconds), void WaitForExit()
WaitForInputIdle          Method     bool WaitForInputIdle(int milliseconds), bool WaitForInputIdle()

Notice that Get-Process cmdlet has a CloseMainWindow method. You can use this method to safely close Microsoft Outlook as shown below:

PS D:\MyScripts> Get-Process Outlook | Where-Object {$_.CloseMainWindow()}

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
   1453      70    71992      77580   613     2.27  16084 OUTLOOK

The benefit of using this method is that it does not forcefully end the process; instead it gracefully exits the Outlook window. The other benefit of using this method is that if any user is writing an email message, he/she will be prompted with 3 options:YES, NO, and CANCEL.

  1. If user selects YES, the message will be saved to Drafts and Outlook will be Closed.
  2. If user selects NO, the message will not be saved to Drafts and Outlook will be Closed.
  3. If user selects CANCEL, the user can continue writing email message and Outlook will not be Closed.

Suppose that you are a backup operator in a company and you are assigned the task to backup the outlook PST files for all users’ on daily basis. You can schedule the backup to be run on a specific time but the problem is that you cannot copy the PST files until the Microsoft Outlook is closed. You can create a Windows PowerShell script and schedule this to be run under every user account. The script will safely close the Microsoft Outlook application and the backup can be done thereafter. You can create your own script using above command or download my Close-Outlook.ps1 script.

Stopping All Other PowerShell Sessions

Sometimes it may be useful to be able to stop all running Windows PowerShell sessions other than the current session. If a session is using too many resources or is inaccessible (it may be running remotely or in another desktop session), you may not be able to directly stop it. If you try to stop all running sessions, however, the current session may also be terminated.

Each Windows PowerShell session has an environment variable PID that contains the Id of the Windows PowerShell process. You can check the $PID against the Id of each session and terminate only Windows PowerShell sessions that have a different Id. The following pipeline command does this and returns the list of terminated sessions with the help of PassThru parameter.

PS D:\MyScripts> Get-Process -Name powershell | Where-Object -FilterScript {$_.Id -ne $PID} | Stop-Process -PassThru

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    402      25   142392       4968   621     0.89  10248 powershell
    448      24    99988     101928   618     0.53  11548 powershell
    601      26   114108     116168   619     0.67  16532 powershell

Using above command, all the other PowerShell sessions will be closed except current session where you run this command.

Start New Processes

The Start-Process cmdlet starts one or more processes on the local computer. To specify the program that runs in the process, enter an executable file or script file, or a file that can be opened by using a program on the computer. If you specify a non-executable file, Start-Process starts the program that is associated with the file, much like the Invoke-Item cmdlet.

You can use the parameters of Start-Process to specify options, such as loading a user profile, starting the process in a new window, or using alternate credentials. The following command starts a  new PowerShell process with “Run as Administrator” permissions.

PS D:\MyScripts> Start-Process Powershell -Verb runAs -wait -windowstyle Maximized

The -wait -windowstyle Maximized operators maximizes the window and retains the window until the process the completes.

Wait-Process

The Wait-Process cmdlet waits for one or more running processes to be stopped before accepting input. In the Windows PowerShell console, this cmdlet suppresses the command prompt until the processes are stopped. You can specify a process by process name or process ID (PID), or pipe a process object to Wait-Process. The Wait-Process works only on processes running on the local computer and you can use this cmdlet in your PowerShell script to wait for one command to complete before the next command executes.

The Wait-Process cmdlet can be used in 3 different ways. The syntax is shown below:

Wait-Process [-Id] <Int32[]> [[-Timeout] <int>] [<CommonParameters>]

Wait-Process -InputObject <Process[]> [[-Timeout] <int>] [<CommonParameters>]

Wait-Process [-Name] <string[]> [[-Timeout] <int>] [<CommonParameters>]

Debug-Process

The Debug-Process cmdlet attaches a debugger to one or more running processes on a local computer. You can specify the processes by their process name or process ID (PID), or you can pipe process objects to Debug-Process.

Debug-Process attaches the debugger that is currently registered for the process. Before using this cmdlet, verify that a debugger is downloaded and correctly configured.

The syntax is shown below:

Debug-Process [-Name] <string[]> [-Confirm] [-WhatIf] [<CommonParameters>]

The following command attaches a debugger to the PowerShell process on the computer.

PS D:\MyScripts> Debug-Process powershell

Select Property vs ExpandProperty

The pipeline ability of PowerShell is really amazing that allows you to input the result of one cmdlet to another. You know the Select-Object cmdlet is used for filtering the result based on selected properties. For instance, let’s pipe the result of Get-Process cmdlet into the Select-Object as shown below:

PS D:\MyScripts> Get-Process | Select-Object -Property ProcessName

This command will show only one column with ProcessName header.  Since -Property is a default parameter for Select-Object cmdlet, you could even shorten the above command like Get-Process | Select ProcessName.

If you run the following command, you will see that the output of command is actually an object of Selected.System.Diagnostics.Process type.

PS D:\MyScripts> Get-Process | Select -Property ProcessName | Get-Member
Get process with property
Understanding the output type of Get-Process with select property

You can see that the output of Get-Process cmdlet is a System.Diagnostics.Process object data type. But what if you want to pipe the output of Get-Process command into another cmdlet which is expecting a string data type as an input instead of an object? Well, in that case you need to use -ExpandProperty parameter instead of -Property as shown below:

PS D:\MyScripts> Get-Process | Select -ExpandProperty ProcessName

This command will generate a similar output but without the ProcessName header. If you run the following command, you will see this time the output is not an object but a normal string:

PS D:\MyScripts> Get-Process | Select -ExpandProperty ProcessName | Get-Member
Get process with expand property
Understanding the output type of Get-Process with select expand property

The -ExpandProperty is particularly useful when the other cmdlet down the pipeline is expecting a string data type instead of object. The command also shows that there are a whole lot of different methods that you can perform on a string data type that were not possible on System.Diagnostics.Process object. So in the end, use of -Property and -ExpandProperty parameters really depend upon what you want to do with the output.

This is all about Managing Windows Processes using PowerShell.

Back

 



Microsoft Certified | Cisco Certified