Windows 任务计划程序图表?

Roo*_*oop 5 windows windows-server-2008 scheduled-tasks windows-server-2012

有谁知道是否有任何实用程序/工具可以根据时间和日期制作 Windows 任务计划程序中所有任务的图表,所以我会知道在某个时间点是否有任何重叠导致服务器过载?

我们有一个用于所有计划任务的服务器,由于前管理员的设计不佳,它最近运行缓慢,现在我需要找出每个任务的运行窗口,我可以在 excel 中手动制作图表,但它也是如此多要一一去。

希望会有一些实用程序可以做到这一点。

bea*_*ker 3

此 Powershell 脚本将读取任务计划程序的事件日志并导出为CSV Task NameStart DateFinish DateDuration已启动的所有任务然后,您可以将此数据输入到您选择的电子表格中并构建甘特图。

\n\n

要求:

\n\n
    \n
  • 电源外壳2.0
  • \n
  • Windows Server 2008\\Vista
  • \n
\n\n

脚本接受以下参数:

\n\n
    \n
  • Computers要查询的计算机名称数组。如果不指定,将查询本地计算机。
  • \n
  • MaxEvents从事件日志中读取的最大事件数。默认值为 100。
  • \n
  • 路径磁盘上的现有文件夹,其中将保存 CSV。如果未指定,将使用脚本文件夹。CSV 的命名如下:COMPUTERNAME_TaskScheduler.csv
  • \n
  • 用户远程认证的用户名。
  • \n
  • 密码用户的密码。如果未指定,将由脚本请求。
  • \n
  • 详细脚本将通过消息告诉您发生了什么Write-Verbose
  • \n
\n\n

示例(从 PowerShell 控制台运行):

\n\n

从本地计算机获取数据,处理最近 100 个事件,将 CSV 保存到脚本文件夹:

\n\n\n\n
.\\TS_Gantt.ps1\n
Run Code Online (Sandbox Code Playgroud)\n\n

从远程计算机获取数据,处理最近 200 个事件,将 CSV 保存到c:\\ts_gantt文件夹:

\n\n\n\n
.\\TS_Gantt.ps1 -Computers Sun, Earth, Moon -MaxEvents 200 -Path \'c:\\ts_gantt\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

脚本 (TS_Gantt.ps1):

