如何获取 PowerShell 作业的进程句柄或 PID?

问题描述 投票:0回答:2

动机:我正在尝试使用简单的 powershell 作业测试一些与进程相关的命令。但是,所有 powershell 作业在进程表中都被命名为“powershell”。所以我需要进程句柄,我可以用它来过滤

Get-Process
输出。

因此,“更大”的问题可能更容易回答,但就目前情况而言,我认为只要我能够将 powershell 作业连接到其进程 ID(“句柄”),我就有了一个解决方案。

如何从 powershell 作业中获取进程 ID? (这不是 JobID)。

$job = Start-Job -Name $jobName -ScriptBlock {
  while ($true) {
    sleep -Seconds 1
  }
}

$processes = Get-Process

$jobHandle = ???
$jobProcess = $processes | where {$_.Handle -eq $jobHandle}

如何获取以“???”表示的缺失信息?


处理 XY 问题并更一般地说,如果这是不可能的,因为所有内容都被继承到当前的 powershell 会话中,那么更大的问题是:如何创建一个任意命名或处理的进程,我可以从 powershell 执行任何操作,用于测试?

# how do I start this code block as an arbitrary named process?
# name = "test-Get-Foo.1.2"

{
  while ($true) {
    sleep -Seconds 2
  }
}

# ???

$proc = Get-Process | where {$_.Name -like "test-Get-Foo*"}
powershell
2个回答
1
投票

关于第一个问题,据我所知,

Job
不会公开幕后生成的底层进程,而获得其
ProcessId
的方法是进行之前和之后比较:

$before = Get-CimInstance win32_process -Filter "ParentProcessId = $pid"
$job = Start-Job -ScriptBlock {
    while ($true) {
        Start-Sleep -Seconds 1
    }
}
$after = Get-CimInstance win32_process -Filter "ParentProcessId = $pid"
$process = $after | Where-Object { $_.ProcessId -notin $before.ProcessId }
$jobHandle = $process.ProcessId

关于第二个问题,解释一下:

如何创建一个任意命名或处理的进程,我可以从 PowerShell 对其执行任何操作以进行测试?

为此,您可以使用

NamedPipeConnectionInfo
。一个简单的例子:

try {
    $proc = Start-Process powershell -PassThru -ArgumentList '-WindowStyle', 'Hidden'
    $pipe = [System.Management.Automation.Runspaces.NamedPipeConnectionInfo]::new($proc.Id)
    $rs = [runspacefactory]::CreateRunspace($pipe)
    $rs.Open()
    $ps = [powershell]::Create().AddScript({ "Hi there! I'm $PID" })
    $ps.Runspace = $rs
    $ps.Invoke() # `$task = $ps.BeginInvoke()` here for Async
}
finally {
    if ($ps) {
        $ps.Dispose()
    }
    if ($rs) {
        $rs.Dispose()
    }
    # Remove this if you don't want to kill the underlying process :)
    if ($proc) {
        $proc.Kill()
    }
}

0
投票

PowerShell 作业当然会有一个

PID
,您可以使用
Named Pipes
让作业告诉父 PowerShell 进程它是
PID

$Job = Start-Job -ScriptBlock {
    $PipeServer = New-Object System.IO.Pipes.NamedPipeServerStream('JobPipe', 'InOut')
    $PipeServer.WaitForConnection() #Waits for parent process to connect

        $StreamWriter = New-Object System.IO.StreamWriter($PipeServer)
        $StreamWriter.AutoFlush = $true
        $StreamWriter.WriteLine($PID) #Put the PID in the JobPipe
        $StreamWriter.Close()

    $PipeServer.Close()

    Start-Sleep -Seconds 10
}

$PipeClient = New-Object System.IO.Pipes.NamedPipeClientStream('.', 'JobPipe', 'In')
$PipeClient.Connect()

$StreamReader = New-Object System.IO.StreamReader($PipeClient)
$JobPid = $StreamReader.ReadLine() #Get the PID of the Job from the JobPipe
$StreamReader.Close()

$PipeClient.Close()

$JobPid
Get-Job # Just to show that the Job hasn't finished yet
© www.soinside.com 2019 - 2024. All rights reserved.