PowerShell-Skript zum Auflisten geplanter Aufgaben auf Remote-Systemen

37976
Ob1lan

Ich möchte ein PowerShell-Skript schreiben, das alle geplanten Aufgaben auf Remote-Systemen auflistet und das Benutzerkonto enthält, mit dem die einzelnen Aufgaben ausgeführt werden.

Auf dem lokalen System wird Windows 7 mit PowerShell 3.0 ausgeführt. Die Remote-Systeme reichen von Server 2003 bis 2008 R2 mit PowerShell-Versionen von 2.0 bis 3.0.

Welche PowerShell-Befehle oder -Funktionen kann ich für diese Aufgabe verwenden?

6
Was verwendet das lokale System? (Betriebssystem- und PowerShell-Version) Iszi vor 9 Jahren 0
@root: Wie Iszi sagte, wird dieses Cmdlet unter Windows Server 2012 oder Windows 8 unterstützt. Bitte lesen Sie die Frage sorgfältig durch, bevor Sie ein Kommentar verfassen / beantworten. Ob1lan vor 9 Jahren 0
@Iszi Das lokale System ist Windows 7 mit PowerShell v3 Ob1lan vor 9 Jahren 1
@ Ob1lan Ich habe meinen Kommentar wegen ungenauem / nicht hilfreichem Inhalt entfernt root vor 9 Jahren 0
@root Wenn Sie Win7 SP1 ausführen, sollten Sie ein Upgrade auf PowerShell 4.0 in Betracht ziehen. Dies kann dazu beitragen, Ihre Optionen ein wenig zu erweitern, obwohl Sie immer noch nicht das Niveau eines Win 8.1-Systems erreichen. Ich bin auch nicht zu 100% sicher, wie PowerShell funktioniert, wenn sich die Version auf dem lokalen System von der auf dem Remote-System unterscheidet. Ich habe dazu eine Frage [hier] (http://superuser.com/questions/811971/how-do-version-differences-affect-powershell-commands-on-remote-computers) gepostet. Iszi vor 9 Jahren 0
@Iszi Ich bin mir nicht sicher, ob ein Upgrade auf PowerShell v4 auf dem lokalen Computer in dieser Situation den Trick ausführen wird. In der Tat wird die Get-Scheduled-Task meines Wissens nicht für entfernte Systeme verwendbar. Ich denke, beide Systeme sollten es erkennen. Ich werde es so schnell wie möglich versuchen. Ob1lan vor 9 Jahren 0
Ack! @wurzel - verzeihen Sie die falsch gerichtete Erwähnung oben. Iszi vor 9 Jahren 0
@ Ob1lan Es wird Ihnen zwar nicht "Get-ScheduledTasks" bringen, aber es kann andere Funktionen und Funktionen haben, die nützlich sein könnten - wenn nicht für dieses bestimmte Skript, dann möglicherweise für andere. Ich bin mir jedoch noch nicht sicher, wie PowerShell Dinge behandelt, wenn sich die Remote-Version von der lokalen Version unterscheidet. Abhängig von den Befehlen und Funktionen, die Sie am Ende benötigen, können Sie sie möglicherweise nicht für Server 2003-Systeme verwenden, die nur bis zu PowerShell 2.0 unterstützen. Iszi vor 9 Jahren 0
@ Ob1lan Wenn du `ForEach-Object` noch nicht kennst, solltest du anfangen, mehr darüber zu erfahren. Was auch immer die Antwort sein wird, hat wahrscheinlich etwas in der Art von: 1. Erstellen Sie eine Liste von Servernamen in einer Textdatei (zB: Servers.txt), einen Namen / IP pro Zeile. 2. Get-Content Servers.txt | ForEach-Objekt {...} ` Iszi vor 9 Jahren 0

4 Antworten auf die Frage

8
Ob1lan

Ich habe endlich ein Skript geschrieben, das meinen Bedürfnissen entspricht. Dieses Skript "scannt" alle in AD aufgeführten Server und durchsucht den Ordner c: \ Windows \ System32 \ task nach XML-Dateien. Dann schreibt es den Wert des UserID-XML-Knotens jeder Datei in die endgültige CSV-Datei.

Noch nicht perfekt, aber es funktioniert vollständig, um alle Aufgaben aller Server aufzulisten und zu protokollieren, mit welchem ​​Benutzerkonto sie ausgeführt werden.

<# .Synopsis PowerShell script to list all Scheduled Tasks and the User ID .DESCRIPTION This script scan the content of the c:\Windows\System32\tasks and search the UserID XML value.  The output of the script is a comma-separated log file containing the Computername, Task name, UserID. #>  Import-Module ActiveDirectory $VerbosePreference = "continue" $list = (Get-ADComputer -LDAPFilter "(&(objectcategory=computer)(OperatingSystem=*server*))").Name Write-Verbose -Message "Trying to query $($list.count) servers found in AD" $logfilepath = "$home\Desktop\TasksLog.csv" $ErrorActionPreference = "SilentlyContinue"  foreach ($computername in $list) { $path = "\\" + $computername + "\c$\Windows\System32\Tasks" $tasks = Get-ChildItem -Path $path -File  if ($tasks) { Write-Verbose -Message "I found $($tasks.count) tasks for $computername" }  foreach ($item in $tasks) { $AbsolutePath = $path + "\" + $item.Name $task = [xml] (Get-Content $AbsolutePath) [STRING]$check = $task.Task.Principals.Principal.UserId  if ($task.Task.Principals.Principal.UserId) { Write-Verbose -Message "Writing the log file with values for $computername"  Add-content -path $logfilepath -Value "$computername,$item,$check" }  } } 

Die Ausgabe ist eine durch Kommas getrennte Datei, die auf Ihrem Desktop generiert wird, wie diese:

> SRV028,CCleanerSkipUAC,administrator > SRV029,GoogleUpdateTaskMachineCore,System > SRV030,GoogleUpdateTaskMachineUA,System > SRV021,BackupMailboxes,DOMAIN\administrator > SRV021,Compress&Archive,DOMAIN\sysScheduler 
hier eine PS-Version ohne XML-Lesezugriff: https://stackoverflow.com/a/53123962/1747983 Tilo vor 5 Jahren 0
5
laoist

Ich dachte, ich würde eine modifizierte Version des von Ob1lan geposteten Skripts freigeben. Die Änderung hilft dabei, Aufgaben in verschachtelten Ordnern zu finden, und listet den Status der Aufgabe sowie Details auf, die im Original enthalten sind.

$Computers = (get-adcomputer -filter ).name $ErrorActionPreference = "SilentlyContinue" $Report = @() foreach ($Computer in $Computers) { if (test-connection $Computer -quiet -count 1) { #Computer is online $path = "\\" + $Computer + "\c$\Windows\System32\Tasks" $tasks = Get-ChildItem -recurse -Path $path -File foreach ($task in $tasks) { $Details = "" | select ComputerName, Task, User, Enabled, Application $AbsolutePath = $task.directory.fullname + "\" + $task.Name $TaskInfo = [xml](Get-Content $AbsolutePath) $Details.ComputerName = $Computer $Details.Task = $task.name $Details.User = $TaskInfo.task.principals.principal.userid $Details.Enabled = $TaskInfo.task.settings.enabled $Details.Application = $TaskInfo.task.actions.exec.command $Details $Report += $Details } } else { #Computer is offline } } $Report | ft 

HINWEIS : Wenn Sie über viele Server verfügen, dauert die Ausführung sehr lange. Wenn Sie es parallel ausführen möchten, können Sie das Skript "invoke-parallel" (Google it) verwenden, das erheblich schneller ist:

. \\server\path\to\invoke-parallel.ps1 $Computers = (get-adcomputer -filter ).name $ErrorActionPreference = "SilentlyContinue" $Scriptblock = { $path = "\\" + $_ + "\c$\Windows\System32\Tasks" $tasks = Get-ChildItem -recurse -Path $path -File foreach ($task in $tasks) { $Details = "" | select ComputerName, Task, User, Enabled, Application $AbsolutePath = $task.directory.fullname + "\" + $task.Name $TaskInfo = [xml](Get-Content $AbsolutePath) $Details.ComputerName = $_ $Details.Task = $task.name $Details.User = $TaskInfo.task.principals.principal.userid $Details.Enabled = $TaskInfo.task.settings.enabled $Details.Application = $TaskInfo.task.actions.exec.command $Details } } $Report = invoke-parallel -input $Computers -scriptblock $Scriptblock -throttle 400 -runspacetimeout 30 -nocloseontimeout $Report | ft  

Beispielausgabe :

Bildschirmfoto

Schöne Bearbeitung, danke fürs Teilen! Ob1lan vor 6 Jahren 0
2
sanyam jain

Ich habe diesen Befehl verwendet, um alle Aufgaben aufzulisten:

 Invoke-Command -ComputerName "computername" -Credential Get-Credential 
Danke, aber ich kenne diesen Befehl bereits. Das Problem ist, dass PowerShell-Remoting aufgrund unserer Sicherheitsrichtlinien nicht auf allen Computern im Netzwerk ausgeführt werden kann. Ich bin auf einem anderen Skript viel einfacher. Ob1lan vor 9 Jahren 1
-1
Patrick E

Achtung: Vorbehalt: Besser verwenden -Literalpath, wie:

$TaskInfo = [xml](Get-Content -literalpath $AbsolutePath) 

oder get-contentgibt nichts zurück, wenn Ihre Tasknamen oder Ordnernamen Wildcards oder Regex-Zeichen enthalten, wie in meinem Fall "['und"] "...

Ja, Powershell scheint nicht nur Literal-Strings zu interpretieren, sondern auch den Inhalt von String-Typ-Variablen.