How to submit the command with RunProgram?

Just starting out? Need help? Post your questions and find answers here.
stmdbe2019
User
User
Posts: 89
Joined: Mon Aug 31, 2009 2:11 pm

How to submit the command with RunProgram?

Post 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$)  
-----
Registered PureBasic Coder.
User avatar
Kiffi
Addict
Addict
Posts: 1485
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: How to submit the command with RunProgram?

Post by Kiffi »

Code: Select all

Compiler = RunProgram("cmd", "/c ipconfig /all ...
Hygge
swhite
Enthusiast
Enthusiast
Posts: 789
Joined: Thu May 21, 2009 6:56 pm

Re: How to submit the command with RunProgram?

Post 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
Simon White
dCipher Computing
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to submit the command with RunProgram?

Post by mk-soft »

Not tested...

Code: Select all

Compiler = RunProgram("ipconfig.exe"," /all | findstr /IR " + #DQUOTE$ + "Physical" + #DQUOTE$,"", #PB_Program_Open | #PB_Program_Read)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Bitblazer
Enthusiast
Enthusiast
Posts: 761
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: How to submit the command with RunProgram?

Post 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.
Last edited by Bitblazer on Tue Aug 20, 2019 1:40 pm, edited 1 time in total.
stmdbe2019
User
User
Posts: 89
Joined: Mon Aug 31, 2009 2:11 pm

Re: How to submit the command with RunProgram?

Post 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?
-----
Registered PureBasic Coder.
User avatar
Kiffi
Addict
Addict
Posts: 1485
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: How to submit the command with RunProgram?

Post 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)
Hygge
Bitblazer
Enthusiast
Enthusiast
Posts: 761
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: How to submit the command with RunProgram?

Post 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 :)
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: How to submit the command with RunProgram?

Post 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)

User avatar
kenmo
Addict
Addict
Posts: 2033
Joined: Tue Dec 23, 2003 3:54 am

Re: How to submit the command with RunProgram?

Post 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
stmdbe2019
User
User
Posts: 89
Joined: Mon Aug 31, 2009 2:11 pm

Re: How to submit the command with RunProgram?

Post by stmdbe2019 »

FAILED:

Image

WORKED (method @firace 100% stable):

Image
-----
Registered PureBasic Coder.
User avatar
kenmo
Addict
Addict
Posts: 2033
Joined: Tue Dec 23, 2003 3:54 am

Re: How to submit the command with RunProgram?

Post 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.
BarryG
Addict
Addict
Posts: 4126
Joined: Thu Apr 18, 2019 8:17 am

Re: How to submit the command with RunProgram?

Post 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
Joris
Addict
Addict
Posts: 890
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: How to submit the command with RunProgram?

Post 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).
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Bitblazer
Enthusiast
Enthusiast
Posts: 761
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: How to submit the command with RunProgram?

Post 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
Post Reply