英文:
How to start a GUI executable and a console program and terminate the console application on GUI application closed by the user?
问题
以下是代码部分的翻译:
我正在执行一个启动可执行文件 `proc1.exe` 的脚本。当 `proc1.exe` 正在运行时,批处理文件必须启动另一个可执行文件 `proc2.exe`。
示例:文件 `A.bat` 运行 `proc1.exe`,具有以下要求。
1. 当 `proc1.exe` 正在运行时,应运行 `proc2.exe`。
2. 当 `proc1.exe` 关闭时,应终止 `proc2.exe`。
我尝试了这段代码:
```plaintext
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
部分是否会执行。如何在脚本中返回到 else
部分并在终止 proc1.exe
后终止 proc2.exe
?
如何实现这一点?
以下是关于 Mofi 第一个回答发布后的更多信息。
这是我尝试过的内容,我认为我接近解决方案,但需要您的支持。
批处理文件 A.bat
修改为:
start bin\proc1.exe 2>&1
rem proc1.exe 正在运行。Proc1.exe 是一个带有按钮和小部件的 GUI 应用程序。
rem 现在打开了 cmd 窗口和 GUI 应用程序窗口。
start /wait proc2.exe 2>&1
rem 现在也运行了 proc2.exe。它是一个 Windows 控制台应用程序。
rem 为此会打开第二个控制台窗口。
rem 现在 proc1.exe 和 proc2.exe 都作为进程运行。
rem 现在我想要检查 Proc1.exe 是否正在运行。
rem 如果正在运行,则不执行任何操作,否则终止 proc2.exe。
rem 我为此编写了一个循环。问题是控制没有传递到循环。
rem 当我关闭 GUI 应用程序时,应执行 ELSE 部分,并终止/杀死 proc2.exe。
rem 如何将控制传递到循环标签,或者如何
rem 信号 proc1.exe 已关闭并运行 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
)
英文:
I am executing a script which starts an executable proc1.exe
. When proc1.exe
is running, the batch file has to start another executable proc2.exe
.
Example: File A.bat
runs proc1.exe
with following requirements.
- When
proc1.exe
is running,proc2.exe
should run. - When
proc1.exe
is closed,proc2.exe
should be terminated.
I tried this code:
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
When I run the script, the command window displays the error message:
> The syntax of tasklist command is incorrect.
What is the issue with the above tasklist
command line?
I am not sure whether the else
part would be achieved. How do I come back to else
part in the script and kill proc2.exe
after proc1.exe
is terminated.
How could this be achieved?
Here are more information after post of first version of Mofi´s answer.
This is what I have tried and I think, I am near to the solution but need your support.
Batch file A.bat
is modified to:
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
)
答案1
得分: -1
以下是翻译好的部分:
-
The task is very unclear.
任务非常不清晰。 -
Is
proc1.exe
started outside of the batch file or also by the batch file?
proc1.exe
是在批处理文件外部启动的,还是由批处理文件启动的? -
Is
proc1.exe
a Windows console or a Windows GUI application and does it open files for read/write operations or makes it registry reads/writes or does it open connections to other processes or even other devices?
proc1.exe
是Windows控制台还是Windows GUI应用程序,它是否打开文件进行读/写操作,或者进行注册表读取/写入,或者打开与其他进程甚至其他设备的连接? -
Is
proc2.exe
a Windows console or a Windows GUI application and does it open files for read/write operations or makes it registry reads/writes or does it open connections to other processes or even other devices?
proc2.exe
是Windows控制台还是Windows GUI应用程序,它是否打开文件进行读/写操作,或者进行注册表读取/写入,或者打开与其他进程甚至其他设备的连接? -
Is it possible to start
proc2.exe
a second beforeproc1.exe
or doesproc2.exe
depend on an already runningproc1.exe
for a successful start?
是否可以在启动proc1.exe
之前一秒启动proc2.exe
,或者proc2.exe
是否依赖于已经运行的proc1.exe
才能成功启动? -
Can be more instances of
proc1.exe
and/orproc2.exe
already running before the batch file starts justproc2.exe
or both applications?
批处理文件启动之前是否可能已经运行了更多的proc1.exe
和/或proc2.exe
实例,只启动proc2.exe
还是两个应用都启动? -
Is it possible that even more instances of
proc1.exe
orproc2.exe
are started by a user or any other process while the batch file observes the one or two processes started during execution of the batch file.
是否可能在批处理文件观察批处理文件执行过程中启动的一个或两个进程时,用户或其他进程启动更多的proc1.exe
或proc2.exe
实例? -
Is it really okay forcing a brutal kill of all running instances of
proc2.exe
by the operating system by using TASKKILL with the options/F /IM proc2.exe
giving none of the runningproc2
processes the chance to gracefully terminate with closing connections, finishing all read/write operations, saving unsaved data and closing files?
使用操作系统使用TASKKILL
的/F /IM proc2.exe
选项强制终止所有正在运行的proc2.exe
实例是否真的可以,而不给任何正在运行的proc2
进程以优雅地关闭连接、完成所有读/写操作、保存未保存的数据并关闭文件的机会?
请注意,这是您提供的文本的翻译,没有额外的内容或回答问题。
英文:
The task is very unclear.
- Is
proc1.exe
started outside of the batch file or also by the batch file? - Is
proc1.exe
a Windows console or a Windows GUI application and does it open files for read/write operations or makes it registry reads/writes or does it open connections to other processes or even other devices? - Is
proc2.exe
a Windows console or a Windows GUI application and does it open files for read/write operations or makes it registry reads/writes or does it open connections to other processes or even other devices? - Is it possible to start
proc2.exe
a second beforeproc1.exe
or doesproc2.exe
depend on an already runningproc1.exe
for a successful start? - Can be more instances of
proc1.exe
and/orproc2.exe
already running before the batch file starts justproc2.exe
or both applications? - Is it possible that even more instances of
proc1.exe
orproc2.exe
are started by a user or any other process while the batch file observes the one or two processes started during execution of the batch file. - Is it really okay forcing a brutal kill of all running instances of
proc2.exe
by the operating system by using TASKKILL with the options/F /IM proc2.exe
giving none of the runningproc2
processes the chance to gracefully terminate with closing connections, finishing all read/write operations, saving unsaved data and closing files?
Let me assume the answers on these seven questions are as follows:
- The batch file always starts
proc1.exe
. - It is unknown what
proc1.exe
is and what it does. - It is unknown what
proc2.exe
is and what it does. - Yes,
proc2.exe
starts also successful onproc1.exe
not already running. - Yes, that is indeed possible.
- Yes, that is possible, too.
- No, that is not okay.
proc2.exe
should close itself and should not be killed by the OS.
In this case can be used the following commented batch file:
@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
This batch file demonstrates the process management by starting two instances of Windows Notepad. A user can start other Notepad instances before running the batch file and can also start even more Notepad processes while the two instances of Notepad started by the Windows Command Processor during processing of the batch file are still running and wait for user actions. The user can close the first batch started instance and later the second batch started instance of Notepad, but the opposite is also possible. If the user entered text into new file of first batch started instance without saving that text and closes first the second batch started instance, the first batch started instance of Notepad prompts the user if the unsaved text should be saved now. The user has five seconds time for the choice as otherwise the batch file runs TASKKILL with option /F
to force a kill of the first batch started Notepad resulting in a loss of the input text.
The batch file as is cannot be used for executables with a space in file name.
The batch file cannot be used as posted here if ProgStart_FullName
is %CompSpec%
or %SystemRoot%\System32\cmd.exe
.
The environment variable ProgStart_FullName
must be defined with the fully qualified file name of proc2.exe
while the environment variable ProgWait_FullName
must be defined with the fully qualified file name of proc1.exe
. So, proc2.exe
is started first as separate, parallel running process and next is started proc1.exe
on which cmd.exe
halts the batch file execution until proc1.exe
exits itself. Then the batch file terminates also proc2.exe
on still running or finally kills it if proc2.exe
does not close itself within five seconds for whatever reason.
The task became more clear with the additional information added to the question.
The seven questions are answered as follows:
- The batch file always starts
proc1.exe
. - The application
proc1.exe
is a Windows GUI application. - The application
proc2.exe
is a Windows console application. proc2.exe
must be started afterproc1.exe
.- There is neither
proc1.exe
norproc2.exe
started before batch file execution. - There are running never more than one
proc1.exe
oneproc2.exe
. proc2.exe
should close itself and should not be killed by the OS.
The commented batch file for this task with proc1.exe
and proc2.exe
in subdirectory bin
of the batch file directory could be:
@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
The batch file as is cannot be used for executables with a space in file name.
The batch file cannot be used if proc2.exe
is in real cmd.exe
because of taskkill.exe /IM "cmd.exe"
results in termination of all running cmd
processes including the one processing the batch file.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
echo /?
endlocal /?
find /?
for /?
goto /?
if /?
pause /?
rem /?
set /?
setlocal /?
start /?
taskkill /?
tasklist /?
timeout /?
Read the Microsoft documentation about Using command redirection operators for an explanation of >nul
and 2>nul
and |
. The redirection operators >
and |
must be escaped with caret character ^
on the FOR command lines to be interpreted as literal characters when Windows command interpreter processes these command lines before executing command FOR which executes the embedded command line with using a separate command process started in background with %ComSpec% /c
and the command line within '
with ^
appended as additional arguments.
See also single line with multiple commands using Windows batch file for an explanation of unconditional command operator &
and conditional command operator ||
and correct syntax for an IF condition with an ELSE branch. The usage of "%ERRORLEVEL%"=="0"
is neither described by the usage help of command IF nor is it ever a good idea to use this string comparison for exit code evaluation in a batch file.
答案2
得分: -1
这是我想要的,我已经尝试过了,我接近解决方案,但需要您的支持。
A.bat 文件
start bin\proc1.exe 2>&1
:: proc1.exe 开始运行。Proc1.exe 是一个带有按钮和小部件的 GUI 应用程序。命令行窗口和 GUI 应用程序会打开。
start /wait proc2.exe 2>&1
:: proc2.exe 开始运行,它是一个 Windows 控制台,一个命令行窗口会打开。proc1.exe 和 proc2.exe 都作为进程在运行。
现在,我想要检查 Proc1.exe 是否正在运行,如果正在运行就不做任何操作,否则终止 proc2.exe。为此,我编写了一个循环,问题是控制没有进入循环。
当我关闭 GUI 应用程序时,应执行 else 部分,并终止/杀死 proc2.exe。我该如何将控制传递到循环标签或如何通知 proc1.exe 已关闭,然后运行循环。
: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
)
英文:
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
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论