2

I have a windows Powershell script that includes the following line...

$script:parent = (Get-Process -Id (Get-CimInstance Win32_Process -Filter "ProcessID = $pid").ParentProcessId).Name

The line appears twice in the same script. The first time it gets executed it always works fine and returns either svchost, explorer or powershell (meaning that the script was either started by task scheduler, a shortcut on the desktop, or another powershell script).

The second time it's executed, it mostly works fine (and returns the same result) but occasionally returns the following...

Get-Process : Cannot find a process with the process identifier 17216.
At C:\blah\blah\testscript.ps1:2675 char:23
+ ... t:parent = (Get-Process -Id (Get-CimInstance Win32_Process -Filter "P ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (17216:Int32) [Get-Process], ProcessCommandException
    + FullyQualifiedErrorId : NoProcessFoundForGivenId,Microsoft.PowerShell.Commands.GetProcessCommand

Why is it failing the 2nd time?

(BTW - I'm asking this out of curiosity only, there's a simple fix - only execute the command the one time!)

UPDATE - @mklement0 answer is correct. I hadn't spotted a critical fact, the second execution of 'who's the parent' only ever fails if the parent was a powershell script. The script runs 24*7 and is designed that in the event of a critical failure it will re-start another copy of itself and then exit. Since this only occurs once or twice a month I had forgotten about this feature

9
  • 1
    There's got to be some context missing from this post. By the way, why are you using the Get-CimInstance API? This should return the same thing, right? (Get-Process -Id $pid).Parent.Name Commented Apr 17 at 3:49
  • 5
    I guess the parent simply died... Commented Apr 17 at 6:05
  • 2
    @dennythecoder, (Get-Process -Id $pid).Parent is only supported in PowerShell (Core) 7, not also in Windows PowerShell. Commented Apr 17 at 13:41
  • 1
    You state: "... or another powershell script", how? Commented Apr 17 at 16:46
  • 2
    @mklement0 - the process name reported by the first call is either either svchost, explorer or powershell. Commented Apr 17 at 18:45

1 Answer 1

3

As iRon states in a comment on the question, your symptom implies that the parent process no longer exists at the time the 2nd call is made.

This can indeed happen, for instance, if you call a PowerShell script via powershell.exe, the Windows PowerShell CLI, using an asynchronous call via Start-Process, i.e. a call that does not use the -Wait switch.

Building on your own example Start-Process call, the following script demonstrates this scenario:

  • Save the code to a *.ps1 file and invoke it from a PowerShell session launched via the Windows (GUI) shell, such as via the Start Menu or the taskbar.

  • The script will re-invoke itself, asynchronously, in a new console window, via a powershell.exe child process.

  • The original invocation will exit the original PowerShell session (and therefore close its window) after about 1 second.

  • In the new window, you'll see that the first attempt to get the parent process succeeds, but the second will fail, because by that time the parent process no longer exists.

# Script block for later use to determine the parent process' name.
$sbGetParentProcessName = {
  (Get-Process -Id (Get-CimInstance Win32_Process -Filter "ProcessID = $pid").ParentProcessId).Name
}

$parent = & $sbGetParentProcessName
"1st attempt: parent process name is: $parent"

# If this script was invoked from the Windows (GUI) shell (Start Menu, taskbar, desktop, ...),
# or from a scheduled task or a service, re-invoke it, then exit after 1 sec. 
if ($parent -in 'explorer', 'svchost') {
  Write-Verbose "Re-invoking this script asynchronously..."
  Start-Process -FilePath "$PSHOME\powershell.exe" -ArgumentList '-NoExit', '-File', """$PSCommandPath"""
  Write-Verbose -Verbose 'Exiting after 1 sec...'
  Start-Sleep 1
  [Environment]::Exit(0)
}

# Getting here means that the script is being re-invoked.
# Sleeping for 2 seconds ensures that the parent process no longer exists.
Write-Verbose -Verbose 'Sleeping 2 seconds...'
Start-Sleep 2

# This attempt now predictably fails.
# Note: The error message will print *first*.
"2nd attempt: parent process name is: $(& $sbGetParentProcessName)"
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.