How to start a GUI executable and a console program and terminate the console application on GUI application closed by the user?

huangapple go评论57阅读模式
英文:

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.

  1. When proc1.exe is running, proc2.exe should run.
  2. 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

以下是翻译好的部分:

  1. The task is very unclear.
    任务非常不清晰。

  2. Is proc1.exe started outside of the batch file or also by the batch file?
    proc1.exe是在批处理文件外部启动的,还是由批处理文件启动的?

  3. 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应用程序,它是否打开文件进行读/写操作,或者进行注册表读取/写入,或者打开与其他进程甚至其他设备的连接?

  4. 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应用程序,它是否打开文件进行读/写操作,或者进行注册表读取/写入,或者打开与其他进程甚至其他设备的连接?

  5. Is it possible to start proc2.exe a second before proc1.exe or does proc2.exe depend on an already running proc1.exe for a successful start?
    是否可以在启动proc1.exe之前一秒启动proc2.exe,或者proc2.exe是否依赖于已经运行的proc1.exe才能成功启动?

  6. Can be more instances of proc1.exe and/or proc2.exe already running before the batch file starts just proc2.exe or both applications?
    批处理文件启动之前是否可能已经运行了更多的proc1.exe和/或proc2.exe实例,只启动proc2.exe还是两个应用都启动?

  7. Is it possible that even more instances of proc1.exe or proc2.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.exeproc2.exe实例?

  8. 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 running proc2 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.

  1. Is proc1.exe started outside of the batch file or also by the batch file?
  2. 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?
  3. 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?
  4. Is it possible to start proc2.exe a second before proc1.exe or does proc2.exe depend on an already running proc1.exe for a successful start?
  5. Can be more instances of proc1.exe and/or proc2.exe already running before the batch file starts just proc2.exe or both applications?
  6. Is it possible that even more instances of proc1.exe or proc2.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.
  7. 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 running proc2 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:

  1. The batch file always starts proc1.exe.
  2. It is unknown what proc1.exe is and what it does.
  3. It is unknown what proc2.exe is and what it does.
  4. Yes, proc2.exe starts also successful on proc1.exe not already running.
  5. Yes, that is indeed possible.
  6. Yes, that is possible, too.
  7. 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:

  1. The batch file always starts proc1.exe.
  2. The application proc1.exe is a Windows GUI application.
  3. The application proc2.exe is a Windows console application.
  4. proc2.exe must be started after proc1.exe.
  5. There is neither proc1.exe nor proc2.exe started before batch file execution.
  6. There are running never more than one proc1.exe one proc2.exe.
  7. 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
)

huangapple
  • 本文由 发表于 2023年6月1日 20:29:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76381875.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定