以下代码启动
conhost.exe
,进而启动 pwsh.exe
的新实例。 流程启动事件将被过滤,直到找到父级为 pwsh.exe
实例的 conhost.exe
流程:
$sourceId = [guid]::NewGuid().guid
Register-CimIndicationEvent `
-ClassName Win32_ProcessStartTrace `
-SourceIdentifier $sourceId
$descendantProcessName = 'pwsh.exe'
$parentProcess =
Start-Process `
-FilePath conhost.exe `
-ArgumentList $descendantProcessName `
-PassThru
while ($true) {
foreach ($event in (Wait-Event `
-SourceIdentifier $sourceId )) {
$event | Remove-Event
$newProcess = $event.SourceEventArgs.NewEvent
if ($descendantProcessName -ne $newProcess.ProcessName) {
continue
}
if ($parentProcess.Id -ne $newProcess.ParentProcessId) {
continue
}
Get-Process -Id $newProcess.ProcessID
Get-EventSubscriber `
-SourceIdentifier $sourceId |
Unregister-Event
Remove-Event `
-SourceIdentifier $sourceId `
-ErrorAction SilentlyContinue
return
}
}
以下是典型输出:
PS C:\>.\test.ps1
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
61 35.63 88.23 0.05 9584 3 pwsh
该过程对应于
pwsh
的(第一个)新实例,源自 conhost.exe
。
我发现这种等待新进程事件来寻找新后代的技术非常强大,即使在使用其后代进程树非常复杂的安装程序时也是如此。 轮询替代方案很容易完全丢失短暂的中间过程。 这使得确定某个特定的新流程是否源自您启动的流程变得更加困难(或者可能不可能)。 这种短暂的中间过程通常似乎只存在足够长的时间来在完成之前启动一些后代。
不幸的是,在 Windows 上没有管理权限运行时,对
Register-CimIndicationEvent
的调用会失败:
Register-CimIndicationEvent: C:\test.ps1:3
Line |
3 | Register-CimIndicationEvent `
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Access denied
是否有与新进程的开始相对应的事件,我可以在没有管理权限的情况下订阅该事件?
我最终遇到了这个答案,其中指出:
与您当前使用的外部事件 Win32_ProcessStartTrace 不同,__InstanceCreationEvent 和 __InstanceDeletionEvent WMI 内部事件不需要管理员权限。
确实,将注册和进程提取替换为
Register-CimIndicationEvent `
-Query "SELECT TargetInstance
FROM __InstanceCreationEvent WITHIN 0.1
WHERE TargetInstance ISA 'Win32_Process'" `
-SourceIdentifier $sourceId
和
$newProcessHandle =
$event.SourceEventArgs.NewEvent.TargetInstance.Handle
$newProcess =
Get-CimInstance `
-Query "SELECT *
FROM Win32_Process
WHERE Handle = $newProcessHandle"
在没有管理员权限的情况下产生与原始代码相同的结果。