- September 19, 2015
- Posted by: Surender Kumar
- Category: PowerShell
Manage Processes using PowerShell
Table of Contents
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.
- If user selects YES, the message will be saved to Drafts and Outlook will be Closed.
- If user selects NO, the message will not be saved to Drafts and Outlook will be Closed.
- 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

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

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.