Is there a way to hide the command prompt window while running from application as I have a loop which contains a run command calls a batch file which causes unpleasant flickering.(the case is not limited to batch files but to any command that opens the command prompt window.
One way to run is calling CreateProcess() and set siStartInfo.wShowWindow = SW_HIDE.
If you want to wait on it to finish, like RUN(File,Wait), you’ll need to monitor the Process Handle piProcInfo.hProcess. The easy way is to monitor GetExitCodeProcess() for STILL_ACTIVE (259) in a timer.
I think it would be easier to call ShellExecuteEx(InfoGroup). The passed Info has a .nShow that can be set to SW_Hide. It can return a Process Handle to monitor for it closing with SEE_MASK_NOCLOSEPROCESS.
There is a CreateProcess() example on GitHub in Devuna KSS where it runs DOS command FindStr. Here’s some of that code…
piProcInfo LIKE(PROCESS_INFORMATION)
!szCmdline CSTRING('findstr /s /i /n /p "keystone" "*.inc *.clw"')
siStartInfo LIKE(STARTUPINFOTYPE)
! Create a child process that uses the previously created pipes for STDIN and STDOUT.
! Set up members of the PROCESS_INFORMATION structure.
kcr_ZeroMemory(ADDRESS(piProcInfo), SIZE(PROCESS_INFORMATION))
! Set up members of the STARTUPINFO structure.
! This structure specifies the STDIN and STDOUT handles for redirection.
kcr_ZeroMemory(ADDRESS(siStartInfo), SIZE(STARTUPINFOTYPE))
siStartInfo.cb = SIZE(STARTUPINFOTYPE);
siStartInfo.hStdError = g_hChildStd_OUT_Wr
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr
siStartInfo.hStdInput = g_hChildStd_IN_Rd
siStartInfo.dwFlags = BOR(siStartInfo.dwFlags,STARTF_USESTDHANDLES)
siStartInfo.dwFlags = BOR(siStartInfo.dwFlags,STARTF_USESHOWWINDOW)
siStartInfo.wShowWindow = SW_HIDE !<=== Hide the Window ****
! Create the child process.
bSuccess = kcr_CreateProcess(0, | ! application name
szCmdline, | ! command line
0, | ! process security attributes
0, | ! primary thread security attributes
TRUE, | ! handles are inherited
0, | ! creation flags
0, | ! use parent's environment
0, | ! use parent's current directory
siStartInfo, | ! STARTUPINFO pointer
piProcInfo) ! receives PROCESS_INFORMATION
! If an error occurs, exit the application.
IF bSuccess = TRUE
! Close handles to the child process and its primary thread.
! Some applications might keep these handles to monitor the status
! of the child process, for example.
!kcr_CloseHandle(piProcInfo.hProcess)
kcr_CloseHandle(piProcInfo.hThread)
ELSE
!MESSAGE('CreateProcess')
END
A simple idea is to make the DOS Window less visible. less obvious. or more like an App Window
Screen size small e.g. 60x10 … it can be smaller like 40x3
Colored White/Gray or like App. There are new ANSI colors in Win 10. Yu canot make both colors the same.
Prompt just space ($S) not X:>
Title not “Command Prompt” e.g. “Copying…”
MODE CON COLS=60 LINES=10
COLOR 87
PROMPT $S
TITLE Copying...
You could run the Batch file Minimized making it less visible. The way I know how to do that is with START /min My.BAT. That’s not going to work with RUN(,wait). There may be other ways for a BAT to hide or minimize.
That was my approach before but in my application every command has an update on the screen which I am stating the loop from, so I need an update for each command instantly. Before when I used to create a batch file and run it, I had to add an additional line after the command to send the result after each execution to an “ini” file from the batch file and read the results from clarion with a timer or such, but still there was a delay sometimes and I felt it was a poor workaround.
Regarding the code I will post soon because I am still testing it to make sure that it is not skipping any data because I am testing around 300,000 command and each command takes 2 to 3 seconds to complete. I faced some issues and fixed them but it seems so far so good.
Actually I have an application that applies a sort of converting files from type to another using a third party line command application. The application used to be very noisy while running but now after the command window is not showing ;you don’t feel that there is a third party application in running in the background.
When the last parameter inRunAs=True, admin rights will be requested.
jhTools.Run PROCEDURE(STRING inFilename,<STRING inParams>,<STRING inStartPath>,<BYTE inWait>,<BYTE inHide>,<BYTE inRunAs>)
procName EQUATE('jhTools.Run')
ShellExecInfo GROUP
cbSize ULONG
fMask ULONG
hwnd ULONG
lpVerb LONG
lpFile LONG
lpParameters LONG
lpDirectory LONG
nShow LONG
hInstApp ULONG
lpIDList ULONG
lpClass LONG
hkeyClass ULONG
dwHotKey ULONG
lpUnion LONG
hProcess ULONG
END
szOperation CSTRING(12)
szFilename CSTRING(256)
szParams CSTRING(256)
szPath CSTRING(256)
dwResult LONG
hWND LONG
dwProcessID LONG
CODE
!-- Check the Filename
IF ~inFilename
RETURN(FALSE)
.
IF inRunAs
szOperation = 'runas'
ELSE
szOperation = 'open'
.
szFilename = CLIP(inFilename)
!-- Wrap a file name containing a space with double quotes if necessary ..
!--
IF INSTRING(' ',szFilename,1,1) AND szFilename[1] ~= '"'
szFilename = '"' & szFilename & '"'
.
!-- StartIn Path ..
IF inStartPath
szPath = CLIP(inStartPath)
ELSE
szPath = ''
.
szParams = CLIP(inParams)
CLEAR(ShellExecInfo)
ShellExecInfo.cbSize = SIZE(ShellExecInfo)
ShellExecInfo.fMask = 040H ! SEE_MASK_NOCLOSEPROCESS (0x00000040)
ShellExecInfo.hwnd = 0
ShellExecInfo.lpVerb = ADDRESS(szOperation)
ShellExecInfo.lpFile = ADDRESS(szFilename)
ShellExecInfo.lpParameters = ADDRESS(szParams)
ShellExecInfo.lpDirectory = ADDRESS(szPath)
IF inHide
ShellExecInfo.nShow = 0
ELSE
ShellExecInfo.nShow = 10
.
!-- ShellExecuteExA ..
!-- Returns TRUE if successful; otherwise, FALSE. Call GetLastError for extended error information.
!-- If the function fails, it returns an error value that indicates the cause of the failure.
!-- The return value is cast as an HINSTANCE for backward compatibility with 16-bit Windows applications.
!-- It is not a true HINSTANCE, however. It can be cast only to an int and compared to either 32 or it's error codes.
IF ShellExecuteExA(ADDRESS(ShellExecInfo)) = True
!MESSAGE('ShellExecute SEInfo.hProcess = ' & SEInfo.hProcess & |
! '|inWait = ' & inWait,procName)
IF ShellExecInfo.hProcess
!-- Do we need to wait for this process to finish ?
IF inWait = TRUE
dwResult = WaitForSingleObject(ShellExecInfo.hProcess, -1)
.
!-- Close the Process Handle once finished
CloseHandle(ShellExecInfo.hProcess)
RETURN(TRUE)
.
.
RETURN(False)
I use these prototypes …
ShellExecuteExA(LONG lpShellExecuteInfoA),LONG,PASCAL,NAME('ShellExecuteExA')
WaitForSingleObject(LONG hHandle,ULONG dwMilliseconds),LONG,PASCAL,NAME('WaitForSingleObject')
CloseHandle( Long hObject ),Long,Pascal,Proc,Name('CloseHandle')
Yes your calculation is correct but in my case some commands take less than a second and from my logs each 100,000 takes around 6 hours, so I ran 3 processes at the same time so it took the whole job around 6 hours.