Capture CMD output into Window

Hi,

Has anyone ever captured the output of a cmd process and put it into a window? Does anyone have any code?

Thanks

Ron

I was trying to paste this thread, but failed. Here’s another try. :slight_smile: Using WriteConsoleA from a Clarion application - #8 by mriffey

Also, Capesoft’s Oddjob works well for capturing a commandline output.

1 Like

Thanks Jeff. I will check it out an see if this will work. I am not trying to capture the output from the command line and just display it. I was thinking of using CreateProcess and running cmd and then read stdout. I just wonder the best way to get the data into a window. Not looking to purchase a solution. Always looking to learn more.

Wow, long time no see.

I’ve been around. Just very busy. A lot of my new work is Laravel (php) and python. Just trying to do some Clarion work and merge Laravel and Clarion hence getting information back from php commands.

Ron, I have an old ClarionMag article that includes a class to do this. I’ll see if I can track down a link.
Also, if you have OddJob from Capesoft there is a method to do what you want.

2 Likes

I think KSS captures Std Out when it runs FindStr.

The source is on GitHub under Devuna.

I have an older one on mine that has the routines converted to a class. It does not have any third party products.

Robert Artigas has it on his GitHub setup to be easy to build.

The article is called ‘Capturing Standard Output From A Console Program’ and is in the ClarionMag cmag-2008-01.pdf and cmag-2008-01.zip (source code) that you can still access on the Jira ClarionMag archive here…

https://clarionmag.jira.com/wiki/spaces/archive/pages/399447/ClarionMag+monthly+PDFs+and+source+ZIPs+2008

1 Like

Thanks for tracking that down, @Graham_Dawson

Here is working code. Took it from a lot of sources. Thanks everyone.

Test2                PROCEDURE                    ! Declare Procedure
szCmdLine                     CSTRING(261)
laravelPath                   CSTRING(261)
currentDirectory              CSTRING(261)
saAttr                        LIKE(SECURITY_ATTRIBUTES)
hStdInPipeRead                HANDLE
hStdInPipeWrite               HANDLE
hStdOutPipeRead               HANDLE
hStdOutPipeWrite              HANDLE
hStdErrPipeWrite              HANDLE
siStartInfo                   LIKE(STARTUPINFO)
bSuccess                      BOOL
chBuf                         CSTRING(128)
dwRead                        DWORD
Window              WINDOW('Caption'),AT(,,260,141),GRAY,FONT('Segoe UI',9),TIMER(10)
											TEXT,AT(2,2,255,137),USE(?OutputText)
										END

  CODE                                            ! Begin processed code

  szCmdLine = 'php artisan bulloch:setx-activate 9998'
  
  laravelPath = GETINI('Laravel','Application Path','','.\cmdbox.INI')
  IF laravelPath = ''
    DO ProcedureReturn
  END
  
  saAttr.nLength = SIZE(SECURITY_ATTRIBUTES)
  saAttr.lpSecurityDescriptor = 0
  saAttr.bInheritHandle = TRUE
  IF NOT CreatePipe(hStdOutPipeRead, hStdOutPipeWrite, saAttr, 0)
  	DO ProcedureReturn
  END
  IF NOT SetHandleInformation(hStdOutPipeRead, HANDLE_FLAG_INHERIT, 0)
  	DO ProcedureReturn
  END
  IF NOT DuplicateHandle(GetCurrentProcess(),hStdOutPipeWrite,GetCurrentProcess(),hStdErrPipeWrite,0,TRUE,DUPLICATE_SAME_ACCESS)
  	DO ProcedureReturn
  END
  IF NOT CreatePipe(hStdInPipeRead, hStdInPipeWrite, saAttr, 0)
  	DO ProcedureReturn
  END
  IF NOT SetHandleInformation(hStdInPipeWrite, HANDLE_FLAG_INHERIT, 0)
  	DO ProcedureReturn
  END
  ZeroMemory(ADDRESS(siStartInfo),SIZE(STARTUPINFO))
  siStartInfo.cb = SIZE(STARTUPINFO);
  siStartInfo.dwFlags = BOR(siStartInfo.dwFlags,STARTF_USESTDHANDLES)
  siStartInfo.hStdError = hStdErrPipeWrite
  siStartInfo.hStdOutput = hStdOutPipeWrite
  siStartInfo.hStdInput = hStdInPipeRead
  siStartInfo.dwFlags = BOR(siStartInfo.dwFlags,STARTF_USESHOWWINDOW)
  siStartInfo.wShowWindow = SW_HIDE
  ZeroMemory(ADDRESS(piProcInfo), SIZE(PROCESS_INFORMATION))
  CurrentDirectory = PATH()
  SETPATH(laravelPath)
  bSuccess = 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 parents environment
  	0,    |  ! The full path to the current directory for the process.
  	siStartInfo,    |  ! STARTUPINFO pointer
  	piProcInfo			|  ! receives PROCESS_INFORMATION
  	)    
  SETPATH(CurrentDirectory)
  IF bSuccess = FALSE
  	DO ProcedureReturn
  END
  CloseHandle(hStdOutPipeWrite)
  CloseHandle(hStdInPipeRead)
  CloseHandle(hStdErrPipeWrite)
  OPEN(Window)
  ACCEPT
  	CASE EVENT()
  	OF EVENT:Timer
  		bSuccess = ReadFile(hStdOutPipeRead,ADDRESS(chBuf),128,ADDRESS(dwRead),0)
  		IF NOT bSuccess OR dwRead = 0
  			0{PROP:Timer} = 0
  			BREAK
  		END
  		chBuf[dwRead + 1] = '<00>'
  		?OutputText{PROP:Text} = ?OutputText{PROP:Text} & chBuf
  		DISPLAY(?OutputText)
  	END
  END
  CLOSE(Window)
  
  !bSuccess = ReadFile(hStdOutPipeRead,ADDRESS(buf),128,ADDRESS(dwRead),0)
  !LOOP WHILE bSuccess = TRUE
  !	buf[dwRead + 1] = '<00>'
  !	MESSAGE(buf)
  !	bSuccess = ReadFile(hStdOutPipeRead,ADDRESS(buf),128,ADDRESS(dwRead),0)
  !END
  CloseHandle(hStdOutPipeRead)
  CloseHandle(hStdInPipeWrite)
  
  DO ProcedureReturn
