批处理文件在继续之前等待另一个进程完成

时间:2016-03-26 22:32:41

标签: windows batch-file taskkill

我每次启动工作PC时都会使用批处理文件。基本上,它会杀死IT部门在PC上运行的所有英国媒体软件,这些文件作为我的用户帐户运行,我从未使用taskkill,安装一个小程序,然后一次加载我实际需要的所有程序。问题是,我运行的程序之一,IT部门最近认为安装"帮助程序"程序自动化我已经知道如何做的程序内的一些东西,并可以手动相当快速地完成。问题是,辅助程序实际上具有相反的效果并且减慢了实际程序的速度。我们当然向IT抱怨它,但它可能需要花费几个月的时间来修复它,如果有的话。与此同时,我发现帮助程序在我的用户帐户下运行它自己的进程,这意味着我可以杀死它,一切运行顺利。问题是程序是如何运行的。我正常启动程序,这种情况发生了:

处理A加载。流程A加载流程B.流程A自行终止。流程B加载流程C.流程C加载流程D,E和F(辅助程序)。进程B自杀,同时将C,D,E和F留在内存中(此时程序已满载)

在继续执行taskkill命令以终止进程D,E和F之前,如何让批处理文件等待进程B自行终止?由于命令行在直接调用EXE时只看到进程A,因此它会在一秒钟内恢复批处理文件,因为A会快速自杀。我不能仅使用timeout或其他一些通用时间浪费,因为程序的加载时间太不稳定,网络问题,程序更新等等。

4 个答案:

答案 0 :(得分:0)

几年前我构建了类似于此的内容,但遗憾的是,我没有代码,也无法访问Windows机器。

然而,它应该相当简单,并且将沿着这些方向(只是调整代码以使其工作或让我知道是否有任何问题;我无法测试它但应该能够修复他们,如果我知道他们是什么):

rem Usage: :killprocesswithwait [pid]
call :killprocesswithwait 1234

:killprocesswithwait
set pid=%1
taskkill /pid %pid%
:iloop
ping 127.0.0.1 -n 2 > nul
for /f "tokens=*" %%a in ('tasklist /fi "PID eq %pid%" ^| find /i %pid%') do (
    if /i "%%a"=="" (
        goto :eof
    ) else (
        goto :iloop
    )
)

答案 1 :(得分:0)

等待任何和所有程序退出并检查是否记事本,如果是,则重新启动它。

等待三个程序开始肯定会更好。将Win32_ProcessStopTrace更改为Win32_ProcessStartTrace

Set WshShell = WScript.CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2") 
Set objEvents = objWMIService.ExecNotificationQuery _
    ("SELECT * FROM Win32_ProcessStopTrace")

Do
    Set objReceivedEvent = objEvents.NextEvent
    msgbox objReceivedEvent.ProcessName
    If lcase(objReceivedEvent.ProcessName) = lcase("Notepad.exe") then 
        Msgbox "Process exited with exit code " & objReceivedEvent.ExitStatus
        WshShell.Run "c:\Windows\notepad.exe", 1, false
    End If
Loop

这会列出进程并终止任何被调用的计算器。

Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")

Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")

For Each objItem in colItems
    'msgbox objItem.ProcessID & " " & objItem.CommandLine
    If objItem.name = "Calculator.exe" then objItem.terminate
Next

答案 2 :(得分:0)

@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q36241667.txt"
SET "filename2=%sourcedir%\q36241667_2.txt"

:dloop
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
 tasklist|FIND "%%a" >NUL
 IF ERRORLEVEL 1 timeout /t 1 >nul&GOTO dloop
)

FOR /f "usebackqdelims=" %%a IN ("%filename2%") DO ECHO(%%a

GOTO :EOF

您需要更改sourcedir的设置以适合您的具体情况。

我使用了名为q36241667.txt&的文件q36241667_2.txt包含一些虚拟数据供我测试。

假设filename1包含

processa.exe
processb.exe
processc.exe
processd.exe
processe.exe

然后for循环将等到所有进程都在运行之后再继续。

filename2包含所需的kill命令(echo用于演示目的)

如果此例程在启动例程中只是start,那么它本身可以触发start命令来终止任何不需要的进程。

我使用类似的例程在启动时将关键目录备份到ramstick。

答案 3 :(得分:0)

谢谢大家,我实际上接受了Ruslan的回答并进行了简化并稍微改了一下。这非常有效。等待exe3加载,因为它是最后一个加载,然后杀死所有3.不需要设置变量以便删除那些并完全忘记将它放入循环中。

:start
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq exe3.exe"') DO IF %%x == exe3.exe goto found
goto start
:found
taskkill /f /fi "blah1.exe"
taskkill /f /fi "blah2.exe"
taskkill /f /fi "blah3.exe"