В этом посте описывается использование встроенного класса WMI __InstanceCreationEvent для отслеживания старта процесса. Важно — этот пост был написан для Windows PowerShell 1.0 и в нем рассказывается как получить информацию о старте процесса с использованием встроенного класса. Стоит упомянуть о существовании класса WMI Win32_ProcessStartTrace , использование которого несколько облегчает решение данной задачи. Главная задача этого поста — показать пример использования встроенного класса.
Некоторые примеры скриптов на VBScript вы можете найти в блоге Hey, Scripting Guy. Дополнительную информацию вы можете найти на этой странице. Книга издательства Microsoft Press Microsoft Windows Scripting with WMI: Self-Paced Learning Edition, содержит целую главу, посвященную работе с событиями.
Скрипт MonitorForProcessStartUp.ps1 получает информацию о процессе, после того как он запустится. Вот его текст:
Clear-Host
$Start = get-date
Write-Host «Waiting for a new process to be created …
You will be notified within 10 seconds of process creation
start time was $Start»
$Query = «select * from __instanceCreationEvent within 10
where targetInstance isa ‘win32_Process'»
$Eventwatcher = New-Object management.managementEventWatcher $Query
$Event = $Eventwatcher.waitForNextEvent()
$Event.targetInstance |
Format-List -property [a-z]*
Первое, что мы сделаем — это очистим экран. Сделаем мы это для того, чтобы скриншоты к посту выглядели как можно лучше, ну и, конечно, на пустом экране проще заметить, получили ли мы сообщение о событии. Вообще, рекомендуемый подход — это спросить пользователя, нужно ли очищать экран, потому как экран консоли может содержать нужную информацию и ее потеря может помешать пользователю, запустившему скрипт. Я лично с этим не сталкивался, но теоретически это возможно. Для очистки экрана мы используем командлет Clear-Host.
Clear-Host
Если вы все же решите, что пользователя стоит спросить, то вы можете использовать следующий код:
$response = Read-Host -prompt «Would you like to clear the screen? »
if($response -eq «yes») { clear-host }
Теперь нам нужно получить текущее время, или даже вместе с датой, как мы и поступаем в этом случае. Для получения текущей даты и времени мы использует командлет Get-Date. В качестве результата он возвращает объект System.DateTime. Мы сохраним его в переменной $Start. Возможно вы не разделяете моего отношения к замечательным объектам DateTime, однако это один из наиболее сильных мотиваторов для использования Windows PowerShell, а не VBScript. Почему? Ну я терпеть не мог манипуляции с этим видом объектов в VBScript. В следующей таблице вы можете видеть члены объекта DateTime.
Таблица 1. Члены объекта System.DateTime.
Name | Member Type | Definition |
Add |
Method |
System.DateTime Add(TimeSpan value) |
AddDays |
Method |
System.DateTime AddDays(Double value) |
AddHours |
Method |
System.DateTime AddHours(Double value) |
AddMilliseconds |
Method |
System.DateTime |
AddMinutes |
Method |
System.DateTime |
AddMonths |
Method |
System.DateTime |
AddSeconds |
Method |
System.DateTime |
AddTicks |
Method |
System.DateTime AddTicks(Int64 value) |
AddYears |
Method |
System.DateTime AddYears(Int32 value) |
CompareTo |
Method |
System.Int32 CompareTo(Object value), |
Equals |
Method |
System.Boolean Equals(Object value), |
GetDateTimeFormats |
Method |
System.String[] GetDateTimeFormats(), |
GetHashCode |
Method |
System.Int32 GetHashCode() |
GetType |
Method |
System.Type GetType() |
GetTypeCode |
Method |
System.TypeCode GetTypeCode() |
IsDaylightSavingTime |
Method |
System.Boolean IsDaylightSavingTime() |
Subtract |
Method |
System.TimeSpan Subtract(DateTime value), |
ToBinary |
Method |
System.Int64 ToBinary() |
ToFileTime |
Method |
System.Int64 ToFileTime() |
ToFileTimeUtc |
Method |
System.Int64 ToFileTimeUtc() |
ToLocalTime |
Method |
System.DateTime ToLocalTime() |
ToLongDateString |
Method |
System.String ToLongDateString() |
ToLongTimeString |
Method |
System.String ToLongTimeString() |
ToOADate |
Method |
System.Double ToOADate() |
ToShortDateString |
Method |
System.String ToShortDateString() |
ToShortTimeString |
Method |
System.String ToShortTimeString() |
ToString |
Method |
System.String ToString(), System.String ToString(String format), |
ToUniversalTime |
Method |
System.DateTime ToUniversalTime() |
DisplayHint |
NoteProperty |
Microsoft.PowerShell.Commands.DisplayHintType DisplayHint=DateTime |
Date |
Property |
System.DateTime Date {get;} |
Day |
Property |
System.Int32 Day {get;} |
DayOfWeek |
Property |
System.DayOfWeek DayOfWeek {get;} |
DayOfYear |
Property |
System.Int32 DayOfYear {get;} |
Hour |
Property |
System.Int32 Hour {get;} |
Kind |
Property |
System.DateTimeKind Kind {get;} |
Millisecond |
Property |
System.Int32 Millisecond {get;} |
Minute |
Property |
System.Int32 Minute {get;} |
Month |
Property |
System.Int32 Month {get;} |
Second |
Property |
System.Int32 Second {get;} |
Ticks |
Property |
System.Int64 Ticks {get;} |
TimeOfDay |
Property |
System.TimeSpan TimeOfDay {get;} |
Year |
Property |
System.Int32 Year {get;} |
DateTime |
ScriptProperty |
System.Object DateTime {get=if ($this.DisplayHint -ieq Date) { {0} -f $this.ToLongDateString() } elseif ($this.DisplayHint -ieq Time) { {0} -f $this.ToLongTimeString() } else { {0} {1} -f $this.ToLongDateString(), $this.ToLongTimeString() };} |
Для того, чтобы сохранить дату в переменной $Start мы используем следующую строку:
$Start = get-date
Теперь нам нужно сообщить пользователю, что же именно делает это скрипт. Для этого мы можем воспользоваться командлетом Write-Host. Мы воспользуемся тем, что переменная, указанная в строке, будет заменена на ее значение, чтобы вывести дату, содержащуюся в переменной $Start. Так как в Windows PowerShell строка, на оканчивающаяся символом кавычки считается продолженной на следующей строке, мы может расположить текст сообщения в трех строках и даже использовать в них символы возврата каретки.
Write-Host «Waiting for a new process to be created …
You will be notified within 10 seconds of process creation
start time was $Start»
При запуске скрипта, на экране высвечивается текст сообщения и текущие дата и время.
После того, как мы сообщили пользователю, что мы собираемся делать, мы можем создать наш запрос события.
$Query = «select * from __instanceCreationEvent within 10
where targetInstance isa ‘win32_Process'»
Теперь рам нужно создать объект event watcher. Для этого мы создадим новый экземпляр класса .NET Framework System.Management.ManagementEventWatcher. Для этого мы воспользуемся командлетом New-Object. Имя класса — ManagementEventWatcher, а пространство имен, в котором он находится — System.Management. Поскольку для создания экземпляра класса требуется знать пространство имен, в котором этот класс расположен, я всегда указываю полное имя класса. Возможно это может показаться несколько громоздким, но на мой взгляд это лучше, чем тратить 15 минут на поиск пространства имен класса на сайте MSDN.
При создании экземпляра класса мы передаем конструктору некоторые аргументы — для того, чтобы создать экземпляр с нужными нам параметрами. В нашем случае — это текст запроса, находящийся в переменной $query. Это мой любимый конструктор для этого класса. Другие его конструкторы можно найти на MSDN. Созданный объект мы сохраним в переменной $EventWatcher.
$Eventwatcher = New-Object system.management.managementEventWatcher $Query
Далее мы используем метод WaitForNextEvent класса System.Management.ManagementEventWatcher. Когда произойдет событие, возвращенный методом объект будет сохранен в переменной $event.
$Event = $Eventwatcher.waitForNextEvent()
Для того, чтобы получить свойства класса Win32_Process, олицетворяющего созданный процесс, мы запрашиваем значение свойства targetInstance полученного объекта и передаем его командлету Format-List, чтобы вывести значения всех свойств начинающихся с букв от a до z. Это позволит нам отфильтровать все системные свойства, имена которых начинаются с двух символов подчеркивания — например __NameSpace.
$Event.targetInstance |
Format-List -property [a-z]*
В результате мы получим такой же набор информации, как и при обычном запросе класса WMI Win32_Process.
Авторы: Ed Wilson and Craig Liebendorfer, Scripting Guys
Страницы в социальных сетях:
Twitter: https://twitter.com/vsseth
Facebook: https://fb.com/inpowershell
VKontakte: https://vk.com/inpowershell