Подтвердить что ты не робот

Powershell - если процесс не запущен, запустите его

Помогите пожалуйста. Я пытаюсь написать script, который будет проверять, запущен ли процесс, а если нет, запустите его. Если процесс запущен, он ничего не должен делать. Я до сих пор придумал следующее, но он запускает новый экземпляр процесса, независимо от того, работает ли он уже. Любая помощь приветствуется.

$Prog = "C:\utilities\prog.exe"
$Running = Get-Process prog -ErrorAction SilentlyContinue
$Start = ([wmiclass]"win32_process").Create($Prog)
if($Running -eq $null)
{$Start}
else
{}
4b9b3361

Ответ 1

Прежде всего, вот что не так в вашем коде. В вашем коде процесс создается до того, как вы оцениваете, запущена ли ваша программа

$Prog = "C:\utilities\prog.exe"
$Running = Get-Process prog -ErrorAction SilentlyContinue
$Start = ([wmiclass]"win32_process").Create($Prog) # the process is created on this line
if($Running -eq $null) # evaluating if the program is running
{$Start}

Можно создать блок кода, который должен быть дополнительно оценен в вашем коде, путем его переноса в {} (скриптовый блок):

$Prog = "C:\utilities\prog.exe"
$Running = Get-Process prog -ErrorAction SilentlyContinue
$Start = {([wmiclass]"win32_process").Create($Prog)} 
if($Running -eq $null) # evaluating if the program is running
{& $Start} # the process is created on this line

Однако, если вы ищете короткий однострочный лоток для решения своей проблемы:

if (! (ps | ? {$_.path -eq $prog})) {& $prog}

Ответ 2

В командлете Get-Process аргумент имени процесса должен быть именем исполняемого файла без расширения файла. Попробуйте заменить $Prog = "C:\utilities\prog.exe" на $Prog = "prog".

По-моему, ваш script был бы более читабельным, если бы вы отфильтровали процесс

Таким образом, вы можете избавиться от аргумента -ErrorAction SilentlyContinue, который может смутить кого-то, кто не знает о том, что выдает ошибку, если он не может найти процесс с указанным именем.

Ответ 3

Имейте в виду, что PowerShell обрабатывает объекты, а не только текст. В обычных командных файлах вы можете установить переменную в строку, а затем просто использовать ее как команду:

set Foo=dir /b
%Foo%

... это не работает в PowerShell. Таким образом, ваше назначение $Start уже создает новый процесс, так как команда после = запускается и ее результат присваивается $Start.

Кроме того, вы слишком усложняете вещи. Вместо этого я предлагаю следующее:

$Running = Get-Process prog -ErrorAction SilentlyContinue
if (!$Running) { Start-Process C:\utilities\prog.exe }

Так как Get-Process возвращает объект (который оценивается как $true) или $null (который оценивается как $false), вы можете упростить проверку, как показано выше. Это называется типом принуждения, так как оператор if ожидает логическое значение, а правила о том, что будет рассматриваться как $true и $false, очень согласованы в таких случаях, как указано выше. И он читается лучше.

Я также использовал командлет Start-Process вместо WMI для создания нового процесса. Вы даже можете использовать следующее:

if (!$Running) { C:\utilities\prog.exe }

если приложение не является консольным приложением (и, таким образом, блокирует PowerShell script до его выхода). PowerShell по-прежнему является оболочкой, поэтому запуск программ - это то, что работает очень хорошо: -)

Вы могли бы даже встроить переменную $running, но я думаю, комментарий был бы для уточнения того, что вы делаете.

Ответ 4

$path = "C:\utilities\prog.exe"        
$list = get-process | where-object {$_.Path -eq $path }     
if ($list -eq $null) { start-process -filepath $path }

Или

$path = "C:\utilities\prog.exe"
get-process | where-object {$_.Path -eq $path } | measure-object | where-object { $_.Count -eq 0} | foreach-object {start-process -filepath $path }

Это сохранит вам оператор if и одно объявление переменной. Это может быть команда одной строки:

  • Получить процессы
  • Выберите те, которые вас интересуют.
  • Используйте объект измерения, чтобы получить статистику о списке, который у вас есть.
  • Продолжайте конвейер только в том случае, если значение count для статистики равно 0
  • Процесс запуска

Не допускайте, чтобы foreach в конце вас отключал. Объект меры возвращает только один элемент, где будет возвращен один или ноль. Foreach используется только для выполнения, если результат равен нулю. Он не начнет больше, чем один процесс.:)