windows 如何启动GUI可执行文件和控制台程序,并在用户关闭的GUI应用程序上终止控制台应用程序?

wxclj1h5  于 2023-06-07  发布在  Windows
关注(0)|答案(2)|浏览(529)

我正在执行一个启动可执行文件proc1.exe的脚本。当proc1.exe运行时,批处理文件必须启动另一个可执行文件proc2.exe
示例:文件A.bat运行proc1.exe,要求如下。
1.当proc1.exe运行时,proc2.exe应该运行。
1.当proc1.exe关闭时,proc2.exe应终止。
我试了这个代码:

tasklist /fi "ImageName eq proc1.exe" /fo csv 2>NUL|find /I "proc1.exe">NUL

if "%ERRORLEVEL%"=="0" 
echo proc1.exe  is running
start /wait proc2.exe

else

taskkill /F /IM proc2.exe

运行脚本时,命令窗口显示错误消息:
tasklist命令的语法不正确。
上面的tasklist命令行有什么问题?
我不确定else部分是否会实现。如何在proc1.exe终止后返回到脚本中的else部分并杀死proc2.exe
如何才能做到这一点?
这里有更多的信息后,张贴第一版的莫菲的答案。
这就是我所尝试的,我认为,我接近解决方案,但需要你的支持。
批处理文件A.bat修改为:

start bin\proc1.exe 2>&1
rem proc1.exe is running. Proc1.exe is a GUI application with buttons and
rem widgets. The cmd window and the GUI application window are opened now.

start /wait proc2.exe 2>&1
rem proc2.exe is running now too. It is a Windows console application.
rem A second console window is opened for that reason.
rem Both proc1.exe and proc2.exe are running as processes.
    
rem Now I want to check whether Proc1.exe is running or not.
rem If it is running do nothing, else terminate proc2.exe.
rem I have written a loop for that purpose. The issue is that
rem the control is not coming to the loop.

rem When I close the GUI application, the ELSE part should
rem be executed and proc2.exe should be terminated/killed.

rem How do I bring the control to loop label or how 
rem to signal proc1.exe is closed and run taskkill?

:loop
tasklist /FI "IMAGENAME eq proc1.exe" 2>NUL | find /I /N "proc1.exe">NUL
if "%ERRORLEVEL%"=="0" (
    timeout /T 1 /NOBREAK >NUL
    goto loop
) else (
    taskkill /F /IM proc2.exe  >NUL
)
ekqde3dh

ekqde3dh1#

任务非常不明确。

  1. proc1.exe是在批处理文件之外启动的,还是也由批处理文件启动的?
  2. proc1.exe是Windows控制台还是Windows GUI应用程序,它是否打开文件进行读/写操作,或使其注册表读/写,或打开与其他进程甚至其他设备的连接?
  3. proc2.exe是Windows控制台还是Windows GUI应用程序,它是否打开文件进行读/写操作,或使其注册表读/写,或打开与其他进程甚至其他设备的连接?
    1.是否可以在proc1.exe之前一秒钟启动proc2.exe,或者proc2.exe是否依赖于已经运行的proc1.exe才能成功启动?
    1.在批处理文件仅启动proc2.exe或同时启动这两个应用程序之前,是否可以运行更多的proc1.exe和/或proc2.exe示例?
    1.在批处理文件观察到在执行批处理文件期间启动的一个或两个进程的同时,用户或任何其他进程是否可能启动更多的proc1.exeproc2.exe示例。
    1.通过使用带有/F /IM proc2.exe选项的TASKKILL,让所有正在运行的proc2进程都没有机会通过关闭连接、完成所有读/写操作、保存未保存的数据和关闭文件优雅地终止,操作系统强制杀死所有**正在运行的proc2.exe示例,真的可以吗?
    让我假设这七个问题的答案如下:
    1.批处理文件始终以proc1.exe开头。
    1.目前还不知道proc1.exe是什么,它有什么作用。
    1.目前还不知道proc2.exe是什么,它做什么。
    1.是的,proc2.exe在尚未运行的proc1.exe上也成功启动。
    1.是的,确实有可能。
    1.是的,这也是可能的。
    1.不,这可不行。proc2.exe应该自行关闭,不应该被操作系统杀死。
    在这种情况下,可以使用以下注解的批处理文件:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define the two programs to run which can be even twice the same program.
set "ProgStart_FullName=%SystemRoot%\Notepad.exe"
set "ProgWait_FullName=%SystemRoot%\Notepad.exe"

rem Get just the file name of the first program with file extension.
for %%I in ("%ProgStart_FullName%") do set "ProgStart_FileName=%%~nxI"

