Start-Process плохо играет с Start-Sleep - PullRequest
2 голосов
/ 06 ноября 2019

Моя цель - запустить несколько процессов и сохранить их ProcessName и 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 = @() на $startedProcesses = New-Object System.Collections.Generic.List[System.ComponentModel.Component], но я закончил с тем же результатом.

Вопросы: почему у меня нет calc под ProcessName? Если я уберу Start-Sleep 1, тогда я получу calc под ProcessName. Почему это? Это правильный способ запуска приложений или я делаю что-то не так? Моя ОС: Windows 10 Home

1 Ответ

2 голосов
/ 06 ноября 2019

Ваша проблема не связана с использованием Start-Sleep.

Вместо этого проблема заключается в том, что в Windows 10 calc.exe является только исполняемым файлом заглушка для процесса, который в конечном итоге запускается, и процесс-заглушка завершается сразу же после запуска реального исполняемого файла .

Если вы удалите вызов Start-Sleep между Start-Process и echoвызовы, объект процесса stub , содержащийся в $startedProcesses, обычно отражает имя исполняемого файла заглушки - calc.exe - в то время в столбце ProcessName, поскольку он все еще жив (хотя и ненадолго),но вы все равно не сможете отследить время жизни исполняемого файла real и код завершения через этот объект.

Имя реального исполняемого файла - Calculator.exe, точный путь которого включает полный AppXимя пакета (имя пакета, номер версии и идентификатор издателя):

Например, после запуска calc.exe, (Get-Process Calculator).Path выдает что-то вроде:

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

Однако дажеесли вы знаете этот путь, вы не можетене используйте его для запуска Calculator напрямую .

Calculator, как AppX-пакет (приложение UWP, обычно распространяемое через Microsoft Store) , должно быть запущен по схеме протокола URL : [1]

Start-Process ms-calculator:

К сожалению, начиная с PowerShell Core 7.0.0-preview.5 / Windows PowerShell v5.1, добавление -PassThru к вызову URL-адреса пакета AppX с Start-Process приводит к ошибке вместо возврата объекта, представляющего запущенный процесс - хотя Калькулятор по-прежнему запускает:

# 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 .


Обходной путь :

# 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 most recently launched instance is used.
$processStatus = (Get-Process -Name Calculator | Sort-Object TotalProcessTime)[0]

Примечание. Этот методне является надежным, учитывая, что другой процесс может гипотетически запускать экземпляр Calculator одновременно, но на практике он должен быть достаточно надежным.


[1] Для автоматического способа обнаруженияИмена протоколов приложения AppX по имени пакета или подстановочному знаку bчасть его - например, *Calculator*, см. этот ответ .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...