Page 1 of 2
How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 1:20 pm
by stmdbe2019
How to submit the command: ipconfig /all | findstr /IR "ipv4 ethernet adapter" | findstr /IRV "description tunnel vpn dial bluetooth [2-9]:$" | findstr /LV "*"
Code: Select all
Compiler = RunProgram("ipconfig /all | findstr /IR ''Physical''", "", "", #PB_Program_Open | #PB_Program_Read)
Output$ = ""
If Compiler
While ProgramRunning(Compiler)
If AvailableProgramOutput(Compiler)
Output$ + ReadProgramString(Compiler) + Chr(13)
EndIf
Wend
Output$ + Chr(13) + Chr(13)
CloseProgram(Compiler)
EndIf
MessageRequester("Show output", Output$)
Re: How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 1:25 pm
by Kiffi
Code: Select all
Compiler = RunProgram("cmd", "/c ipconfig /all ...
Re: How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 1:27 pm
by swhite
Have you tried separating the file name and the parameters as below?
Code: Select all
Compiler = RunProgram("ipconfig.exe"," /all | findstr /IR ''Physical''","", #PB_Program_Open | #PB_Program_Read)
Simon
Re: How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 1:35 pm
by mk-soft
Not tested...
Code: Select all
Compiler = RunProgram("ipconfig.exe"," /all | findstr /IR " + #DQUOTE$ + "Physical" + #DQUOTE$,"", #PB_Program_Open | #PB_Program_Read)
Re: How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 1:37 pm
by Bitblazer
Code: Select all
ipconfig /all | findstr /IR ''Physical''
Those are two commands, not one. The pipe symbol attaches the STDOUT of "ipconfig /all" with the STDIN of "findstr /IR Physical".
Not sure if you can do it with a single runpgram call this way. You could call a shell and pass that command though, but that just delegates the work to the shell processor (like Kifi suggested). Or you do it the correct way manually by using two RUNPROGRAM calls and handle STDIN and STDOUT yourself.
Re: How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 1:40 pm
by stmdbe2019
Not working. Tried both.
Compiler = RunProgram("cmd", "/c ipconfig /all ...
or
Compiler = RunProgram("ipconfig.exe"," /all | findstr /IR " + #DQUOTE$ + "Physical" + #DQUOTE$,"", #PB_Program_Open | #PB_Program_Read)
Compiler = RunProgram("ipconfig.exe"," /all | findstr /IR ''Physical''","", #PB_Program_Open | #PB_Program_Read)
Or you do it the correct way manually by using two RUNPROGRAM calls and handle STDIN and STDOUT yourself.
> how?
Re: How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 2:03 pm
by Kiffi
shamun wrote:Compiler = RunProgram("cmd", "/c ipconfig /all ...
That was just an example, of course.
Try this one:
Code: Select all
Compiler = RunProgram("cmd", "/c ipconfig /all | findstr /IR " + #DQUOTE$ + "Physical" + #DQUOTE$, "", #PB_Program_Open | #PB_Program_Read)
Re: How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 2:22 pm
by Bitblazer
shamun wrote:
> how?[/quote]
I usually use a procedure like this to get the STDOUT from a command
Code: Select all
Procedure.s GetOutput(ProgramName$, Parameter$, *ExitCode, SkipLines.i = 0)
Define ThisTool.i, ExitCode.i, LineNum.i
Define Output$, NextLine$
ThisTool = RunProgram(ProgramName$, Parameter$, GetCurrentDirectory(), #PB_Program_Open | #PB_Program_Read | #PB_Program_Ascii)
Output$ = ""
LineNum = 1
If (ThisTool <> 0)
While ProgramRunning(ThisTool)
If AvailableProgramOutput(ThisTool)
NextLine$ = ReadProgramString(ThisTool)
If (SkipLines < LineNum)
If (Len(Output$) > 0)
Output$ + Chr(13)
EndIf
Output$ + NextLine$
EndIf
Linenum + 1
EndIf
Wend
ExitCode = ProgramExitCode(ThisTool)
CloseProgram(ThisTool)
ExitCode = 1
If (*ExitCode <> 0)
PokeI(*ExitCode, ExitCode)
EndIf
Else
If (*ExitCode <> 0)
PokeI(*ExitCode, ThisTool)
EndIf
EndIf
ProcedureReturn Output$
EndProcedure
and use it like
Code: Select all
CommandName$ = GetOutput("which", "equo", 0)
and for STDIN, just check
programparameter and
countprogramparameters
But using Kifi's way is much less code by letting the shell processor do the work
If you need more practical examples check out for example the
linux sysinfo sources where i shamelessly rippped this from

Re: How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 2:36 pm
by firace
My take on it
Code: Select all
Procedure.s outputOf(externalCommand.s, elevated=0, hidden=0, allLines=0)
externalCommand = ReplaceString(externalCommand,"'",Chr(34))
If allLines
binary= RunProgram( "cmd", "/c " + externalCommand, "", #PB_Program_Open|#PB_Program_Read|#PB_Program_Hide)
While ProgramRunning(Binary)
If AvailableProgramOutput(Binary) : o.s + ReadProgramString(Binary) + #CRLF$
EndIf
Wend
Else
o.s = ReadProgramString(RunProgram( "cmd", "/c " + externalCommand, "", #PB_Program_Open|#PB_Program_Read|#PB_Program_Hide) )
EndIf
ProcedureReturn o
EndProcedure
Debug OutputOf("ipconfig /all | findstr /IR 'ipv4 ethernet adapter' | findstr /IRV 'description tunnel vpn dial bluetooth [2-9]:$' | findstr /LV '*' ", 0, 0, 1)
Re: How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 2:42 pm
by kenmo
Bitblazer is 100% right, when you use the "|" character in a console it's actually running multiple commands and connecting them together.
RunProgram() has a #PB_Program_Connect flag for
exactly this purpose but I tried and I can't get it working. I don't think it's a commonly used feature and I can't find any examples on the forum.
EDIT: If we can get it working, I would gladly package it into a helper procedure
Code: Select all
; Testing #PB_Program_Connect
CompilerIf (#PB_Compiler_ExecutableFormat <> #PB_Compiler_Console)
CompilerWarning "Note: Not compiled in Console mode (is it needed to pipe programs?)"
CompilerEndIf
If OpenConsole()
Flags = #PB_Program_Open | #PB_Program_Read | #PB_Program_Hide
*ipconfig = RunProgram("ipconfig", "/all", "", Flags)
;Debug *ipconfig
Flags = #PB_Program_Open | #PB_Program_Read | #PB_Program_Hide | #PB_Program_Connect; | #PB_Program_Write
*findstr = RunProgram("findstr", "/I ipv4", "", Flags, *ipconfig)
;Debug *findstr
StartTime = ElapsedMilliseconds()
While (ProgramRunning(*ipconfig) Or ProgramRunning(*findstr))
; This should not be needed, because findstr should read ipconfig's output
; But it seems this must be read or the loop will never exit
If AvailableProgramOutput(*ipconfig)
Output.s + ReadProgramString(*ipconfig) + #CRLF$
EndIf
If AvailableProgramOutput(*findstr)
Output2.s + ReadProgramString(*findstr) + #CRLF$
EndIf
Delay(0)
Wend
Debug "-------------- ipconfig output:"
Debug Output
Debug "-------------- findstr output:"
Debug Output2
CloseProgram(*findstr)
CloseProgram(*ipconfig)
CloseConsole()
EndIf
Re: How to submit the command with RunProgram?
Posted: Tue Aug 20, 2019 4:14 pm
by stmdbe2019
FAILED:
WORKED (method @firace 100% stable):

Re: How to submit the command with RunProgram?
Posted: Wed Aug 21, 2019 2:59 am
by kenmo
shamun wrote:FAILED:

I am aware. I said I could not get the #PB_Program_Connect flag working. Moving it to another thread.
Re: How to submit the command with RunProgram?
Posted: Wed Aug 21, 2019 8:39 am
by BarryG
Is this what you're trying to do? What's the expected output?
Code: Select all
Prog = RunProgram(GetEnvironmentVariable("comspec"),"/c ipconfig.exe /all | findstr /IR " + #DQUOTE$ + "Physical" + #DQUOTE$,"", #PB_Program_Hide | #PB_Program_Open | #PB_Program_Read)
If Prog
While ProgramRunning(Prog)
If AvailableProgramOutput(Prog)
Output$ + ReadProgramString(Prog) + Chr(13)
EndIf
Wend
CloseProgram(Prog)
EndIf
MessageRequester("Output", Output$)

Re: How to submit the command with RunProgram?
Posted: Wed Aug 21, 2019 8:53 am
by Joris
My two cents... if the problem is not fixed yet.
I find out that the ProgramName in "RunProgram(ProgramName$..." is not always enough.
Sometimes the complete path to that program is needed also. I don't no why, but am sure it is like that (here).
Re: How to submit the command with RunProgram?
Posted: Wed Aug 21, 2019 6:47 pm
by Bitblazer
kenmo wrote:Bitblazer is 100% right, when you use the "|" character in a console it's actually running multiple commands and connecting them together.
Because this is really essential in understanding, i made some amateurish graphics and will attempt a simplified explanation.
When a shell does when it launches a commandline executable (among other things) is to create a process envorinment. Among loading of data, resolving adresses and bindings (DLL's, SO's), it also creates a file descriptor table in each process. The first descriptors are reserved and connected to IO pathes the command processor handles (for a terminal window, that would usually be keyboard input and console text output). Remember that this design was invented many decades ago for text processing and not GUI's.
The first descriptors are reserved and called STDIN, STDOUT and STDERR. Their numbers internally are 0, 1 and 2. In many command processors you can manually re-assign them by their internal number ( cat textfile.txt 2> errors.txt" would make a shell send all STDERR messages into the file "errors.txt".
For one process executed from a commandline it looks like this
If you use a pipe symbol between 2 commands, the shell processor will spawn two processes and manipulate their IO tables like this:
With the right tools or if you actually look inside the source of different shell processors, you can watch this whole process nicely. For unix use something like trace/strace/dtrace and for windows i suggest looking into
WinAPIOverride
kenmo wrote:RunProgram() has a #PB_Program_Connect flag for exactly this purpose but I tried and I can't get it working. I don't think it's a commonly used feature and I can't find any examples on the forum.
I grepped my sources but i actually never used the flag anywhere and i wrote quite a few console programs
