在Windows中启动另一个进程时如何启动进程?

我试图创build一个方法,将检查某个程序是否正在运行 – 如果是,则启动另一个程序。

这是我在英美烟草公司的进展

@ECHO OFF :LOOP tasklist /nh /fi "imagename eq steam.exe" | find /i "steam.exe" >nul && START "" "C:\Program Files\TeamSpeak 3 Client\ts3client_win64.exe" || goto :LOOP 

而且我创build了一个基本上在Windows启动时启动BAT的VBS(这只是为了确保batch file在没有可见控制台窗口的情况下运行):

 Set WshShell = CreateObject("WScript.Shell" ) WshShell.Run chr(34) & "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\if Steam running then TS.bat" & Chr(34), 0 Set WshShell = Nothing 

我的问题是,这样做,我得到一个令人难以置信的高CPU使用率(20至60%与I5-4670K)。

我做错了什么? 或者我可以改进代码吗? 我正在考虑减慢窗口检查过程的时间(比如等待2秒钟,然后检查),但是我真的很陌生,我不知道如何去做。

我知道我的英语不完美,对不起。

编辑:如果有帮助,我的电脑运行在Windows 10上。

我得到了令人难以置信的高CPU使用率

你需要让你的电脑在检查之间休息一下。 timeout命令会中断批处理执行一段可配置的秒数:

 @echo off setlocal set "FIND_STEAM=tasklist /nh /fi "imagename eq steam.exe" ^| find /i "steam.exe" ^> NUL" set "START_TS=start "C:\Program Files\TeamSpeak 3 Client\ts3client_win64.exe"" :LOOP timeout 5 > NUL %FIND_STEAM% && %START_TS% || goto LOOP 

编辑

这里是一个复杂的方式,用VBScript对Windows进程的启动和终止做出反应。

它与WMI一起工作 ,这是一个强大的框架,可以在Windows中执行各种各样的事情。 在这里,我们使用它来监听进程创建和进程终止事件。 (比起每秒轮询所有进程,听事件的效率要高很多):

 Option Explicit Dim WMIService, ProcessNew, ProcessEnd Dim computer, query, teamspeakPID ' create a WMI service object and ProcessNew / ProcessEnd event sinks computer = "." Set WMIService = GetObject("winmgmts:\\" & computer & "\root\CIMV2") Set ProcessNew = WScript.CreateObject("WbemScripting.SWbemSink", "ProcessNew_") Set ProcessEnd = WScript.CreateObject("WbemScripting.SWbemSink", "ProcessEnd_") ' we will be waiting for Win32_Process creation events and notify event sink "ProcessNew" WMIService.ExecNotificationQueryAsync ProcessNew, _ "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'" ' we will also be waiting for Win32_Process deletion events and notify event sink "ProcessEnd" WMIService.ExecNotificationQueryAsync ProcessEnd, _ "SELECT * FROM __InstanceDeletionEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'" ' main loop: nothing to do, we just sit and wait While True Wscript.Sleep(500) Wend ' function that handles "process created" events Sub ProcessNew_OnObjectReady(latestEvent, asyncContext) Dim process If LCase(latestEvent.TargetInstance.Name) = "steam.exe" Then ' start TeamSpeak Set process = GetObject("winmgmts:Win32_Process") process.Create "C:\Program Files\TeamSpeak 3 Client\ts3client_win64.exe", null, null, teamspeakPID End If End Sub ' function that handles "process ended" events Sub ProcessEnd_OnObjectReady(latestEvent, asyncContext) Dim processList, process If LCase(latestEvent.TargetInstance.Name) = "steam.exe" Then ' kill TeamSpeak (but only the one we started earlier) Set processList = WMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'ts3client_win64.exe' AND ProcessId = " & teamspeakPID) For Each process in processList process.Terminate() Next End If End Sub 

作为一个练习,您可以尝试扩展它,使其仅在尚未运行时才启动TS。

进一步阅读:

  • Technet“医生Scripto的脚本商店”专栏

    • 使用VBScript进行WMI异步事件监视
    • 不同步:异步事件监测的返回
  • MSDN

    • Win32_Process类
    • 创建Win32_Process类的方法
    • 终止Win32_Process类的方法
    • SWbemServices.ExecNotificationQueryAsAs方法