What’s My PID?

Doctor Scripto

Summary: Ed Wilson, Microsoft Scripting Guy, creates a function to capture the process ID of a Windows PowerShell host.

Microsoft Scripting Guy, Ed Wilson, is here. One of the things I like to know is the process ID (PID) of specific processes. Often this is trivial. I can use the Get-Process cmdlet and, for example, look to see what the process ID of Notepad.exe is. But what if I have four or five instances of Notepad running? Then it becomes somewhat an exercise in trial and error.

This is also true for Windows PowerShell. For example, the Windows PowerShell console process name is PowerShell. No problem. Except that I often have multiple instances of Windows PowerShell running, and quite often they are all doing different things.

So, whereas the $host automatic variable represents the Windows PowerShell console host, and it has an instance ID, I cannot easily reference that instance ID to a process ID. So, I had this idea about adding a member to the $host variable. Not too big of a deal. In fact, it is something that I could do since Windows PowerShell 1.0 by using the Add-Member cmdlet.

I need to know which instance of Windows PowerShell I am talking about, and I need a way to differentiate which is which. One way I can do that is by using the StartTime property from the process object that I obtain via the Get-Process cmdlet.

Now, to what do I compare it? Well obviously, with the date from Get-Date. So, I decided to capture the date as soon as I can and compare it with the StartTime property from Get-Process. The result? For me, it works nearly all the time, and that is good enough for something like this.

At first, it was easy, I simply captured the process ID and add it to $host. But that quickly did not work because if I have multiple instances of Windows PowerShell running (more likely than not in my case), I have an array of process IDs—and that doesn’t do any good.

But in fact, when I have multiple instances of Windows PowerShell running, that is THE time when it is most important to know which instance is which. So that added to the complexity of my Windows PowerShell function.

The first thing I do is use the Foreach statement and walk through a collection of Windows PowerShell processes. If the start time matches the current date time, I use the Add-Member cmdlet to add the PID to a property I created called PID. Otherwise, I don’t do anything.

Here is the function:

Function Get-HostPid


 Foreach($p in (Get-Process PowerShell))


   if ($p.StartTime.Touniversaltime() -match


     { $host | Add-Member -NotePropertyName PID -NotePropertyValue ($p.ID)}}}

The first thing I do when processing commands in my Windows PowerShell profile is to call the Get-HostPID function. This gives me the best chance for success. The command is simple:


Here is the output from the $host variable now:

Image of command output

The complete Windows PowerShell profile is shown here:



# PowerShell console profile

# ed wilson, msft


# NOTES: contains five types of things: aliases, functions, psdrives,

# variables and commands.

# version 1.2

# 7/27/2015

# HSG 7-28-2015



Set-Alias -Name ep -Value edit-profile | out-null

Set-Alias -Name tch -Value Test-ConsoleHost | out-null

Set-Alias -Name gfl -Value Get-ForwardLink | out-null

Set-Alias -Name gwp -Value Get-WebPage | out-null

Set-Alias -Name rifc -Value Replace-InvalidFileCharacters | out-null

Set-Alias -Name gev -Value Get-EnumValues | out-null

Set-Alias -Name sudo -Value Start-ElevatedPowerShell | out-null


New-Variable -Name doc -Value "$home\documents" `

   -Description "My documents library. Profile created" `

   -Option ReadOnly -Scope "Global"

if(!(Test-Path variable:backupHome))


 new-variable -name backupHome -value "$doc\WindowsPowerShell\profileBackup" `

    -Description "Folder for profile backups. Profile created" `

    -Option ReadOnly -Scope "Global"



New-PSDrive -Name Mod -Root ($env:PSModulePath -split ';')[0] `

 -PSProvider FileSystem | out-null


Function Edit-Profile

{ ISE $profile }

Function Test-ConsoleHost


 if(($host.Name -match 'consolehost')) {$true}

 Else {$false}  


Function Replace-InvalidFileCharacters


 Param ($stringIn,


 # Replace-InvalidFileCharacters "my?string"

 # Replace-InvalidFileCharacters (get-date).tostring()

 $stringIN -replace "[$( [System.IO.Path]::GetInvalidFileNameChars() )]", $replacementChar


Function Get-TranscriptName


 $date = Get-Date -format s

  "{0}.{1}.{2}.txt" -f "PowerShell_Transcript", $env:COMPUTERNAME,

  (rifc -stringIn $date.ToString() -replacementChar "-") }

Function Get-WebPage



 # Get-WebPage -url (Get-CmdletFwLink get-process)

 (New-Object -ComObject shell.application).open($url)


Function Get-ForwardLink



 # Get-WebPage -url (Get-CmdletFwLink get-process)

 (Get-Command $cmdletName).helpuri


Function BackUp-Profile


 Param([string]$destination = $backupHome)

  if(!(test-path $destination))

   {New-Item -Path $destination -ItemType directory -force | out-null}

  $date = Get-Date -Format s

  $backupName = "{0}.{1}.{2}.{3}" -f $env:COMPUTERNAME, $env:USERNAME,

   (rifc -stringIn $date.ToString() -replacementChar "-"),

   (Split-Path -Path $PROFILE -Leaf)

 copy-item -path $profile -destination "$destination\$backupName" -force


Function get-enumValues


 # get-enumValues -enum "System.Diagnostics.Eventing.Reader.StandardEventLevel"


$enumValues = @{}

[enum]::getvalues([type]$enum) |

ForEach-Object {

$enumValues.add($_, $_.value__)




Function Test-IsAdmin




        Tests if the user is an administrator


        Returns true if a user is an administrator, false if the user is not an administrator       




 $identity = [Security.Principal.WindowsIdentity]::GetCurrent()

 $principal = New-Object Security.Principal.WindowsPrincipal $identity



Function Start-ElevatedPowerShell


 Start-Process PowerShell -Verb Runas


Function Get-HostPid


 Foreach($p in (Get-Process PowerShell))


   if ($p.StartTime.Touniversaltime() -match


     { $host | Add-Member -NotePropertyName PID -NotePropertyValue ($p.ID)}}}



Set-Location c:\

If(tch) {Start-Transcript -Path (Join-Path -Path `

 $doc -ChildPath $(Get-TranscriptName))}



   { $host.UI.RawUI.WindowTitle = "Elevated PowerShell" }

else { $host.UI.RawUI.WindowTitle = "Mr $($env:USERNAME) Non-elevated Posh" }

That is how you can use Windows PowerShell to find a PID. Join me tomorrow when I will talk about more cool stuff.

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 


Discussion is closed.

Feedback usabilla icon