【问题标题】:How to find the process ID of a running scheduled task?如何查找正在运行的计划任务的进程 ID?
【发布时间】:2018-08-21 23:22:03
【问题描述】:

我可以通过以下方式确定正在运行的任务:

$TaskService    = new-object -ComObject('Schedule.Service')
$TaskService.connect()
$TaskFolder = $TaskService.GetFolder('\')
$TaskFolder.gettasks(1) | ? {$_.state -eq 4}

如果这些任务与其他现有进程启动相同的程序(即进程名称),是否有任何方法可以识别这些任务的进程 ID?

我的目标是从计划任务启动的 PowerShell 脚本,该脚本可以识别它在哪个计划任务下运行。我可以使用$PID 轻松确定 PoSh 进程 ID,但我不知道如何将其链接到特定的计划任务。

谢谢。

【问题讨论】:

  • 我会更改脚本和任务,以便他们启动带有识别触发器参数的脚本...
  • 您可以在脚本中添加一个参数,您可以指定哪个任务启动它?像-StartedFrom SchedTask1 这样简单的东西
  • 命令行参数似乎是解决您问题的更好方法。也就是说,获取任务的 PID 并不难。对于所有正在运行的任务的列表,task service interface 有一个GetRunningTasks 方法。 OTOH,对于特定文件夹,遍历任务并在每个任务上调用 GetInstances。无论哪种情况,您都会获得一组正在运行的任务。正在运行的任务具有其NamePathCurrentActionEnginePID 的属性。后者是运行任务的进程的 PID。
  • @eryksun 这是一个答案。你应该这样写。
  • $TaskService.GetRunningTasks(0) 将根据eryksun 显示您有权查看的所有内容

标签: windows powershell scheduled-tasks taskscheduler


【解决方案1】:

如果您在作为操作触发的脚本中运行它,这应该可以工作。假设它可以被 RunningTasks COM 对象方法找到,它将获取任务路径

# Initiate a COM object and connect
$TaskService = New-Object -ComObject('Schedule.Service')
$TaskService.Connect()

# Query for currently running tasks 
# 0 - the user is permitted to see. 
# 1 - 0 + Hidden
$runningTasks = $TaskService.GetRunningTasks(0)

# Get the task associated to a certain PID
$runningTasks | Where-Object{$_.EnginePID -eq $PID} | Select-Object -ExpandProperty Path

感谢eryksun 指出方法并链接到ITaskService interface on MSDN


关于通过额外参数告诉你的脚本运行什么的其他建议有一些话要说。这样您就不必担心 COM 依赖关系。

param(
  [string]$SuperImportantString,
  [int]$NumberofBagels,
  [string]$TaskInitiated
)

Set-Content -Path $file -Value "I'm running from $TaskInitiated"

是的,这确实使它更加手动,但您可以最终控制文本和使用的文本,而不必担心从同一个 PID 运行多个任务。

【讨论】:

  • 感谢您正式撰写此答案,并感谢@eryksun 提供初始信息。
  • 我后来发现第一个答案适用于 SYSTEM 或 Admin 帐户,但非特权用户调用的 GetRunningTasks(1) 不会返回该用户的所有任务。正在运行的进程被标识为属于用户并且可以被用户看到,但是正在运行的任务列表(由用户检查)明显没有具有该ID的任务。管理员可以看到用户的运行任务。这一定是调度服务 API 中的错误。否则为什么会阻止用户查看自己正在运行的任务?
  • 更多详细信息:GetRunningTasks(1) 如果用户创建了任务,则工作正常,但如果任务是由管理员分配给用户的,则不能正常工作。因此,即使任务以用户身份运行,用户也无法(通过调度服务)看到它正在运行。在 Win10 中,任务似乎完全存储在注册表中(大部分信息都是二进制的)并且可以抵抗更改。用户创建的任务和管理员创建的任务权限相同。目前尚不清楚是什么限制了用户查看不是他们创建的任务。
  • 更新:显然,任务计划程序 GUI 和 TaskService 对象(例如 GetRunningTasks(1) 方法)的任务可见性由 Author 属性确定。以管理员身份创建以用户身份运行的任务不允许用户查看它。以管理员身份导入任务并将 Author 设置为用户或用户所属的组确实允许用户在 GUI 和脚本化的 TaskService 对象中查看任务.但是,非特权用户无权删除任务。任务上的 ACL 仍然是个谜。
【解决方案2】:

这似乎准确地告诉了我是哪个任务启动了脚本:

$EventFilter = @{ 
              Logname      = 'Microsoft-Windows-TaskScheduler/Operational'
              ProviderName = "Microsoft-Windows-TaskScheduler"
              Id           = 129
              Data         = "$PID"
           }

$ThisProcessEvent = Get-WinEvent -FilterHashtable $EventFilter -MaxEvents 1 -ErrorAction SilentlyContinue

$EventXML = [xml]$ThisProcessEvent.toxml()

$TaskFullName = $eventxml.event.eventdata.data | ? {$_.name -eq 'taskname'} |select -ExpandProperty "#text"

【讨论】:

  • 只要用户有权访问事件日志,这个答案(大部分)就可以工作。不幸的是,事件日志可能会稍微滞后于进程本身,并且不会返回任何事件。解决这个问题的唯一方法(我知道)是在寻找事件前几秒钟非常丑陋的start-sleep
猜你喜欢
  • 2013-07-03
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-23
相关资源
最近更新 更多