Как создать задачу Windows, которая активируется на событие в Powershell

1742
nyshanin

Привет, мне нужно создать задачу Windows, которая будет работать так же, как сценарии выхода из системы в групповой политике (в нашей среде нет AD). Задача должна выполняться от имени вошедшего в систему пользователя, чтобы скрипт мог вывести имя пользователя, выполняющего ее, в файл .csv, который отслеживает время и даты выхода пользователя из системы / входа в систему. Я не уверен, что powershell - это лучший способ сделать это, но мне нужно иметь возможность создавать задачи как администратор, но настроить пользователя на запуск скрипта от имени текущего пользователя, который в данный момент вошел в систему. Это будет развернуто на несколько сотен машин.

Если есть другой способ отслеживания выхода пользователя из системы, меня бы очень заинтересовал этот метод, независимо от того, использует ли он PowerShell или нет. Ранее я пытался запустить сценарии, редактируя реестр, чтобы попытаться установить сценарии выхода из системы в GP, но это оказалось сложнее, чем я первоначально ожидал. Zenworks был другим вариантом, но он запускал сценарии только ПОСЛЕ того, как пользователь вышел из системы, в результате чего сценарий выводил неверные результаты в .csv.

Для справки, ссылка ниже содержит кого-то с подобной проблемой, но без некоторых специфических особенностей, на которые я должен ориентироваться.

https://stackoverflow.com/questions/33390035/windows-creating-a-task-for-an-event-from-the-command-line

-1
в чем твоя конкретная проблема? что вы пробовали и почему не получилось? flolilolilo 6 лет назад 0
@flolilolilo Проблема в основном связана с отсутствием AD. Если бы у меня была AD, я мог бы просто добавить скрипт выхода из системы через GP. Я пытался внести изменения в реестр, но мне не хватает знаний в скриптах PowerShell, поэтому затрудняется разработка более разумного решения. Я также пытался использовать Zenworks (нашу платформу развертывания пакетов) для запуска сценария при событии выхода пользователя из системы, но он всегда срабатывает слишком поздно (сценарии извлекают имя пользователя, вошедшего в систему в данный момент, и некоторые другие метрики, и помещают его в файл .csv. файл. Zenworks запускает скрипт после того, как пользователь уже вышел из системы.). nyshanin 6 лет назад 0

2 ответа на вопрос

0
BryKKan

Изменить: Значительно пересмотренный ответ из-за обновленного вопроса.
Это все еще плохая идея для сценария выхода из системы общего назначения - см. Этот вопрос для объяснения причин.

Ключевой аргумент вы должны смотреть на это /MO. Это модификатор. Согласно документу Microsoft SCHTASKS, когда /SCаргумент равен ONEVENT, тогда /MOразрешается строка запроса события XPath.

Этот блог Technet - Расширенная фильтрация XML в средстве просмотра событий Windows - описывает формат и предоставляет полезные примеры.

Исходя из того, что вы на самом деле делаете с данными, вам не нужно выполнять их в контексте выхода пользователя из системы. Это хорошо, поскольку позволяет избежать потенциального состояния гонки, присущего попытке запуска нового процесса в середине выхода из системы. Это также упрощает ваш запрос XPath:

*[System[EventID=4647]] 

Все, что вам действительно нужно сделать, - это убедиться, что задание, запущенное из этого события, получит подробную информацию о событии, которое его вызвало. Запланированные задачи хранятся в виде XML-файлов, и вы можете вручную редактировать XML-файл, добавляя дополнительные элементы XML-схемы планировщика задач, которые не отображаются через пользовательский интерфейс. Я предлагаю вам сначала создать задачу с помощью SCHTASKS или через пользовательский интерфейс со всеми значениями, которые вы можете указать. Затем экспортируйте его через пользовательский интерфейс или с помощью:

