Why do not all started applications save the wante

2020-03-30 07:17发布

问题:

I am trying to create a batch file on a USB drive that will run an .exe, save its text to a .txt file, and then close the .exe.

I am currently running into a weird problem, only 5 of the 18 .exe's are actually saving their text to a file.

This is the convention I am using to complete my task:

start IEPassView.exe /stext Results/IEPassView.txt 
taskkill /f /im IEPassView.exe

start MailPassView.exe /stext Results/MailPassView.txt
taskkill /f /im MailPassView.exe

start MessenPass.exe /stext Results/MessenPass.txt
taskkill /f /im MessenPass.exe

start RouterPassView.exe /stext Results/RouterPassView.txt
taskkill /f /im RouterPassView.exe

start ProtectedStoragePassView.exe /stext Results/ProtectedStoragePassView.txt
taskkill /f /im ProtectedStoragePassView.exe

start DialUpPassView.exe /stext Results/DialUpPassView.txt
taskkill /f /im DialUpPassView.exe

I have 18 of the above blocks in a row all calling different small programs and even though 5 of them actually save the files none of them save a .cfg file as they sometimes do. Any help would be greatly appreciated, thanks.

回答1:

There are mainly 3 different types of executables:

  • A console application is reading from stdin or a file and writing to stdout or a file and outputs error messages to stderr.

    The processing of a batch file is halted on starting a console application until the console application terminated itself. The correct term is therefore: calling a console application.

    The exit code of the console application is assigned to environment variable ERRORLEVEL and can be also directly evaluated for example with if errorlevel X rem do something

    Many *.exe in System32 directory of Windows are such console applications, like find.exe, findstr.exe, ping.exe, ...

  • A GUI (graphical user interface) application is started as new process which means the Windows command processor does not halt batch processing until the GUI application terminates itself.

    It is not easily possible to get something from within a command process from such applications. GUI applications are designed for interacting via a graphical user interface with a user and not via standard streams or files with a command process.

    A typical example for such applications is Windows Explorer explorer.exe in Windows directory.

  • A hybrid application supports both interfaces and can be therefore used from within a command process as well as by a user via GUI.

    Hybrid applications are rare because not easy to code. The behavior of hybrid applications on usage from within a batch file must be find out by testing.

    Example for such applications are Windows Registry Editor regedit.exe or shareware archiver tool WinRAR WinRAR.exe.

It is best to look on simple examples to see the differences regarding starting/calling all 3 types of applications from within a batch file.

Example for console application:

@echo off
cls
%SystemRoot%\System32\ping.exe 127.0.0.1 -n 5
echo.
echo Ping finished pinging the own computer (localhost).
echo.
pause

The command processing is halted until ping.exe terminated itself which takes 4 seconds. There is no need for start or call for such applications, except the console application should be intentionally executed in a separate process.

Example for a GUI application:

@echo off
cls
%WinDir%\Explorer.exe
echo.
echo Windows Explorer opened and is still running!
echo.
pause

This batch file outputs the text and message prompt to press any key immediately after starting Windows Explorer indicating that Windows Explorer was started as separate process and Windows command processor immediately continued on the next lines of the batch file. So although Windows Explorer was started and is still running, the batch processing continued, too.

Example for a hybrid application:

@echo off
cls
"%ProgramFiles%\WinRAR\WinRAR.exe"
echo.
echo User exited WinRAR.
echo.
pause

This batch file starts WinRAR without any parameter (usually not useful from within a batch file) if being installed at all in default installation directory. But batch processing is halted until the user exited WinRAR for example by clicking on X symbol of the WinRAR´s application window.

But opening a command prompt window and executing from within the window

"%ProgramFiles%\WinRAR\WinRAR.exe"

results in getting immediately the prompt back in command window to type and execute the next command. So WinRAR finds out what is the parent process and acts accordingly.

Windows Registry Editor shows the same behavior. Executing from within a command prompt window

%WinDir%\regedit.exe

results in opening Windows Registry Editor, but next command can be immediately entered in command prompt window. But using this command in a batch file results in halting batch processing until GUI window of Windows Registry Editor is closed by the user.

Therefore hybrid applications are used from within a batch file mainly with parameters to avoid the necessity of user interaction.


Okay, back to the question after this brief lesson about various types of applications.

First suggestion is using

Result\TextFileName.txt

instead of

Result/TextFileName.txt

as the directory separator on Windows is the backslash character, except the executables require forward slashes as directory separator because of being badly ported from Unix/Linux to Windows.

Second suggestion is finding out type of application. Is command start really necessary because the applications don't start itself in a separate process and need user interaction to terminate itself?

Note: Command start interprets first double quoted string as title string. Therefore it is always good to specify as first parameter "" (empty title string) on starting a GUI or hybrid application as a separate process. On starting a console application as a separate process it is in general a good idea to give the console window a meaningful title.

And last if the started applications really would need user interaction to terminate, it would be definitely better to either start and kill them after waiting 1 or more seconds between start and kill or start them all, wait a few seconds and finally kill them all at once.

Example for first solution with starting and killing each application separately:

@echo off
setlocal
set TimeoutInSeconds=3
call :RunApp IEPassView
call :RunApp MailPassView
call :RunApp MessenPass
call :RunApp RouterPassView
call :RunApp ProtectedStoragePassView
call :RunApp DialUpPassView
endlocal
goto :EOF

:RunApp
start "" "%~1.exe" /stext "Results\%~1.txt"
set /A RetryNumber=TimeoutInSeconds + 1
%SystemRoot%\System32\ping.exe 127.0.0.1 -n %RetryNumber% >nul
%SystemRoot%\System32\taskkill.exe /f /im "%~1.exe"
goto :EOF

It is also possible to use timeout instead of ping for the delay if the batch file is only for Windows Vista and later Windows versions.

Example for second solution with starting all applications, wait some seconds and kill them finally all:

@echo off
call :StartApp IEPassView
call :StartApp MailPassView
call :StartApp MessenPass
call :StartApp RouterPassView
call :StartApp ProtectedStoragePassView
call :StartApp DialUpPassView

%SystemRoot%\System32\ping.exe 127.0.0.1 -n 6 >nul

call :KillApp IEPassView
call :KillApp MailPassView
call :KillApp MessenPass
call :KillApp RouterPassView
call :KillApp ProtectedStoragePassView
call :KillApp DialUpPassView

goto :EOF

:StartApp
start "" "%~1.exe" /stext "Results\%~1.txt"
goto :EOF

:KillApp
%SystemRoot%\System32\taskkill.exe /f /im "%~1.exe"
goto :EOF

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /?
  • echo /?
  • endlocal /?
  • goto /?
  • ping /?
  • set /?
  • setlocal /?
  • start /?
  • taskkill /?

See also the Microsoft article about Using command redirection operators.

PS: The last two batch code blocks were not tested by me because of not having available the applications.



回答2:

I suggest killing all tasks at once, at the end of the very end, possibly after a timeout command with a amount of time appropriate to your system's speed. That may help the issue.