web-dev-qa-db-fra.com

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 de PowerShell de 2.0 à 3.0.

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

7
Ob1lan

J'ai finalement écrit un script qui convient à mes besoins. Ce script "analyse" tous les serveurs répertoriés dans AD, en recherchant les fichiers xml dans le dossier c:\Windows\System32\tasks. Ensuite, il écrira la valeur du nœud XML UserID de chaque fichier dans le fichier CSV final.

Pas encore parfait, mais fonctionne parfaitement pour répertorier toutes les tâches de tous les serveurs et consigner le compte d'utilisateur 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 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
Ob1lan

Hey pensait que je partagerais une version modifiée du script posté par Ob1lan. La modification permet de rechercher des tâches dans des dossiers imbriqués et répertorie le statut 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

NOTE: Si vous avez plusieurs serveurs, son exécution prendra beaucoup de temps. Si vous souhaitez l'exécuter en parallèle, vous pouvez utiliser le script invoke-parallel (Google it), qui est nettement 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 résultat :

Screenshot

5
laoist

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

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