schtasks /Query [/S <system> [/U <username> [/P [<password>]]]] ` /XML /TN <taskname> >event.xml 

Статья Technet Запуск сценария PowerShell из события Windows предлагает хорошее объяснение и пример того, как его использовать. Однако ключевым атрибутом, который они добавили, был ValueQueries :

<ValueQueries> <Value name="eventChannel">Event/System/Channel</Value> <Value name="eventRecordID">Event/System/EventRecordID</Value> <Value name="eventSeverity">Event/System/Level</Value> </ValueQueries> 

Вместо того чтобы использовать EventRecordID для запроса обратно к событию, как они продемонстрировали, вы должны быть в состоянии получить ограниченные данные, которые вам нужны напрямую:

<Value name="logoffUsername">Event/EventData/Data[@Name='TargetUserName']</Value> 

Возможно, вы также захотите добавить TimeCreated, так как он должен быть более надежным, чем функция времени, вызываемая из вашего скрипта:

<Value name="eventTime">Event/System/TimeCreated/@SystemTime</Value> 

Это позволит вам ссылаться $(logoffUsername)и (необязательно) $(eventTime)в скрипте Powershell, выполняемом заданием.

Если вы хотите получить другие значения, XML-схема события определяется в MSDN . Я также сослался на сообщение в блоге Майкла Альберта о передаче параметров событий для примеров синтаксиса.

Закончив изменение определения задачи, вы можете импортировать один и тот же XML-файл на все компьютеры:

schtasks /Create [/S <system> [/U <username> [/P [<password>]]]] 

/ XML / TN

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

$cred = Get-Credential $password = $cred.GetNetworkCredential().Password $command = <your command> $myQuery = "*[System[EventID=4647] and EventData[Data [@Name='TargetUserName'] = '" + $env:username + "']]"  SCHTASKS /Create /TN "Logoff Monitor" /TR $command /SC ONEVENT ` /RL Highest /RU $cred.Username /RP $password ` /EC ScriptEvents /MO $myQuery 
Вы не указываете, какой из этих 5 ответов является релевантным. Честно говоря, пока вы не процитируете и не процитируете актуальную соответствующую информацию в своем ответе, я думаю, что добавлять цитату для вас нецелесообразно. Так что не стесняйтесь улучшать этот ответ, и я добавлю ссылку для вас. Ramhound 6 лет назад 0
Я только хочу отслеживать безопасность \ Аудит безопасности Microsoft Windows \ 4647. В моей среде AD не является чем-то особенным, и мне не удалось получить никаких ответов о внесении изменений в реестр, чтобы добавить сценарий выхода из системы через GP, поэтому кажется, что задачи являются наиболее разумным способом достижения моей цели. nyshanin 6 лет назад 0
@nyshanin AD не требуется для реализации сценариев выхода из системы. Вы также можете установить их в локальной политике. BryKKan 6 лет назад 0
@BryKKan Есть ли способ легко вносить изменения в локальную политику на многих машинах? nyshanin 6 лет назад 0
Я еще не использовал его сам, но старая версия больше не поддерживается, поэтому я бы посоветовал взглянуть на этот инструмент: https://blogs.technet.microsoft.com/secguide/2016/01/21/lgpo- EXE-локальной групповой политики объектно-утилита-V1-0 / BryKKan 6 лет назад 0
@BryKKan Я работаю с этим, и я еще не выяснил, как правильно импортировать вещи. nyshanin 6 лет назад 0
@nyshanin см обновленный ответ BryKKan 6 лет назад 0
@BryKKan, я ценю подробное описание, но после просмотра моих опций и попытки проверить мою идею планировщика заданий на нескольких машинах я пришел к выводу, что она не будет работать. С тех пор я создал четыре сценария powershell, которые Zenworks запускает при выходе из системы, входе в систему и запуске (журналы событий проверяются на наличие идентификаторов завершения и запуска при запуске в указанном порядке). Каждый из них добавляет запись в файл .CSV всякий раз, когда происходит соответствующее действие. nyshanin 6 лет назад 0
0
nyshanin

После попытки выполнить эту работу с планировщиком заданий я, наконец, пришел к выводу, что моя первоначальная идея не будет реализована так просто и надежно, как я надеялся. Отойдя от задач, но сохранив идею использовать PowerShell, я создал скрипт PowerShell, который zenworks мог запускать при выходе пользователя из системы, чтобы отслеживать детали, которые я счел актуальными. Этот скрипт можно найти здесь (это скрипт powershell, запускаемый через командный файл из-за проблем совместимости):

@@:: This prolog allows a PowerShell script to be embedded in a .CMD file. @@:: Any non-PowerShell content must be preceeded by "@@" @@setlocal @@set POWERSHELL_BAT_ARGS=%* @@if defined POWERSHELL_BAT_ARGS set POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"% @@PowerShell -Command Invoke-Expression $('$args=@(^&{$args} %POWERSHELL_BAT_ARGS%);'+[String]::Join([char]10,$((Get-Content '%~f0') -notmatch '^^@@'))) & goto :EOF  if( -Not (Test-Path -Path C:\Windows\Logs\$env:computername.csv ) ) { New-Item -Path C:\Windows\Logs\ -name "$env:computername.csv" -itemtype "file" }  $events = Get-WinEvent -FilterHashtable @ -MaxEvents 1 foreach ($event in $events) { #Writes events to XML file $eventXML = [xml]$event.ToXml()  #Converts Datetime of event into Two entries $DateTime = '' -f ($event.timecreated) $date = ($DateTime -split ' ')[0] $time = ($DateTime -split ' ')[1]  #Formats Outputs of data to prep for export $NewLine = ",,,," -f  "Logoff", $env:computername, $eventXML.Event.EventData.Data[1].'#text', $Date, $Time  #Exports Data to .csv $NewLine | add-content -path C:\Windows\Logs\$env:computername.csv }