Question Script Powershell pour répertorier les tâches planifiées sur des systèmes distants


Je souhaite écrire un script PowerShell qui répertorie toutes les tâches planifiées sur des systèmes distants et inclut le compte d'utilisateur qui sera utilisé pour exécuter chaque tâche.

Le système local exécute Windows 7, avec PowerShell 3.0. Les systèmes distants vont de Server 2003 à 2008 R2, avec les versions PowerShell de 2.0 à 3.0.

Quelles commandes ou fonctions PowerShell puis-je utiliser pour cette tâche?


5
2017-09-15 12:01


origine


Quel est le système local utilisé? (Version OS & PowerShell) - Iszi
@root: Comme Iszi l'a dit, cette cmdlet est prise en charge sur Windows Server 2012 ou Windows 8. Veuillez lire attentivement la question avant de commenter / répondre. - Ob1lan
@Iszi Le système local est Windows 7 avec PowerShell v3 - Ob1lan
@ Ob1lan J'ai enlevé mon commentaire pour être inexact / inutile - root
@root Si vous utilisez Win7 SP1, vous souhaiterez peut-être envisager une mise à niveau vers PowerShell 4.0. Cela peut aider à élargir un peu vos options, même si cela ne vous permettra pas d'atteindre le niveau d'un système Windows 8.1. Je ne suis pas sûr à 100% comment PowerShell fonctionne lorsque la version du système local est différente de celle du système distant. J'ai posté une question pour cela ici. - Iszi


Réponses:


J'ai finalement écrit un script qui répond à mes besoins. Ce script «analysera» tous les serveurs répertoriés dans AD, en recherchant dans le dossier c: \ Windows \ System32 \ tasks les fichiers XML. Ensuite, il écrira la valeur du noeud XML UserID de chaque fichier, dans le fichier CSV final.

Pas encore parfait, mais fonctionne totalement pour répertorier toutes les tâches de tous les serveurs, et enregistrer quel compte d'utilisateur est utilisé pour les exécuter.

<#
.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"
        }

    }
}

La sortie est un fichier séparé par des virgules et généré sur votre bureau, comme celui-ci:

> SRV028,CCleanerSkipUAC,administrator
> SRV029,GoogleUpdateTaskMachineCore,System
> SRV030,GoogleUpdateTaskMachineUA,System
> SRV021,BackupMailboxes,DOMAIN\administrator
> SRV021,Compress&Archive,DOMAIN\sysScheduler

8
2017-09-18 06:25





Hey, je pensais partager une version modifiée du script publiée par Ob1lan. La modification aide à trouver des tâches dans les dossiers imbriqués et répertorie l'état de la tâche ainsi que les détails inclus dans l'original.

$Computers = (get-adcomputer -filter {operatingsystem -like "*server*"}).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

REMARQUE: Si vous avez beaucoup de serveurs, cela prendra beaucoup de temps. Si vous souhaitez l'exécuter en parallèle, vous pouvez utiliser le script invoke-parallel (Google it), qui est significativement plus rapide:

. \\server\path\to\invoke-parallel.ps1
$Computers = (get-adcomputer -filter {operatingsystem -like "*server*"}).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 

Exemple de sortie:

Screenshot


5
2017-09-04 23:31



Nice edit, merci pour le partage! - Ob1lan


J'ai utilisé cette commande pour répertorier toutes les tâches:

        Invoke-Command -ComputerName "computername" -Credential Get-Credential {schtasks.exe}

2
2017-09-15 16:49



Merci, mais je connais déjà cette commande. Le problème est que la communication à distance PowerShell ne peut pas être effectuée sur tous les ordinateurs du réseau en raison de notre politique de sécurité. Je suis sur un autre script plus simple. - Ob1lan