简体   繁体   English

从 Start-Job 中获取 PID

[英]Getting PID from within a Start-Job

I am having trouble getting the PID from a Start-Process within a Start-Job in Powershell (latest version).我在 Powershell(最新版​​本)中从 Start-Job 中的 Start-Process 获取 PID 时遇到问题。 The Start-Process cmdlet runs and returns the PID as expected when run outside of the Start-Job Scriptblock.在 Start-Job Scriptblock 之外运行时,Start-Process cmdlet 运行并按预期返回 PID。 When the statement is added to the Start-Job Scriptblock, no PID is returned.将语句添加到启动作业脚本块时,不会返回任何 PID。 Can someone point this newbie in the right direction?有人可以将这个新手指向正确的方向吗?

$myJob = Start-Job -Name newJob -ScriptBlock {
$procID = (Start-Process myprogram.exe -PassThru -ArgumentList "myArgs" -WorkingDirectory "myWorkingDir").Id
}

Perhaps you think that assigning to a variable in a script block being executed in a background job makes that variable visible to the caller , which is not the case.也许您认为分配给正在后台作业中执行的脚本块中的变量会使该变量对调用者可见,但事实并非如此。

Background jobs run in an entirely separate session, and in order to communicate data to the caller the success output stream must be used, whose content the caller must collect via the Receive-Job cmdlet:后台作业在一个完全独立的会话中运行,为了将数据传送给调用者,必须使用成功输出流,调用者必须通过Receive-Job cmdlet 收集其内容:

$myJob = Start-Job -Name newJob -ScriptBlock {
 # Implicitly output the PID of then newly launched process.
 (Start-Process myprogram.exe -PassThru -ArgumentList "myArgs" -WorkingDirectory "myWorkingDir").Id
}

# Use Receive-Job to collect the background job's output, once available.
# NOTE: If `Start-Process` failed, this would result in an infinite loop.
#       Be sure to implement a timeout.
# You could use `$procID = Receive-Job -Wait -AutoRemoveJob` to wait synchronously,
# but that would defeat the purpose of a background job (see below).
while (-not ($procID = Receive-Job $myjob)) {
  Start-Sleep -Milliseconds 200
}

Taking a step back: Start-Process itself is asynchronous, so there's no need to use a background job : just start myprogram.exe directly in the caller's context:退一步: Start-Process本身是异步的,因此不需要使用后台作业:只需直接在调用者的上下文中启动myprogram.exe

# Launch myprogram.exe asynchronously.
# $proc receives a value once the program has *launched* and
# your script continues right after.
$proc = Start-Process myprogram.exe -PassThru -ArgumentList "myArgs" -WorkingDirectory "myWorkingDir"

# $proc.Id retrieves the PID (process ID)
# $proc.HasExited tells you whether the process has exited.
# $proc.WaitForExit() allows you to wait synchronously to wait for the process to exit.

However, if myprogram.exe is a console (terminal) application whose output you want to capture , do use Start-Job , but don't use Start-Process to launch myprogram.exe : invoke it directly from the background job:但是,如果myprogram.exe是您想要捕获其输出的控制台(终端)应用程序,请使用Start-Job ,但不要使用Start-Process来启动myprogram.exe直接从后台作业调用它:

$myJob = Start-Job -Name newJob -ScriptBlock {
  Set-Location "myWorkingDir"
  myprogram.exe
}

While that won't give you that process' ID, you can instead use the job that launched the process - $myJob - to track that particular process and its output.虽然这不会为您提供该进程的 ID,但您可以改为使用启动该进程的作业- $myJob - 来跟踪该特定进程及其输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM