【问题标题】:PowerShell query Windows task scheduler for tasks that will run between specific datetimespowershell 查询 Windows 任务计划程序以获取将在特定日期时间之间运行的任务
【发布时间】:2021-04-07 21:09:09
【问题描述】:

我继承了一个服务器,它为数百个不同的进程运行 Windows 计划任务(主要是它启动自定义 PowerShell 脚本)——这些任务的计划可以是每 15 分钟一次,也可以是每年一次在特定日期。

如何使用 PowerShell(或任何其他方式)查询任务调度程序以确定将来是否有任何任务将在特定日期时间范围内运行?这是必要的,因此我们可以在此服务器以及与之交互的其他服务器上安排和执行维护。

【问题讨论】:

  • 欢迎来到堆栈溢出。对于有关 MS Windows 中任务计划的问题,我认为标记 taskschedule 不会为标记 taskscheduler 增加价值。
  • 这里是 wmi:get-ciminstance -ClassName MSFT_ScheduledTask -Namespace ROOT\Microsoft\Windows\TaskScheduler

标签: powershell scheduled-tasks scheduler taskscheduler


【解决方案1】:

这是获取下一个正在运行的作业的脚本

Get-ScheduledTask |
   Foreach-object { Get-ScheduledTaskInfo $_} |
   where-object {!($_.NextRunTime -eq $null)} |
   Select-object Taskname, NextRunTime |
   Sort-object -property NextRunTime

【讨论】:

  • 下一个运行时不会预测给定未来时间运行的内容。没有考虑任务的持续时间,也没有考虑重复或其他触发器等......
【解决方案2】:

欢迎来到 StackOverflow。我建议你阅读"How do I ask a good question"。你并不是真的在寻求帮助来解决问题。你在问如何在一个新项目上破土动工。话虽如此,因为这是一个社区,所以我会告诉你一些我对这个主题的了解以及我对编写这样一个工具的最初想法。

首先我应该提到这是一个看似复杂的话题。造成这种情况的原因很少,包括但不限于:

  1. 作为对象的计划任务可能非常复杂,具有广泛可变的计划、重复间隔、其他触发器类型和大量其他配置点。
  2. 非 GUI(即 CLI、cmdlet 和/或 API 工具)多年来发生了变化。而且,将它们串在一起来解决第 1 点中提到的复杂性并不总是那么容易。

警告:这份报告将很难写。在开始这样的挑战之前,您应该寻找任何可以清点或为任务计划程序提供其他透明度的预先存在的工具。

此外,将维护窗口定义为政策问题可能会更好。然后您可以配置作业以避免该窗口。乍一看,这让我觉得这比编写一个困难的程序来帮助挑选时隙要容易得多。

如果您选择继续前进,这里有一些工具可能会有所帮助:

  1. Schtasks.exe:一个功能惊人的 CLI 工具,已经存在了很长时间。
  2. TaskScheduler PowerShell 模块:围绕调度 COM 对象编写的 PowerShell 模块。它最初是 Windows 7 PowerShell 包的一部分,但现在您可以通过 PowerShell 库获得它。最简单的方法是通过典型的模块 cmdlet,例如 Find-ModuleInstall-Module
  3. 较新的 ScheduledTasks 模块默认安装在较新的 Windows 系统上。它围绕 Cim (WMI) 编写,默认安装在更高版本的 PowerShell / Windows 中。

注意:后两种工具很容易混淆。不仅名称非常相似,而且它们所包含的命令之间也存在重叠和相似性。例如,两个模块都有一个Get-Scheduledtask cmdlet。处理混淆的两种方法:

  1. 使用Import-Module cmdlet 导入模块时,使用-Prefix 参数为cmdlet 的none 部分添加前缀。然后在之后调用 cmdlet 时使用该前缀。
  2. 调用具有限定名称的 cmdlet,例如 TaskScheduler\GetScheduledTasks

现在获取调度数据。根据我的经验,所需的详细信息仅通过任务的 XML 定义公开。同样,您将遇到各种调度和/或触发选项带来的复杂性。您可以阅读有关 XML 架构 here

以下是一些如何访问 XML 数据的示例:

schtasks.exe /query /s pyexadm1 /tn <TaskName> /XML

在这种情况下,您必须进行额外的字符串操作以隔离 XML,然后将其转换为 [XML],以便您可以以典型的 PowerShell 方式使用它。显然,更广泛地利用这一工具将面临挑战。但是,了解快速检查和工作非常方便,尤其是在下一个工具无法立即使用的情况下。

注意:如果您不引用/TN 参数,所有任务都将被返回。虽然下一种方法更简单,但最好了解这种方法,在开发过程中会很方便。

下一个示例使用较旧的 TaskScheduler 模块(上面的#2):

$TaskXML = [XML](TaskScheduler\Get-ScheduledTask -ComputerName <ComputerName>-Name <TaskName>).XML

注意:以上假设没有使用前缀。因此,您必须引用源模块以防止与 ScheduledTask 模块混淆。

本示例加载 XML 文本并将其转换为单行中的 XmlDocument 对象。然后您可以访问有关任务的数据,如下所示:

$TaskXML.Task.Triggers.CalendarTrigger

这可能会产生如下输出:

StartBoundary       Enabled ScheduleByWeek
-------------       ------- --------------
2020-09-14T08:00:00 true    ScheduleByWeek

您可以通过利用管道大规模运行它,如下所示:

$XMLTaskData = 
TaskScheduler\Get-ScheduledTask -ComputerName <ComputerName> -Recurse | 
ForEach-Object{ [XML]$_.XML }

在上面的管道示例中,生成的 $XMLTaskData 是一个数组,每个元素都是一个相应的 XML 任务定义。

注意:使用-Recurse 开关参数。鉴于任务数量众多,如果将它们组织到子文件夹中,我不会感到惊讶。

同样,您也可以使用 ScheduledTasks 模块中的 Export-ScheduledTask cmdlet:

$TaskXML = [XML](Export-ScheduledTask -CimSession <ComputerName> -TaskName <TaskName>)

您可以像这样利用管道:

$XMLTaskData = 
Get-ScheduledTask -CimSession <ComputerName> | 
Export-ScheduledTask | 
ForEach-Object{ [XML]$_ }

与其他管道示例一样,这会产生一组 XML 任务定义。

注意:在这种情况下,没有-Recurse 参数。不过,您可以具体引用路径。

显然,使用这些方法中的任何一种,您都需要熟悉在 PowerShell 中使用 XML 对象,但有大量教程或其他资源可供使用。

同样,这里的复杂性在于处理许多触发器类型和调度范例。在获得最小可行程序 (MVP) 的过程中,您可能希望使用这些技术来清点现有任务。这可以帮助您确定开发过程的优先级。

最后一点;知道任务何时运行可能与知道它何时运行完全不同。例如,一项任务可能在下午 1:00 运行,但作业的持续时间是可变的且无法解释。这让我觉得很难应付。您可能需要另一个过程来在事件日志中查找任务完成事件。您可能还需要考虑可在 XML 数据中找到的执行时间限制。

【讨论】:

  • 我将深入研究 Schtasks.exe;到目前为止,我只是在试验这个模块(只知道这个)。你会碰巧知道我已经设置了一个停电窗口,但遗憾的是,这对我现有的 10 到 15 年的流程没有帮助,而且由于种类繁多,我们无法重新安排所有流程不幸的是,限制。这似乎是一个普遍的问题;我想我很惊讶没有更本地的解决方案。
  • 同意,即使在定义了策略之后,也并不总是容易解开。没有本地解决方案并不让我感到惊讶。 MS 做了很多,他们提供的足够多,让第 3 方(或其他 MS 产品)填补空白。实际上,考虑到您可能想要研究的工作数量。调度和编排领域可能有数十家供应商。MS System Center Orchestrator 就是一个例子。一家名为 Advanced System Concepts 的公司有一款名为 Active Batch 的产品,我很久以前就使用过。
  • 添加了一些管道示例。如果您认为这是一个有用的答案,如果您可以通过单击问题左侧的检查接受它,我将不胜感激。如果您有任何问题,请告诉我。
猜你喜欢
  • 2012-01-25
  • 2018-03-12
  • 2018-09-16
  • 2010-10-08
  • 1970-01-01
  • 2011-05-22
  • 2020-10-23
  • 2017-05-28
  • 1970-01-01
相关资源
最近更新 更多