Как работать с процессами в Powershell используя Get и Start-Proccess


26 сентября 2019


Работа с процессами Powershell Start-Process и управление ими на примерах

Процессы - это один из основных компонентов Windows и чаще всего мы работаем с ними через Task Manager (диспетчер задач), но эта возможность становится весомее если мы используем команды по управлению процессами в Powershell. Основные команды по управлению запущенными задачами можно увидеть так:

Get-Command -Noun Process

Мы получим следующий вывод:

  • Debug-Process - возможность мониторинга и отладки процессов. Для его работы нужно загрузить дополнительное ПО.
  • Get-Process - получение в Powershell списка процессов.
  • Start-Process - запуск процессов.
  • Stop-Process - убивает (завершает) процесс.
  • Wait-Process - ожидание окончания процесса.

Таких команд и вариантов их использования очень много. Например мы можем работать с процессами через WMI или использовать их в связке с мониторингом сетевых подключений через Get-NetTCPConnection

Получив список процессов в Powershell можно увидеть что значения отображаются в Кб:

Get-Process

 Изменить это можно через выражения:

# В чем отображать значения 1MB,1GB,1TB и т.д.
$size = 1MB

Get-Process | Format-Table `
 @{Label = "NPM(K)"; Expression = {[int]($_.NPM / $size)}},
 @{Label = "PM(K)"; Expression = {[int]($_.PM / $size)}},
 @{Label = "WS(K)"; Expression = {[int]($_.WS / $size)}},
 @{Label = "CPU(s)"; Expression = {if ($_.CPU) {$_.CPU.ToString("N")}}},
 Id, ProcessName -AutoSize

В скрипте выше будут выводиться 5 свойств, но их намного больше. Посмотреть возможные свойства можно так:

Get-Process | Get-Member -MemberType Properties

Powershell свойства процессов

Каждое это свойство можно вызвать так:

Get-Process | SELECT Id
# или
Get-Process | FT id

Можно вызвать все свойства всех процессов или по одному выбранному:

Get-Process | SELECT *
# или
Get-Process -Name 'notepad' | SELECT *

Кроме свойств есть еще методы .NET, которые выводятся без дополнительных ключей или с указанием: 

Get-Process | Get-Member -MemberType Method

Методы полезны тем, что ими можно воспользоваться не прибегая к дополнительным командам. Для примера так мы можем остановить процесс notepad (блокнот) тремя разными способами:

# Удаление процесса используя метод .NET
$process = Get-Process -Name "notepad"
$process.Kill()
# Закрытие процесса используя командлет PS
Stop-Process -Name "notepad"
# Остановка процесса используя алиас PS kill
kill -Name "Notepad"
# Если мы хотим убить процесс по его идентификатору
kill -ID 332

Методы .NET не всегда так очевидны, как командлеты поэтому к ним нужно прибегать с осторожностью.

При получении списка процессов есть параметр, который выводит путь откуда запущен процесс и версию файла:

Get-Process -FileVersionInfo

В варианте выше у нас будет много не критичных ошибок:

  • Get-Process : Не удалось перечислить информацию о версиях файла для процесса "svchost".
  • Get-Process : Cannot enumerate the file version information of the "csrss" process.

Связано это с тем, что не все процессы в Powershell имеют версии и выполняется запрос несуществующего свойства. Этого можно избежать двумя путями, первый - это указать параметр, который будет игнорировать эти ошибки:

Get-Process -FileVersionInfo -ErrorAction SilentlyContinue

Или запросить информацию о конкретном процессе:

Get-Process -Name 'notepad' -FileVersionInfo

powershell процессы

Ключ FileVersionInfo это три свойства: Product, FileVersion и Path каждый из которых можно вывести отдельно. Получим процессы в Powershell со свойством времени запуска и отсортируем их:

Get-Process | select StartTime,Path,Name | sort StartTime

Если нужно выяснить когда и кто запустил процесс нужно добавить параметр IncludeUserName. В моем примере это два процесса:

Get-Process -Name 'notepad','explorer' -IncludeUserName | ft starttime,ProcessName,UserName

Эти же команды можно выполнять удаленно. Во всех командах Powershell, где есть ключ ComputerName можно указать минимум один удаленный компьютер:

Get-Process -ComputerName 'AD1','localhost'

Выполняя удаленную команду вы можете получить две ошибки. Первую, если у вас не настроена возможность удаленного управления в Powershell. И вторая, если вы укажете ключ -IncludeUserName, почему-то он не работает совместно с ComputerName:

  • Get-Process : Parameter set cannot be resolved using the specified named parameters.

 

Запуск процессов с Powershell Start-Process

На примере запуска блокнота команда выполняется так:

Start-Process -FilePath 'notepad'

Если исполняемый файл находится в другом месте нужно указать путь:

Start-Process -FilePath 'C:\Users\Administrator\Desktop\test.txt'

 Если в программа может принимать аргументы их так же можно добавить:

Start-Process -FilePath tracert -ArgumentList "-d -4 fixmypc.ru"

По умолчанию окно процесса разворачивается. Если хотите запустить свернутым, то добавьте ключ WindowStyle:

Start-Process -FilePath tracert -ArgumentList "-d -4 fixmypc.ru" -WindowStyle minimized

Ключ WindowStyle принимает 4 значения:

  • minimized - свернутый вариант.
  • hidden -  скрытый режим.
  • normal - обычный.
  • maximized - полностью развернутый.

Добавив ключ NoNewWindow, в случае с tracert, команда выполнится в текущем окне:

Start-Process -FilePath tracert -ArgumentList "-d -4 fixmypc.ru" -WindowStyle minimized

powershell start processЕсли мы запускаем процесс, который подразумевает вывод, но не хотим открывать окно программы, то нам понадобится перенаправить вывод команд. Для этого есть два ключа:

  • RedirectStandardOutput - перенаправляет вывод
  • RedirectStandardError  - перенаправляет ошибки
  • RedirectStandardInput - перенаправляет ввод

Воспользоваться этими ключами можно так:

Start-Process tracert -ArgumentList "-d -4 fixmypc.ru" -RedirectStandardOutput c:\success.txt -RedirectStandardError c:\error.txt  -WindowStyle minimized

 Если нужно открыть файл в определенной программе, то это делается так:

Start-Process -FilePath "C:\Windows\notepad.exe" "C:\Users\Administrator\Desktop\test.txt"

Отмечу, что ни одна команда PS не позволяет запускать процессы в интерактивном сеансе пользователя (например открыть пользователю Excel). Если вы хотите использовать такой метод, то вам нужно использовать psexec от SysInternals либо помещать задачи в планировщик и выполнять оттуда.

 

Пример по работе с процессами в Powershell

Директории, откуда работает основная часть программ относятся к Windows и Program Files. Работа программ из Application Data, например, всегда подозрительна. Мы можем мониторить запуск процессов из этой директории. Нам нужно объявить переменные с путями, которые не будут вызывать подозрений и проверять путь процессов на вхождение:

# Директория для проверки
$path = '*C:\Users*'
# Список компьютеров
$computers = 'AD1','localhost'
# Получение и фильтрация процессов 
$process = $computers |% {Get-Process -ComputerName $_ | where {$_.Path -like $path}
# Вывод результатов
$process
# Завершение процессов (закоментирован от случайного убийства нужных задач)
#$process | kill

process powershell

Второй пример выполнения - это запуск всех файлов из папки. Обычно скрипты применяются через групповые политики в момент входа пользователя. Если таких скриптов 10, то мы можем поместить их в определенную папку и запускать из планировщика задач указывая только директорию и расширение запускаемого файла и перенаправлять ошибки в индивидуальный файл:

# Директория для поиска файлов
$path = 'C:\dd\*'
# Поиск файлов и включение нужных и исключение ненужных
$items = Get-ChildItem -Path $path -Include '*exe*' -Exclude '*txt*'
# Сетевой путь, куда будут сохраняться ошибки
$error_path = '\\localhost\SYSVOL\'
$items |%  {Start-Process -FilePath $_ -WindowStyle Maximized -RedirectStandardError ($error_path + {hostname} + 'error.txt')}

Обратите внимание, что все файлы с ошибками будут сохраняться с именем компьютеров на котором запущен скрипт. В каждом из скриптов я так же ставил знак *, это связано не с точным вхождением. Например в первом случае после пути C:\Users* мы ожидаем еще символы и установив звездочку мы это указали. В случае Get-ChildItem ситуация похожая, но более подробно мы обсуждали в статье поиск файлов в Powershell.

Мы можем использовать поиск процессов не относящихся к производителям ПО, которые мы устанавливали на ПК пользователей. Для этого есть свойство Company. Не все объекты имеют имя компании, они связаны с задачами операционной системы:

$company = 'microsoft'
Get-Process | where {$_.company -notmatch $company} | Sort Company | Select ID,Name,WS,VM,Company | format-table -AutoSize

powershell список процессов

По умолчанию мы получаем данные по CPU в секундах, но следующий скрипт вернет процент использования:

function Get-CPUPercent
{
    $CPUPercent = @{
        Name = 'CPUPercent'
        Expression = {
            $TotalSec = (New-TimeSpan -Start $_.StartTime).TotalSeconds
            [Math]::Round( ($_.CPU * 100 / $TotalSec), 2)
        }
    }
 
    Get-Process | 
    Select-Object -Property Name, $CPUPercent, Description |
    Sort-Object -Property CPUPercent -Descending |
    Select-Object -First 10
}
Get-CPUPercent

 Далее эту функцию можно запускать на удаленных компьютерах:

$computers = 'AD1','localhost'
Invoke-Command -ComputerName $computers -ScriptBlock ${function:Get-CPUPercent} | ft

powershell get process

...

Теги: #powershell


Популярные тэги
О блоге
Этот блог представляет собой конспекты выученного материала, преобретенного опыта и лучшие практики в системном администрировании и программировании.