我想编写一个 PowerShell 脚本,列出远程系统上的所有计划任务,并包含用于运行每个任务的用户帐户。
本地系统运行的是 Windows 7,带有 PowerShell 3.0。远程系统范围从 Server 2003 到 2008 R2,带有 PowerShell 版本从 2.0 到 3.0。
我可以使用哪些 PowerShell 命令或函数来完成此任务?
答案1
我终于写了一个符合我需求的脚本。此脚本将“扫描” AD 中列出的所有服务器,在 c:\Windows\System32\tasks 文件夹中搜索 xml 文件。然后,它将在最终的 CSV 文件中写入每个文件的 UserID xml 节点的值。
虽然尚不完善,但完全可以列出所有服务器的所有任务,并记录使用哪个用户帐户来运行它们。
<#
.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"
}
}
}
输出是桌面上生成的以逗号分隔的文件,如下所示:
> SRV028,CCleanerSkipUAC,administrator
> SRV029,GoogleUpdateTaskMachineCore,System
> SRV030,GoogleUpdateTaskMachineUA,System
> SRV021,BackupMailboxes,DOMAIN\administrator
> SRV021,Compress&Archive,DOMAIN\sysScheduler
答案2
嘿,我想分享一下 Ob1lan 发布的脚本的修改版本。修改后可帮助查找嵌套文件夹中的任务,并列出任务的状态以及原始脚本中包含的详细信息。
$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
笔记:如果您有许多服务器,这将需要很长时间才能运行。如果您想并行运行它,可以使用invoke-parallel脚本(谷歌一下),它是显著地快点:
. \\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
示例输出:
答案3
我使用此命令列出所有任务:
Invoke-Command -ComputerName "computername" -Credential Get-Credential {schtasks.exe}
答案4
我想获得更多信息(如 LastRunTime 和 LastTaskResult),因此我将 DD 的脚本修改为:
$Date = Get-Date -f "yyyy-MM-dd"
$Time = Get-Date -f "HH-mm-ss"
$Computers = (get-adcomputer -filter {operatingsystem -like "*server*"}).name
$Computers >C:\Temp\servers_"$Date"_"$Time".txt
$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)
{
$Info = Get-ScheduledTask -CimSession $Computer -TaskName $task | Get-ScheduledTaskInfo | Select LastRunTime, LastTaskResult
$Details = "" | select ComputerName, Task, User, Enabled, Application, LastRunTime, LastTaskResult
$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.LastRunTime = $Info.LastRunTime
$Details.LastTaskResult = $Info.LastTaskResult
$Details
$Report += $Details
}
}
else
{
#Computer is offline
}
}
$Report | Export-csv C:\Temp\Tasks_"$Date"_"$Time".csv -NoTypeInformation
它需要更多时间来执行,但我认为您已经拥有所需的所有信息。