Hang with ReadProgramString()

Just starting out? Need help? Post your questions and find answers here.
jassing
Addict
Addict
Posts: 1768
Joined: Wed Feb 17, 2010 12:00 am

Hang with ReadProgramString()

Post by jassing »

The code below will hang -- on one hand, it says, "yes, there is program output available" but on the other, it fails to return from fetching said output...
Is there a way to resolve this? It seems availableprogramoutput() sees the string,but ReadProgramString() fails to return because there is no cr/lf ...

Code: Select all

  hProg = RunProgram(GetEnvironmentVariable("WinDir")+"\system32\cmd.exe", "", "", #PB_Program_Open | #PB_Program_Read)
  
  If hProg
    OpenConsole()
    While ProgramRunning(hProg)
      If AvailableProgramOutput(hProg)
        Debug "Avail output"
        ; get's stuck here:
        c$ = ReadProgramString(hProg)
        Debug "Output is "+c$
        PrintN(C$)
      EndIf
    Wend
   
    CloseProgram(hProg) ; Close the connection to the program
  EndIf
jassing
Addict
Addict
Posts: 1768
Joined: Wed Feb 17, 2010 12:00 am

Re: Hang with ReadProgramString()

Post by jassing »

Solved my own issue...

Code: Select all

  While ProgramRunning(hProg)
      n = AvailableProgramOutput(hProg)
      If n 
        Debug "Avail output"
        c$ = Space(n)
        ReadProgramData(hProg,@c$,n)
        Debug "Output is "+c$
        PrintN(C$)
      EndIf
    Wend
User avatar
Michael Vogel
Addict
Addict
Posts: 2677
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Hang with ReadProgramString()

Post by Michael Vogel »

Does anyone know how to get this running - means you'll see the console output of a console program before it ends?
The console tool Latte can be found here and needs to be copied into the source code path.

PB5.71 works a little bit better than PB 5.46 which can be seen here...

Code: Select all

#ToolPath="Latte.exe"
#ToolPort=5555

Structure ControlType
	Address.s
	Port.i
	Active.i
EndStructure

Global Control.ControlType

If InitNetwork()
	If ExamineIPAddresses()
		Repeat
			IP=NextIPAddress()
			If IP
				Control\Address=IPString(IP)
				Debug "IPv4: " + Control\Address
			EndIf
		Until IP=0
	EndIf
EndIf

s.s
Control\Port=#ToolPort
s=#ToolPath+" -a "+Control\Address+":"+Str(Control\Port)
cmd=RunProgram("cmd.exe","/c "+s,".",#PB_Program_Open|#PB_Program_Read);|#PB_Program_Hide)
Control\Active=1

If cmd
	Timer=ElapsedMilliseconds()+10
	While ProgramRunning(cmd) ;And Control\Active
		If ElapsedMilliseconds()>Timer; AvailableProgramOutput(cmd)
			n = AvailableProgramOutput(cmd)
			Debug "."
			;s=ReadProgramError(cmd,#PB_Ascii)
			;Debug s
			s=ReadProgramString(cmd,#PB_Ascii);  STUCKS HERE when using PB5.46
			Debug "ok"
			If s
				Debug Str(n)+"/"+Str(ProgramRunning(cmd))+": ["+Right(s,70)+"]"
			EndIf
			Timer=ElapsedMilliseconds()+10
		EndIf
	Wend
	CloseProgram(cmd)
	Debug "Closed."
EndIf
But there's NO server output seen when using the code below. After starting the program, Latte is started as a server, when pressing "C", a client instance will also be started. Doing so, both console instances should display their information right now. In fact, the output is delayed until the program is finished, therefore the client's output is seen, but not the server's.

Code: Select all

; Define

	#ToolPath="Latte.exe"
	#ToolPort=5555

	Structure ThreadType
		ID.i
		Active.i
	EndStructure

	Structure ControlType
		Address.s
		Port.i
		Server.ThreadType
		Client.ThreadType
	EndStructure

	Global Control.ControlType

	If InitNetwork()
		If ExamineIPAddresses()
			Repeat
				IP=NextIPAddress()
				If IP
					Control\Address=IPString(IP)
					Debug "IPv4: " + Control\Address
				EndIf
			Until IP=0
		EndIf
	EndIf

	Control\Port=#ToolPort

; EndDefine

Procedure Server(nil)

	Protected s.s
	Protected Timer

	s=#ToolPath+" -ga -a "+Control\Address+":"+Str(Control\Port)
	;s=#ToolPath+" -a "+Control\Address+":"+Str(Control\Port)
	Debug s
	;SetClipboardText(s)

	Control\Server\Active=#True
	cmd=RunProgram("cmd.exe","/c "+s,".",#PB_Program_Open|#PB_Program_Read);|#PB_Program_Hide)

	If cmd
		Timer=ElapsedMilliseconds()+10
		While ProgramRunning(cmd) And Control\Server\Active
			If ElapsedMilliseconds()>Timer; AvailableProgramOutput(cmd)
				s=ReadProgramString(cmd,#PB_Ascii)
				If s
					Debug "Server "+Str(ProgramRunning(cmd))+": ["+Right(s,70)+"]"
				EndIf
				Timer=ElapsedMilliseconds()+10
			EndIf
		Wend
		CloseProgram(cmd)
		Debug "Server done."
	EndIf

	Control\Server\Active=#Null

EndProcedure
Procedure Client(nil)

	Protected s.s

	s=#ToolPath+" -sa -c -a "+Control\Address+":"+Str(Control\Port)+" -i 10"
	;s=#ToolPath+" -a "+Control\Address+":"+Str(Control\Port)
	Debug s
	;SetClipboardText(s)

	cmd=RunProgram("cmd.exe","/c "+s,".",#PB_Program_Open|#PB_Program_Read);|#PB_Program_Hide)

	Control\Client\Active=#True

	If cmd
		Timer=ElapsedMilliseconds()+10
		While ProgramRunning(cmd) And Control\Client\Active
			If ElapsedMilliseconds()>Timer; AvailableProgramOutput(cmd)
				s=ReadProgramString(cmd,#PB_Ascii)
				If s
					Debug "Client "+Str(ProgramRunning(cmd))+": ["+Right(s,70)+"]"
				EndIf
				Timer=ElapsedMilliseconds()+10
			EndIf
		Wend
		CloseProgram(cmd)
		Debug "Client done."
	EndIf

	Control\Client\Active=#Null

EndProcedure
Procedure Exit()

	Control\Client\Active=#Null
	Control\Server\Active=#Null

	While IsThread(Control\Server\ID) Or IsThread(Control\Client\ID)
		Debug "wait..."
		Delay(5)
	Wend
	End

EndProcedure

OpenWindow(0,10,10,100,0,"...")
Control\Server\ID=CreateThread(@Server(),0)
SetForegroundWindow_(WindowID(0))
AddWindowTimer(0,0,1000)

Repeat
	Select WaitWindowEvent()
	Case #PB_Event_CloseWindow
		Exit()
	Case #WM_CHAR
		Select EventwParam()
		Case 'c','C'
			If Control\Client\Active=#Null
				Control\Client\ID=CreateThread(@Client(),0)
			Else
				Debug "Client busy"
			EndIf
		Case #ESC
			Exit()
		EndSelect
	Case #PB_Event_Timer
		Debug "Threads S:"+Str(Control\Server\Active)+" / C:"+Str(Control\Client\Active)
	EndSelect
ForEver
It seems that the console output is buffered here, so maybe reducing the buffer size would do the trick - so how to do something like SetBuffer(stdout,#NULL) :?:
Post Reply