Start-Process 与 Start-Sleep 不能很好地配合

2024-03-26

我的目标是运行多个进程并保存它们ProcessName and Id供以后使用。这是我的代码

[System.Collections.ArrayList]$startedProcesses = @()
$processStatus = Start-Process -FilePath notepad.exe -passthru
Start-Sleep 1
$startedProcesses.add($processStatus)

$processStatus = Start-Process -FilePath calc.exe -passthru
Start-Sleep 1
$startedProcesses.add($processStatus)

echo $startedProcesses

该脚本的输出是:

PS C:\Users\wakatana\Desktop\> .\so_question0.ps1

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    235      15     3408      14112       0.08  24812   2 notepad
              0        0          0       0.13  21460

我也尝试过更换[System.Collections.ArrayList]$startedProcesses = @() with $startedProcesses = New-Object System.Collections.Generic.List[System.ComponentModel.Component]但我最终得到了相同的结果。

问题:为什么我没有calc under ProcessName?如果我删除Start-Sleep 1然后我得到了calc under ProcessName。这是为什么?这是启动应用程序的正确方法还是我做错了什么?我的操作系统:Windows 10 家庭版


您的问题与使用无关Start-Sleep.

相反,问题是,从 Windows 10 开始,calc.exe只是一个stub最终启动的进程的可执行文件,存根进程在启动真正的可执行文件后立即退出.

如果您删除Start-Sleep之间的呼叫Start-Processecho来电、stub过程对象包含在$startedProcesses通常确实反映了存根可执行文件的名称 -calc.exe- 在里面ProcessName当时的专栏,由于还活着(尽管很短),但你仍然无法追踪real可执行文件的进程生命周期和通过该对象的退出代码。

真正的可执行文件的名称是Calculator.exe,其确切路径包含完整的 AppX 包名称(包名称、版本号和发布者 ID):

例如,启动后calc.exe, (Get-Process Calculator).Path产生类似:

C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_10.1908.0.0_x64__8wekyb3d8bbwe\Calculator.exe

然而,您不能使用该路径来启动计算器directly- 你会得到一个Access denied错误,即使在海拔高度运行时也是如此。

计算器,作为AppX 包(通常通过 Microsoft Store 分发的 UWP 应用程序), 最容易由其 URL 方案启动:

Start-Process ms-calculator:

Note:

  • 通过包名称或基于通配符的部分自动发现 AppX 应用程序的 URL 方案名称 - 例如,*Calculator* - see 这个答案 https://stackoverflow.com/a/58733061/45375.

  • 不太方便的替代方法是使用shell:基于应用程序 AppID 的 URL - 请参阅这个答案 https://stackoverflow.com/a/68907604/45375.

不幸的是,从 PowerShell (Core) 7.2 / Windows PowerShell v5.1 开始,adding -PassThru调用 AppX 包 URLStart-Process结果是error而不是返回代表已启动进程的对象 - 尽管计算器仍然启动;这同样适用于-Wait:

# Launches Calculator, but doesn't return a process object
# and reports an error instead:
PS> Start-Process ms-calculator: -PassThru
Start-Process : This command cannot be run completely because the system cannot find all the information required.
...

该问题已报告于GitHub 问题 #10996 https://github.com/PowerShell/PowerShell/issues/10996.


解决方法:

# Invoke the *stub executable* synchronously, so that
# the real executable has already been launched by the time
# the call returns.
Start-Process -Wait -FilePath calc.exe 

# Now get the real process object, named 'Calculator'.
# The newly launched or a preexisting instance is used (see below).
$processStatus = Get-Process -Name Calculator |
                 Where-Object SessionId -eq (Get-Process -ID $PID).SessionId).ID

注意:计算器只创建one每个用户会话的进程(窗口站):如果进程已存在,则随后启动该进程的委托。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Start-Process 与 Start-Sleep 不能很好地配合 的相关文章

随机推荐