Windows cmd或Powershell脚本来启动程序实例,获取其PID并在一段时间后停止它

问题描述

我正在尝试在Windows中使用命令行脚本实现以下目标:

  1. 启动启动GUI的程序(.exe)实例(还将一些参数传递给命令)
  2. 等待程序执行的特定时间(例如X秒)
  3. 终止执行

在某些情况下该程序的多个实例可以并行运行,因此我正在搜索的是一种能够终止由该程序先前启动的程序的特定实例的方式。 “启动”命令。我认为可能的一种方法是能够获得其PID,但是我不确定使用简单的命令行脚本时是否可以做到这一点。

我尝试过的是:

A)程序实例“ A”的命令行脚本

Start "" "C:\Program Files (x86)\XXXX\YYYY.exe" /USER=myUser /PASSWORDD=myPass  /CMDLINEID=winTsk_IntSO_A
timeout 180
taskkill /F /T /IM YYYY.exe /FI "USERNAME eq domain\username"
timeout 30
exit

B)程序实例“ B”的命令行脚本

Start "" "C:\Program Files (x86)\XXXX\YYYY.exe" /USER=myUser /PASSWORDD=myPass  /CMDLINEID=winTsk_IntSO_B
timeout 180
taskkill /F /T /IM YYYY.exe /FI "USERNAME eq domain\username"
timeout 30
exit

但是很明显如果我并行运行两个脚本,则首先执行的taskkill命令会终止两个实例(我将它们作为Windows计划任务在特定用户帐户下运行)。唯一标识每个实例的参数是/ CMDLINEID ,但我怀疑我是否可以根据该参数过滤正在运行的任务。

在@filimonic建议之后,我正在使用以下Powershell脚本来实现目标:

A)实例“ A”的Powershell脚本

$process = [System.Diagnostics.Process]::Start(
    'C:\Program Files (x86)\XXXX\YYYY.exe','/USER=myUser /PASSWORDD=myPass /CMDLINEID=winTsk_IntSO_A')

Write-Host $process.Id
Start-Sleep -Seconds 10

if (-not $process.HasExited) {
    $process.Kill()
}

A)实例“ B”的Powershell脚本

$process = [System.Diagnostics.Process]::Start(
'C:\Program Files (x86)\XXXX\YYYY.exe','/USER=myUser /PASSWORDD=myPass /CMDLINEID=winTsk_IntSO_B')

Write-Host $process.Id
Start-Sleep -Seconds 120

if (-not $process.HasExited) {
    //Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq $ppid } | ForEach-Object { Kill-Tree $_.ProcessId }
    //Stop-Process -Id $ppid
    $process.Kill()
}

这是可行的,但是我有以下问题:

  • YYYY.exe是一个GUI应用程序,其“加载”时间约为60秒
  • 一个具有“ 10秒”等待时间的脚本已正常执行,我可以在任务管理器中看到相应的“任务”也已终止
  • 具有“ 120秒” 等待时间的第二个脚本可以正常执行,但执行后,任务管理器(相同的PID)中的“任务”仍在运行

enter image description here

关于如何更有效地终止YYYY.exe运行实例的任何想法?

解决方法

通过一个脚本:

$process = [System.Diagnostics.Process]::Start('cmd.exe')
$process.Id #PID here
# ... Wait something #
$process.Kill()

从第二个脚本开始:($ storedProcessId以某种方式存储在脚本之间)。您可能需要管理员权限

$process = [System.Diagnostics.Process]::GetProcessById($storedProcessId)
$process.Kill()

当然,您可以使用其他更强大的powershell-native方式:

$process = Start-Process -PassThrough -FileName 'cmd.exe'

当然,两种方式都有带有命令行参数的变体。请参阅Process.StartStart-Process

的文档

所以您的脚本会像这样

$process = [System.Diagnostics.Process]::Start(
    'C:\Program Files (x86)\XXXX\YYYY.exe','/USER=myUser /PASSWORDD=myPass  /CMDLINEID=winTsk_IntSO_A')

Start-Sleep -Seconds 180

if (-not $process.HasExited) {
    $process.Kill()
}