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)



Image
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. :wink:

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:

Image

WORKED (method @firace 100% stable):

Image

Re: How to submit the command with RunProgram?

Posted: Wed Aug 21, 2019 2:59 am
by kenmo
shamun wrote:FAILED:
:lol: 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$)
Image

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

Image

If you use a pipe symbol between 2 commands, the shell processor will spawn two processes and manipulate their IO tables like this:

Image

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 :o