RunProgram, then send it a message?

Just starting out? Need help? Post your questions and find answers here.
Seymour Clufley
Addict
Addict
Posts: 1266
Joined: Wed Feb 28, 2007 9:13 am
Location: London

RunProgram, then send it a message?

Post by Seymour Clufley »

Is there a cross-platform way to make a command line utility stop? I have a Windows solution, in case anyone needs it:

Code: Select all

Structure RunProgramExtendedStructure
  ProgramID.i
  WindowHandle.i
EndStructure

Procedure.i EnumWindowsCallBack(hwnd.i, param.i)
  
  Protected *RunProgramExtended.RunProgramExtendedStructure
  
  Result.i = #True
  *RunProgramExtended = param
  If GetWindowThreadProcessId_(hwnd, @PID.i)
    If PID = *RunProgramExtended\ProgramID
      *RunProgramExtended\WindowHandle = hwnd
      Result = #False
    EndIf
  EndIf
  
  ProcedureReturn Result
  
EndProcedure



prog.i = RunProgram(exe,param,folder,#PB_Program_Open)

*Buffer = AllocateMemory(#MAX_PATH * SizeOf(Character), #PB_Memory_NoClear)
RunProgramExtended.RunProgramExtendedStructure\ProgramID = ProgramID(prog)

starttime.i = Date()
While ProgramRunning(prog)
  If RunProgramExtended\WindowHandle = 0
    EnumWindows_(@EnumWindowsCallBack(), @RunProgramExtended)
  EndIf
  
  If (Date()-starttime)>4 ; after 4 seconds, tell it to shut down
    PostMessage_(RunProgramExtended\WindowHandle,#WM_KEYDOWN,#VK_Q,0)
    PostMessage_(RunProgramExtended\WindowHandle,#WM_KEYUP,#VK_Q,0)
  EndIf
  Delay(50)
Wend

CloseProgram(prog)
but I'm wondering if there is a direct way to communicate with a program started using RunProgram, rather than faking keystrokes?

If not, are there equivalents of the keystroke code above, but for Mac and Linux?

Thank you.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RunProgram, then send it a message?

Post by infratec »

Code: Select all

WriteProgramString()
Example:

Code: Select all

EnableExplicit


Structure RunProgramExtendedStructure
  ProgramID.i
  WindowHandle.i
EndStructure


Procedure.i EnumWindowsCallBack(hwnd.i, param.i)
 
  Protected Result.i, PID.l, Length.i, *RunProgramExtended.RunProgramExtendedStructure
 
 
  Result = #True
  *RunProgramExtended = param
  If GetWindowThreadProcessId_(hwnd, @PID)
    If PID = *RunProgramExtended\ProgramID
      *RunProgramExtended\WindowHandle = hwnd
      Result = #False
    EndIf
  EndIf
 
  ProcedureReturn Result
 
EndProcedure


Define Compiler.i, *Buffer, Length.i, Title$, NewTitle$, StartTime.i
Define RunProgramExtended.RunProgramExtendedStructure


Compiler = RunProgram("cmd","","", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write)
If Compiler
 
  *Buffer = AllocateMemory(#MAX_PATH * SizeOf(Character), #PB_Memory_NoClear)
  If *Buffer
   
    RunProgramExtended\ProgramID = ProgramID(Compiler)
    
    StartTime = Date()
    
    While ProgramRunning(Compiler)
      
      If Date() - StartTime > 4
        StartTime = Date()
        WriteProgramStringN(Compiler, "exit")
      EndIf
      
      If RunProgramExtended\WindowHandle = 0
        EnumWindows_(@EnumWindowsCallBack(), @RunProgramExtended)
      Else
        Length = GetWindowText_(RunProgramExtended\WindowHandle, *Buffer, #MAX_PATH)
        If Length
          ;Debug Length
          NewTitle$ = PeekS(*Buffer, Length)
          If Title$ <> NewTitle$
            Title$ = NewTitle$
            Debug "Title: " + Title$
          EndIf
        EndIf
      EndIf
     
      Length = AvailableProgramOutput(Compiler)
      If Length
        If ReadProgramData(Compiler,*Buffer, Length)
          Debug PeekS(*Buffer, Length, #PB_UTF8|#PB_ByteLength)
        EndIf
      EndIf
    Wend
   
    FreeMemory(*Buffer)
  EndIf
 
  CloseProgram(Compiler) ; Close the connection to the program
EndIf
Last edited by infratec on Fri Oct 23, 2020 5:43 pm, edited 1 time in total.
Seymour Clufley
Addict
Addict
Posts: 1266
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: RunProgram, then send it a message?

Post by Seymour Clufley »

Thanks, Infratec. I can't believe I was looking through the Help file for ages this morning but somehow didn't see that command!
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: RunProgram, then send it a message?

Post by Marc56us »

On my PC Windows with PB 5.72 LTS
Works on x86 version but not on x64

Code: Select all

Waiting for executable to start...
Executable type: Windows - x64  (64bit, Unicode)
Executable started.
[ERROR] Line: 18
[ERROR] Invalid memory access. (read error at address 1074013176)
The Program was killed.
Line 18:

Code: Select all

    If PID = *RunProgramExtended\ProgramID
:(
User avatar
Shardik
Addict
Addict
Posts: 2067
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: RunProgram, then send it a message?

Post by Shardik »

Marc56us wrote:On my PC Windows with PB 5.72 LTS
Works on x86 version but not on x64
In

Code: Select all

EnumWindowsCallBack(hwnd.i, param.l)
you have to change param.l to param.i to work correctly with 32 and 64 bit... :wink:
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RunProgram, then send it a message?

Post by infratec »

Yes that's right, I looked in the win32 API where it is declared as LongParam.
I changed the listing above.
Post Reply