So erstellen Sie eine Windows-Task, die bei einem Ereignis in Powershell aktiviert wird

1694
nyshanin

Hey, ich muss eine Windows-Task erstellen, die den Abmeldeskripts in den Gruppenrichtlinien (in unserer Umgebung ist kein AD) ähnlich ist. Die Task muss als angemeldeter Benutzer ausgeführt werden, damit das Skript den Namen des Benutzers, der es ausführt, in eine CSV-Datei ausgeben kann, in der die Abmelde- / Anmeldezeiten und -daten der Benutzer verfolgt werden. Ich bin nicht sicher, dass Powershell der absolut beste Weg ist, dies zu tun, aber ich muss die Aufgabe als Administrator erstellen können, aber der Benutzer muss das Skript als aktuell angemeldeten Benutzer ausführen, wer auch immer dies sein mag. Dies wird auf mehreren hundert Maschinen bereitgestellt.

Wenn es eine andere Möglichkeit gibt, die Abmeldung von Benutzern zu verfolgen, wäre ich sehr an dieser Methode interessiert, ob es sich dabei um Powershell handelt oder nicht. Zuvor habe ich versucht, die Skripts auszuführen, indem ich die Registrierung bearbeitete, um zu versuchen, Abmeldeskripts in GP festzulegen. Dies schien jedoch komplexer zu sein, als ich ursprünglich erwartet hatte. Zenworks war eine weitere Option, aber es wurden nur die Skripts ausgeführt, nachdem der Benutzer sich abgemeldet hatte, was dazu führte, dass das Skript falsche Ergebnisse in die CSV-Datei ausgab.

Als Referenz enthält der Link unten jemanden mit einem ähnlichen Problem, jedoch ohne einige Besonderheiten, die ich anvisieren muss.

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

-1
Was ist dein spezielles Problem? was hast du ausprobiert und warum ist es fehlgeschlagen? flolilolilo vor 6 Jahren 0
@flolilolilo Das Problem ist meistens auf AD zurückzuführen. Wenn ich AD hätte, könnte ich einfach ein Abmeldeskript über GP hinzufügen. Ich habe versucht, Änderungen an der Registrierung vorzunehmen, aber es fehlen mir Kenntnisse in Powershell-Skripten. Ich habe auch versucht, mit Zenworks (unserer Plattform zur Paketbereitstellung) ein Skript für ein Benutzerabmeldeereignis auszuführen, das jedoch immer zu spät ausgelöst wird (Die Skripts erfassen den aktuell angemeldeten Benutzernamen und einige andere Metriken und geben sie in eine CSV-Datei ein.) Datei. Zenworks löst das Skript aus, nachdem der Benutzer sich bereits abgemeldet hat. nyshanin vor 6 Jahren 0

2 Antworten auf die Frage

0
BryKKan

Bearbeiten: Deutlich überarbeitete Antwort aufgrund der aktualisierten Frage.
Dies ist immer noch eine schlechte Idee für ein allgemeines Abmeldeskript - eine Erläuterung der Gründe finden Sie in dieser Frage .

Das Schlüsselargument, das Sie betrachten müssen, ist /MO. Dies ist der Modifikator. Nach dem Microsoft-Dokument von SCHTASKS wird dann, wenn das /SCArgument lautet ONEVENT, /MOeine XPath-Ereignisabfragezeichenfolge zugelassen.

Dieses Technet-Blog - Erweiterte XML-Filterung in der Windows-Ereignisanzeige - beschreibt das Format und bietet nützliche Beispiele.

Je nachdem, was Sie tatsächlich mit den Daten tun, müssen Sie sie nicht im Kontext der Abmeldung durch den Benutzer ausführen. Dies ist gut, da dadurch die potenzielle Race-Bedingung vermieden wird, die beim Versuch besteht, einen neuen Prozess mitten in einer Abmeldung zu starten. Es vereinfacht auch Ihre XPath-Abfrage:

*[System[EventID=4647]] 

Alles, was Sie wirklich tun müssen, ist sicherzustellen, dass die von diesem Ereignis ausgelöste Aufgabe Details über das Ereignis erhält, das das Ereignis ausgelöst hat. Geplante Tasks werden als XML-Dateien gespeichert. Sie können die XML-Datei manuell bearbeiten, um zusätzliche Elemente des XML-Schemas für Taskplaner hinzuzufügen, die nicht über die Benutzeroberfläche verfügbar gemacht werden. Ich empfehle Ihnen, eine Aufgabe zuerst mit SCHTASKS oder über die Benutzeroberfläche mit allen Werten zu erstellen, die Sie angeben können. Dann exportieren Sie es über die Benutzeroberfläche oder mit:

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