rem Delete all environment variables of which name starts with
rem #PID_ in the local environment of this batch file context.
for /F "delims==" %%I in ('set #PID_ 2^>nul') do "set %%I="

rem Get all process identifiers of all already running processes
rem of the executable which is started next by the the batch file.
for /F "tokens=2" %%I in ('%SystemRoot%\System32\tasklist.exe /FI "IMAGENAME eq %ProgStart_FileName%" /NH') do set "#PID_%%I=1"

rem Start the program which should run as separate process.
start "" "%ProgStart_FullName%"

rem Find out the process identifier of just started program. There are
rem hopefully not started two instances of this program at the same time.
for /F "tokens=2" %%I in ('%SystemRoot%\System32\tasklist.exe /FI "IMAGENAME eq  %ProgStart_FileName%" /NH') do if not defined #PID_%%I set "#PID_OBSERVE=%%I" & goto StartNext
echo ERROR: Failed to start "%ProgStart_FullName%"!& echo(& pause & goto EndBatch

:StartNext
rem Start the next program and wait for its self-termination.
"%ProgWait_FullName%"

rem Check if the first started program is still running and send it in
rem this case the WM_CLOSE message for a graceful self-termination giving
rem the process the chance to close all connections, finish all file and
rem registry accesses with saving all unsaved data and close all files.
%SystemRoot%\System32\tasklist.exe /FI "PID eq %#PID_OBSERVE%" | %SystemRoot%\System32\find.exe /I "%ProgStart_FileName%" >nul || goto EndBatch
%SystemRoot%\System32\taskkill.exe /PID %#PID_OBSERVE% >nul 2>nul

rem Wait five seconds for the self-termination of the first started program.
rem A Windows GUI program should get even more time, especially if a user uses
rem that GUI program and the program asks the user if unsaved data should be
rem saved before exiting. How much time to wait depends on the application.
echo Wait for exit of "%ProgStart_FileName%" with PID %#PID_OBSERVE%" ...
set "LoopCount=5"
:WaitLoop
%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK >nul
%SystemRoot%\System32\tasklist.exe /FI "PID eq %#PID_OBSERVE%" | %SystemRoot%\System32\find.exe /I "%ProgStart_FileName%" >nul || goto EndBatch
set /A LoopCount-=5
if not %LoopCount% == 0 goto WaitLoop

rem Force a brutal kill of the first started program by the operating system.
%SystemRoot%\System32\taskkill.exe /F /PID %#PID_OBSERVE% >nul 2>nul

:EndBatch
endlocal

此批处理文件通过启动 *Windows记事本 * 的两个示例来演示进程管理。用户可以在运行批处理文件之前启动其他 Notepad 示例,也可以启动更多 Notepad 进程,而在处理批处理文件期间由 Windows Command Processor 启动的两个 Notepad 示例仍在运行,并等待用户操作。用户可以关闭第一个批量启动的示例,然后关闭第二个批量启动的 Notepad 示例,但也可以相反。如果用户在第一个批量启动示例的新文件中输入文本,但未保存该文本,并首先关闭第二个批量启动示例,则 * 记事本 * 的第一个批量启动示例会提示用户是否应立即保存未保存的文本。用户有5秒钟的时间来选择,否则批处理文件将运行TASKKILL,并带有选项/F,以强制终止第一批启动的 * 记事本 *,从而导致输入文本丢失。
批处理文件不能用于文件名中有空格的可执行文件。
如果ProgStart_FullName%CompSpec%%SystemRoot%\System32\cmd.exe,则无法使用此处发布的批处理文件。
环境变量ProgStart_FullName必须使用完全限定文件名proc2.exe定义,而环境变量ProgWait_FullName必须使用完全限定文件名proc1.exe定义。因此,proc2.exe首先作为单独的并行运行进程启动,然后启动proc1.execmd.execmd.exe上暂停批处理文件执行,直到proc1.exe自行退出。然后,如果proc2.exe仍在运行,则批处理文件也会终止,或者如果proc2.exe出于任何原因没有在5秒内关闭自己,则最终将其杀死。
在问题中添加了额外的信息,任务变得更加清晰。
现就这七个问题答复如下:
1.批处理文件始终以proc1.exe开头。
1.应用程序proc1.exe是Windows GUI应用程序。
1.应用程序proc2.exe是Windows控制台应用程序。

  1. proc2.exe必须在proc1.exe之后启动。
    1.在执行批处理文件之前,既没有启动proc1.exe,也没有启动proc2.exe
    1.有运行从来没有超过一个proc1.exe一个proc2.exe
  2. proc2.exe应该自行关闭,不应该被操作系统杀死。
    在批处理文件目录的子目录bin中包含proc1.exeproc2.exe的此任务的注解批处理文件可以是:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FullNameProcess1=%~dp0bin\proc1.exe"
set "FullNameProcess2=%~dp0bin\proc2.exe"

rem Get just the file name of the two programs with file extension.
for %%I in ("%FullNameProcess1%") do set "FileNameProcess1=%%~nxI"
for %%I in ("%FullNameProcess2%") do set "FileNameProcess2=%%~nxI"

rem Start the GUI program which should run as separate process in foreground.
start "" "%FullNameProcess1%" 2>nul
rem Could the first program not be started at all?
if errorlevel 9059 echo ERROR: Failed to start "%FullNameProcess1%"!& echo(& pause & goto EndBatch

rem Start the console program which should run as separate process
rem without opening a console window.
start "" /B "%FullNameProcess2%"

rem Define an endless running loop searching once per second in the
rem task list if the first started GUI application is still running.
:WaitLoop
%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK >nul
%SystemRoot%\System32\tasklist.exe /FI "IMAGENAME eq %FileNameProcess1%" /NH | %SystemRoot%\System32\find.exe "%FileNameProcess1%" >nul && goto WaitLoop

rem The first started GUI program is not running anymore. Check now if the
rem console program is still running and if that is the case, send it the
rem message to close itself.
%SystemRoot%\System32\tasklist.exe /FI "IMAGENAME eq %FileNameProcess2%" /NH | %SystemRoot%\System32\find.exe "%FileNameProcess2%" >nul || goto EndBatch
%SystemRoot%\System32\taskkill.exe /IM "%FileNameProcess2%" >nul 2>nul

rem Wait one second and check if the console program really terminated itself.
rem Otherwise force a brutal kill of the console program by the operating system.
%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK >nul
%SystemRoot%\System32\tasklist.exe /FI "IMAGENAME eq %FileNameProcess2%" /NH | %SystemRoot%\System32\find.exe "%FileNameProcess2%" >nul && %SystemRoot%\System32\taskkill.exe /F /IM "%FileNameProcess2%" >nul 2>nul

:EndBatch
endlocal

批处理文件不能用于文件名中有空格的可执行文件。
如果proc2.exe是真实的cmd.exe,则无法使用批处理文件,因为taskkill.exe /IM "cmd.exe"会导致所有正在运行的cmd进程(包括处理批处理文件的进程)终止。
要了解所使用的命令及其工作方式,请打开command prompt窗口,在那里执行以下命令,并仔细阅读显示的每个命令的帮助页面。

  • echo /?
  • endlocal /?
  • find /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?
  • start /?
  • taskkill /?
  • tasklist /?
  • timeout /?

阅读有关Using command redirection operators的Microsoft文档,了解>nul2>nul|的说明。在执行命令FOR之前,Windows命令解释器处理FOR命令行时,必须使用插入符号^对重定向运算符>|进行转义,以将其解释为原义字符它使用在后台用%ComSpec% /c启动的单独命令进程和在'内用的命令行来执行嵌入式命令行^作为附加参数追加。
有关无条件命令运算符&和条件命令运算符||的解释以及带有ELSE分支的IF条件的正确语法,请参见single line with multiple commands using Windows batch file"%ERRORLEVEL%"=="0"的用法既没有在命令IF的用法帮助中描述,也不是在批处理文件中使用此string comparison进行退出代码计算的好主意。

wqsoz72f

wqsoz72f2#

This is I want I tried and I am near to the solution but need your support.

A.bat file
start bin\proc1.exe 2>&1
::proc1.exe gets running. Proc1.exe is a gui application with buttons and widgets. cmd window and gui application gets opened.
start /wait proc2.exe 2>&1
    ::proc2.exe gets running it is a windows console, a cmd windows gets 
    opened. Both proc1.exe and proc2.exe are running as process
    
    Now I want to check whether Proc1.exe is running or not if it is running do nothing, else kill proc2.exe
    for that I have written a loop, the issue is control
 is not coming to loop.
    
    when I close the gui application, else part to be executed and proc2. exe should be terminated/killed.
 How do I bring the control to loop lable or how 
    to signal , proc1.exe is closed , u run loop.

:loop
tasklist /FI "IMAGENAME eq proc1.exe" 2>NUL | find /I /N "proc1.exe">NUL
if "%ERRORLEVEL%"=="0" (
    timeout /T 1 /NOBREAK >NUL
    goto loop
) else (
    taskkill /F /IM proc2.exe  >NUL
)

相关问题