我试图创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的脚本商店”专栏
MSDN