\n\n\n\n
Param\n(\n    [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]\n    [ValidateNotNullOrEmpty()]\n    [string[]]$Computers = $env:COMPUTERNAME,\n\n    [Parameter(ValueFromPipelineByPropertyName = $true)]\n    [ValidateRange(1, 2147483647)]\n    [int]$MaxEvents = 100,\n\n    [Parameter(ValueFromPipelineByPropertyName = $true)]\n    [ValidateScript({\n        if(!(Test-Path -LiteralPath $_ -PathType Container))\n        {\n            throw "Folder doesn\'t exist: $_"\n        }\n        $true\n    })]\n    [ValidateNotNullOrEmpty()]\n    [string]$Path,\n\n    [Parameter(ValueFromPipelineByPropertyName = $true)]\n    [ValidateNotNullOrEmpty()]\n    [string]$User,\n\n    [Parameter(ValueFromPipelineByPropertyName = $true)]\n    [string]$Password\n\n)\n\n# Get script path, to save CSV\'s, if not specified\nif(!$Path)\n{\n    if($psISE.CurrentFile.FullPath)\n    {\n        $Path = $psISE.CurrentFile.FullPath | Split-Path\n    }\n    elseif($script:MyInvocation.MyCommand.Path)\n    {\n        $Path = $script:MyInvocation.MyCommand.Path | Split-Path\n    }\n    else\n    {\n        $Path = $PWD.Path\n    }\n\n    Write-Verbose "No Path specified, defaulting to: $Path"\n}\n\n# Get user credentials, if needed\nif($User)\n{\n    Write-Verbose "User specified: $User"\n    if($Password)\n    {\n        Write-Verbose \'Password specified, converting to credentials object\'\n        $SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force\n        $Credentials =  New-Object System.Management.Automation.PSCredential -ArgumentList $User, $SecurePassword\n    }\n    else\n    {\n        Write-Verbose \'Password not specified, requesting from user.\'\n        $Credentials = Get-Credential -UserName $User -Message "Enter password for user: $User" -ErrorAction Stop\n        if(!$Credentials)\n        {\n            Write-Verbose \'User cancelled password request\'\n        }\n    }\n}\n\n# https://mnaoumov.wordpress.com/2014/05/15/task-scheduler-event-ids/\n$TaskStartId = 100\n$TaskFinishId = 102\n$FilterXml = @"\n<QueryList>\n  <Query Id="0" Path="Microsoft-Windows-TaskScheduler/Operational">\n    <Select Path="Microsoft-Windows-TaskScheduler/Operational">*[System[(EventID=$TaskStartId or EventID=$TaskFinishId)]]</Select>\n  </Query>\n</QueryList>\n"@\n\n# Hashtable to hold results\n$Result = @{}\n\n# Loop through computers\nforeach ($PC in $Computers){\n\n    # Grab the events from a PC\n    $Params = @{\n        ComputerName = $PC\n        FilterXml = $FilterXml\n        MaxEvents = $MaxEvents\n    }\n\n    if($Credentials)\n    {\n        $Params += @{Credential = $Credentials}\n    }\n\n    Write-Verbose "Trying to get Task Scheduler\'s event log. Computer: $PC"\n    try\n    {\n        $Events = Get-WinEvent @Params -ErrorAction Stop\n        Write-Verbose "Success"\n    }\n    catch\n    {\n        Write-Error "Can\'t access Task Scheduler\'s event log. Computer: $PC"\n        continue\n    }\n\n    if(!$Events)\n    {\n        Write-Error "Task Scheduler\'s event log is empty! Computer: $PC"\n        continue\n    }\n\n    Write-Verbose \'Extracting additional data from events\'\n    $Events |\n        ForEach-Object {\n            # Hashtable for new properties\n            $Properties = @{}\n\n            # Convert the event to XML and iterate through each one       \n            # of the XML message properties to extract additional data  \n            ([xml]$_.ToXml()).Event.EventData.Data |\n                ForEach-Object {\n                    $Properties.Add($_.name, $_.\'#text\')\n                }\n\n            # Add extracted properties to the event object\n            $_ | Add-Member -NotePropertyMembers $Properties\n        }\n\n    # Set default start\\finish date for event in case\n    # it\'s still running or was started before $MaxEvents\n    $DefaultStartDate = $Events[-1].TimeCreated\n    $DefaultFinishDate = Get-Date\n    Write-Verbose "Default task start date: $DefaultStartDate"\n    Write-Verbose "Default task finish date: $DefaultFinishDate"\n\n    Write-Verbose \'Processing events...\'\n    # Group events by ID and process them\n    $PcEvents = $Events |\n        Group-Object -Property InstanceId |\n            ForEach-Object {\n                # Get Name and start\\finish Date\n                $TaskName = $_.Group[0].TaskName\n                $StartDate = ($_.Group | Where-Object {$_.OpcodeDisplayName -eq \'Start\'}).TimeCreated\n                $FinishDate = ($_.Group | Where-Object {$_.OpcodeDisplayName -eq \'Stop\'}).TimeCreated\n\n                # If we can\'t get dates, set them to defaults\n                if(!$StartDate)\n                {\n                    $StartDate = $DefaultStartDate\n                }\n                elseif(!$FinishDate)\n                {\n                    $FinishDate = $DefaultFinishDate\n                }\n\n                # Hashtable holding object\'s properties\n                $ItemProp = @{\n                    Name = $TaskName\n                    StartDate = $StartDate\n                    FinishDate = $FinishDate\n                    Duration = $FinishDate - $StartDate\n                }\n\n                # Output new object to the pipeline\n                New-Object psobject -Property $ItemProp |\n                    Select-Object Name, StartDate, FinishDate, Duration\n        }\n\n    # Add data to results\n    $Result += @{$PC = $PcEvents}\n}\n\n\n# Loop through results\n$Result.GetEnumerator() |\n    ForEach-Object {\n        # Export results to CSV, one file per computer\n        $CsvPath = Join-Path -Path $Path -ChildPath ($_.Key + \'_TaskScheduler.csv\')\n        Write-Verbose "Saving data to CSV: $CsvPath"\n        $_.Value | Export-Csv -LiteralPath $CsvPath -Force -NoTypeInformation\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

更新 (1):我添加了以不同用户身份进行身份验证的功能(用户名\\密码参数),并切换到使用 XML 进行过滤,这更快,并且应该允许针对 Vista\\Server 2008 PC 运行此脚本(避免这种情况)漏洞)。此外,现在还兼容 PowerShell 2.0。

\n\n

更新(2):我已经调整了脚本的路径检测,因此现在它不应在 Powershell ISE 中中断。另外,我发现在某些电脑上,任务计划程序日志被禁用。以下是验证日志记录是否已启用的方法:

\n\n
    \n
  1. 检查是否已All Tasks History启用。它应该读Disable All Tasks History(呃):
  2. \n
\n\n

所有任务历史记录

\n\n
    \n
  1. 检查任务计划程序是否Operational事件日志是否已启用。\n打开:

    \n\n

    Event Viewer\xe2\x86\x92 Applications and Services Log\xe2\x86\x92 Microsoft\xe2\x86\x92 Windows\xe2\x86\x92 Task Scheduler\xe2\x86\x92 \ Operationalxe2\x86\x92 右键单击​​它,(或转到右侧窗格)Properties

  2. \n
\n\n

任务计划程序操作事件日志

\n\n

任务计划程序操作事件日志属性

\n\n

更新(3):修复了丢失或不可用事件日志的处理,添加了一堆Verbose消息。

\n