批量启动程序 B 时停止程序 A,在结束程序 B 时启动程序 A
Batch Stop Program A on Launch Program B, Start Program A on End Program B
我使用 Google 的同步程序同步我的文档。但是,当我打开某些程序时,我不希望同步程序干扰我的项目文件。我尝试的解决方案如下。
这是一种非常笨拙的方法,试图在程序 B 启动时关闭程序 A,然后在程序 B 停止时重新打开程序 A 运行。下面的批处理脚本有效地做到了这一点,但它占用了相当大的处理器资源(在我的第 8 代移动 i5 上占 1% 到 4%)。有没有更优雅的方法来做到这一点?我愿意考虑其他工具(即 AutoIT)。
编辑,根据建议,我在最后添加了一个简单的 15 秒超时,这使得该程序可以接受处理器密集型(即,不是)。 运行 这通过隐藏的任务调度程序使它成为一个可行的解决方案。
@echo off
rem mutually exclusive program enforcer
rem initialize variables
set gDriveOn=init
set reaperOn=init
rem begin infinite loop for monitoring on states
:loopStart
tasklist /FI "IMAGENAME eq reaper.exe" 2>NUL | find /I /N "reaper.exe">NUL
if "%ERRORLEVEL%"=="0" (
set reaperOn="TRUE"
goto gDrivecheck
)
rem else if reaper not found
set reaperOn="FALSE"
:gDriveCheck
tasklist /FI "IMAGENAME eq googledrivesync.exe" 2>NUL | find /I /N "googledrivesync.exe">NUL
if "%ERRORLEVEL%"=="0" (
set gDriveOn="TRUE"
goto doStuff
)
rem else if Google Drive not found
set gDriveOn="FALSE"
:doStuff
rem turn off gdrive when reaper is on
if %reaperOn% == "TRUE" (
if %gDriveOn% == "TRUE" (
taskkill /f /t /im googledrivesync.exe
)
)
if %reaperOn% == "FALSE" (
if %gDriveOn% == "FALSE" (
start C:\"Program Files"\Google\Drive\googledrivesync.exe
)
)
rem delay 15 seconds for efficiency
timeout 15
goto :loopStart
)
rem end of infinite loop
)
因为发布的源代码没有 运行 我不会尝试回答问题的稳定性部分。请参阅我之前关于建议如何自行调试的评论。
至于表现:
批处理文件延迟
如果我没有遗漏任何东西,这段代码会不断请求是否存在一对进程。也就是说,它会在上一个检查完成后立即开始下一个检查,一次又一次,中间没有停顿。
这基本上是指示您的计算机将所有可用的处理能力用于检查进程是否存在。这个程序理论上应该使用 100% CPU,但是由于某些原因,在 Windows 下列出任务是缓慢且低效的,而且你可能有一个 CPU 核心,批处理是本身变慢,它只能使用 CPU.
的一小部分
您很可能不需要那么频繁地检查进程。这通常在 1 到 10 秒内完成一次。如果这是可以接受的,请在代码中的某处插入延迟,如下所示:
TIMEOUT /T 5 /NOBREAK
其中 5 是等待的秒数。有关详细信息,请参阅 timeout /?
或 this。
AutoIT
在 AutoIt 中,您需要 ProcessExists()
检查进程是否存在,Sleep()
插入延迟。杀死一个进程是通过 ProcessClose()
完成的, Run()
启动一个。该文档可在 here Function Reference
下找到
检查 windows 上的进程仍然缓慢且效率低下。 AutoIT 文档建议 the process is polled approximately every 250 milliseconds
这可能意味着如果您尝试更快地请求它,您将获得上次保存的结果,因此插入 Sleep(250)
或更多是有意义的。
然而,这主要适用于按名称查询进程,它请求所有 运行ning 进程的列表并在其中搜索您的进程。如果您知道某个进程已经存在,则无需执行此操作 - 您可以简单地使用其进程 ID 号 (PID) 来检查它是否已停止 - 这应该会更快。所以除了 ProcessExists("notepad.exe")
你还可以这样做:
local $pid = 0
while true
if ($pid <> 0) then $pid = ProcessExists($pid) ;Process already existed, use PID
if ($pid = 0) then $pid = ProcessExists("notepad.exe") ;Process did not exist
if ($pid <> 0) then
;do something if process exists...
endif
sleep(300)
.........
wend
这是有效的,因为 ProcessExists()
returns 如果进程存在则为 PID,否则为 0。
第一 if
行 运行s 如果 $pid
从我们上次检查时就已经知道了。
如果不是,或者如果我们之前从未检查过,或者如果它是但不再存在,则第二行 运行s 并根据进程名称进行检查。这应该在第二个过程中重复。请注意,这不是故意的 if-then-else
,因为第一次检查可能会将 $pid
设置为 0
。
EXE替换
如果上述解决方案不起作用——例如,如果 reaper.exe
碰巧试图访问 googledrivesync.exe
持有的内容,它就会严重崩溃——那么可能应该采取其他措施。
一个选择是将 reaper.exe
重命名为 real_reaper.exe
并将一个自动脚本编译成新的 reaper.exe
以杀死 googledrivesync
并启动 real_reaper.exe
。此脚本需要传递所有参数,例如
RunWait ('"real_reaper.exe" ' & $CmdLineRaw)
应该可以解决问题。这等待 real_reaper.exe
完成 运行ning 然后你可以做 Run("googledrivesync.exe")
如果启动 reaper.exe
的程序使用了一些技巧,这可能无法正常工作,但在大多数情况下应该可以正常工作。
我使用 Google 的同步程序同步我的文档。但是,当我打开某些程序时,我不希望同步程序干扰我的项目文件。我尝试的解决方案如下。
这是一种非常笨拙的方法,试图在程序 B 启动时关闭程序 A,然后在程序 B 停止时重新打开程序 A 运行。下面的批处理脚本有效地做到了这一点,但它占用了相当大的处理器资源(在我的第 8 代移动 i5 上占 1% 到 4%)。有没有更优雅的方法来做到这一点?我愿意考虑其他工具(即 AutoIT)。
编辑,根据建议,我在最后添加了一个简单的 15 秒超时,这使得该程序可以接受处理器密集型(即,不是)。 运行 这通过隐藏的任务调度程序使它成为一个可行的解决方案。
@echo off
rem mutually exclusive program enforcer
rem initialize variables
set gDriveOn=init
set reaperOn=init
rem begin infinite loop for monitoring on states
:loopStart
tasklist /FI "IMAGENAME eq reaper.exe" 2>NUL | find /I /N "reaper.exe">NUL
if "%ERRORLEVEL%"=="0" (
set reaperOn="TRUE"
goto gDrivecheck
)
rem else if reaper not found
set reaperOn="FALSE"
:gDriveCheck
tasklist /FI "IMAGENAME eq googledrivesync.exe" 2>NUL | find /I /N "googledrivesync.exe">NUL
if "%ERRORLEVEL%"=="0" (
set gDriveOn="TRUE"
goto doStuff
)
rem else if Google Drive not found
set gDriveOn="FALSE"
:doStuff
rem turn off gdrive when reaper is on
if %reaperOn% == "TRUE" (
if %gDriveOn% == "TRUE" (
taskkill /f /t /im googledrivesync.exe
)
)
if %reaperOn% == "FALSE" (
if %gDriveOn% == "FALSE" (
start C:\"Program Files"\Google\Drive\googledrivesync.exe
)
)
rem delay 15 seconds for efficiency
timeout 15
goto :loopStart
)
rem end of infinite loop
)
因为发布的源代码没有 运行 我不会尝试回答问题的稳定性部分。请参阅我之前关于建议如何自行调试的评论。
至于表现:
批处理文件延迟
如果我没有遗漏任何东西,这段代码会不断请求是否存在一对进程。也就是说,它会在上一个检查完成后立即开始下一个检查,一次又一次,中间没有停顿。
这基本上是指示您的计算机将所有可用的处理能力用于检查进程是否存在。这个程序理论上应该使用 100% CPU,但是由于某些原因,在 Windows 下列出任务是缓慢且低效的,而且你可能有一个 CPU 核心,批处理是本身变慢,它只能使用 CPU.
的一小部分您很可能不需要那么频繁地检查进程。这通常在 1 到 10 秒内完成一次。如果这是可以接受的,请在代码中的某处插入延迟,如下所示:
TIMEOUT /T 5 /NOBREAK
其中 5 是等待的秒数。有关详细信息,请参阅 timeout /?
或 this。
AutoIT
在 AutoIt 中,您需要 ProcessExists()
检查进程是否存在,Sleep()
插入延迟。杀死一个进程是通过 ProcessClose()
完成的, Run()
启动一个。该文档可在 here Function Reference
检查 windows 上的进程仍然缓慢且效率低下。 AutoIT 文档建议 the process is polled approximately every 250 milliseconds
这可能意味着如果您尝试更快地请求它,您将获得上次保存的结果,因此插入 Sleep(250)
或更多是有意义的。
然而,这主要适用于按名称查询进程,它请求所有 运行ning 进程的列表并在其中搜索您的进程。如果您知道某个进程已经存在,则无需执行此操作 - 您可以简单地使用其进程 ID 号 (PID) 来检查它是否已停止 - 这应该会更快。所以除了 ProcessExists("notepad.exe")
你还可以这样做:
local $pid = 0
while true
if ($pid <> 0) then $pid = ProcessExists($pid) ;Process already existed, use PID
if ($pid = 0) then $pid = ProcessExists("notepad.exe") ;Process did not exist
if ($pid <> 0) then
;do something if process exists...
endif
sleep(300)
.........
wend
这是有效的,因为 ProcessExists()
returns 如果进程存在则为 PID,否则为 0。
第一 if
行 运行s 如果 $pid
从我们上次检查时就已经知道了。
如果不是,或者如果我们之前从未检查过,或者如果它是但不再存在,则第二行 运行s 并根据进程名称进行检查。这应该在第二个过程中重复。请注意,这不是故意的 if-then-else
,因为第一次检查可能会将 $pid
设置为 0
。
EXE替换
如果上述解决方案不起作用——例如,如果 reaper.exe
碰巧试图访问 googledrivesync.exe
持有的内容,它就会严重崩溃——那么可能应该采取其他措施。
一个选择是将 reaper.exe
重命名为 real_reaper.exe
并将一个自动脚本编译成新的 reaper.exe
以杀死 googledrivesync
并启动 real_reaper.exe
。此脚本需要传递所有参数,例如
RunWait ('"real_reaper.exe" ' & $CmdLineRaw)
应该可以解决问题。这等待 real_reaper.exe
完成 运行ning 然后你可以做 Run("googledrivesync.exe")
如果启动 reaper.exe
的程序使用了一些技巧,这可能无法正常工作,但在大多数情况下应该可以正常工作。