!---------------------------------------------------------------------------
ProcedureReturn ROUTINE
  RETURN
!---------------------------------------------------------------------------
                  PROGRAM
                  MAP
                  END

Command1        CSTRING(100)
Text1           CSTRING(10000)

QuickWindow WINDOW('Test 1'),AT(,,500,329),CENTER,GRAY,IMM,SYSTEM,FONT('MS Sans Serif',8,,FONT:regular),COLOR(0F8FFFDH)
        TEXT,AT(25,75,449,228),USE(Text1),SKIP,VSCROLL,FONT('Consolas')
        ENTRY(@s100),AT(72,33,402,11),USE(Command1),FONT('Consolas',10)
        BUTTON('Run command'),AT(25,50,78),USE(?Button:Run),SKIP
        PROMPT('Command:'),AT(25,34),USE(?Prompt:Command1)
    END
  
  CODE
  OPEN(QuickWindow)
  ACCEPT
    IF EVENT() = EVENT:Accepted
      RUN('Test1.bat ' & Command1, 1)
      Text1 = CLIPBOARD(1)
      DISPLAY(?Text1)
    END
  END 

Above is a little program that puts the output of a cmd into a window.

Here is the Test1.bat file referenced:
@echo off
rem echo %1 %2 %3 %4
%1 %1 %2 %3 %4 | CLIP

For example, enter a command, DIR *.exe, and see the output in a window.

Bob

An alternative to using | CLIP for the Clipboard would be Redirection > to a File. Then use the ASCII BASIC DOS driver to read that file, or StringTheory.

That would have a batch file like this:

@echo off
rem echo %1 %2 %3 %4
rem Write [Failed] to the file so if fails to run we have a way to tell
echo [Failed]  > TestResult.TXT
%1 %1 %2 %3 %4 > TestResult.TXT

Instead of always > TestResult.TXT I would pass the output name in the Clarion RUN as a parameter so it could be unique per user and run instance. I would probably have it in the Temp folder using GetTempFileNameA

Also in Clarion I would write [Failed] to that file so should the RUN not work I’ll know, there will be no chance of stale or invalid data. I would do the same in your code before Run e.g. SetClipboard('Failed]')

Good suggestions. Thanks Carl.
I’ll give it a try.
I think I can put >> in the RUN command line and not use a bat file.
The RUN command doesn’t seem to treat the stile character as DOS piping character.

On another note, I hope Clarion will someday have a driver to get the output of a PowerShell command. Z talked about this at CIDC 2024.
Bob