Der Technet-Artikel Auslösen eines PowerShell-Skripts aus einem Windows-Ereignis bietet eine gute Erklärung und ein Beispiel, wie dies verwendet wird. Das Schlüsselattribut, das sie hinzufügten, war jedoch ValueQueries :

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

Anstatt die EventRecordID zu verwenden, um das Ereignis wie beschrieben abzurufen, sollten Sie die begrenzten Daten, die Sie benötigen, direkt einlesen können:

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

Vielleicht möchten Sie auch TimeCreated einlesen, da es zuverlässiger sein sollte als eine Zeitfunktion, die in Ihrem Skript aufgerufen wird:

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

Dies ermöglicht es Ihnen zu verweisen $(logoffUsername)und (optional) $(eventTime)in der Powershell - Skript durch die Aufgabe ausgeführt wird .

Falls Sie andere Werte einlesen möchten, ist das Event-XML-Schema auf MSDN definiert . Ich habe auch auf den Blogbeitrag von Michael Albert verwiesen, in dem er Ereignisparameter für Syntaxbeispiele übergeben hat.

Nachdem Sie die Aufgabendefinition geändert haben, können Sie dasselbe XML auf allen Computern importieren :

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

/ XML / TN

Hinweis: In der ursprünglichen Frage wurde ein Ereignis für einen Benutzer im Kontext dieses Benutzers erstellt und nur dann ausgeführt, wenn der Benutzer sich abgemeldet hat. Dies ist eine schlechte Idee aufgrund der oben genannten möglichen Rennbedingungen. Dies war die angebotene Lösung.

$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 
Sie geben nicht an, welche dieser 5 Antworten relevant ist. Ehrlich gesagt, bis Sie die aktuellen relevanten Informationen in Ihrer Antwort zitieren und zitieren, denke ich, dass das Hinzufügen des Zitats für Sie nicht sinnvoll ist. Fühlen Sie sich also frei, diese Antwort zu verbessern, und ich werde den Link für Sie hinzufügen. Ramhound vor 6 Jahren 0
Ich möchte nur Sicherheit \ Microsoft Windows-Sicherheitsüberwachung \ 4647 verfolgen. AD ist in meiner Umgebung keine Sache, und ich habe kläglich keine Antworten auf Änderungen an der Registrierung erhalten, um ein Abmeldeskript über GP hinzuzufügen. Es scheint also, dass Aufgaben der vernünftigste Weg sind, mein Ziel zu erreichen. nyshanin vor 6 Jahren 0
@nyshanin AD muss nicht vorhanden sein, um Abmeldeskripts zu implementieren. Sie können sie auch in der lokalen Richtlinie festlegen. BryKKan vor 6 Jahren 0
@BryKKan Gibt es eine Möglichkeit, die lokale Richtlinie auf vielen Computern einfach zu ändern? nyshanin vor 6 Jahren 0
Ich habe es zwar noch nicht selbst verwendet, aber die alte Version wird nicht mehr unterstützt. Ich schlage daher vor, dieses Tool zu betrachten: exe-local-group-policy-object-utility-v1-0 / BryKKan vor 6 Jahren 0
@BryKKan Ich arbeite damit und habe noch nicht herausgefunden, wie man Dinge richtig importiert. nyshanin vor 6 Jahren 0
@nyshanin siehe aktualisierte Antwort BryKKan vor 6 Jahren 0
@BryKKan, ich schätze die ausführliche Berichterstattung, aber nachdem ich meine Optionen überprüft und versucht hatte, meine Idee zum Task-Scheduler auf mehreren Computern zu testen, kam ich zu dem Schluss, dass dies nicht funktionieren würde. Seitdem habe ich vier Powershell-Skripts erstellt, die von Zenworks unter Logoff, Logon und Startup ausgeführt werden (Ereignisprotokolle werden beim Start in dieser Reihenfolge auf Herunterfahren und Startereignis-IDs geprüft). Jedes Element fügt einer CSV-Datei einen Eintrag hinzu, wenn eine verwandte Aktion auftritt. nyshanin vor 6 Jahren 0
0
nyshanin

Nachdem ich versucht hatte, diese Arbeit mit Taskscheduler zu erreichen, kam ich schließlich zu dem Schluss, dass meine ursprüngliche Idee nicht so einfach und zuverlässig umgesetzt werden konnte, wie ich es mir erhofft hatte. Ich entfernte mich von der Aufgabe, hatte aber die Idee, Powershell zu verwenden, ein Powershell-Skript, das zenworks bei User Logoff ausführen konnte, um die für mich relevanten Details zu verfolgen. Dieses Skript finden Sie hier (Es ist ein Powershell-Skript, das aufgrund von Kompatibilitätsproblemen durch eine Batch-Datei läuft):

@@:: 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 }