-1

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

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

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

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

2 ответа2

0

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

Ключевым аргументом, на который вам нужно обратить внимание, является /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
0

После попытки выполнить эту работу с планировщиком заданий я, наконец, пришел к выводу, что моя первоначальная идея не будет реализована так просто и надежно, как я надеялся. Отойдя от задач, но сохранив идею использовать 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 @{LogName='Security'; ID=4647} -MaxEvents 1
foreach ($event in $events)
{
    #Writes events to XML file
    $eventXML = [xml]$event.ToXml()

    #Converts Datetime of event into Two entries
    $DateTime = '{0:MM/dd/yyyy hh:mm:ss}' -f ($event.timecreated)
    $date = ($DateTime -split ' ')[0]
    $time = ($DateTime -split ' ')[1]

    #Formats Outputs of data to prep for export
    $NewLine = "{0},{1},{2},{3},{4}" -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
}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .