Page 1 of 2
Bug? - ReadProgramString() and unicode
Posted: Tue Apr 20, 2010 7:25 pm
by c4s
With unicode enabled the following example displays a big string instead of several ones. Test both modes to see what I mean. Code:
Code: Select all
Define ProgramString.s, ProgramNr
ProgramNr = RunProgram("help", "", GetPathPart(ProgramFilename()), #PB_Program_Open | #PB_Program_Read | #PB_Program_Hide)
If ProgramNr
While ProgramRunning(ProgramNr)
If AvailableProgramOutput(ProgramNr)
ProgramString = ReadProgramString(ProgramNr)
Debug ProgramString ;; Bug? -> With unicode enabled just one big string
EndIf
Wend
CloseProgram(ProgramNr)
EndIf
Is it a bug or am I doing something wrong?
Re: Bug? - ReadProgramString() and unicode
Posted: Tue Apr 20, 2010 8:01 pm
by ts-soft
Use ReadProgramData() and PeekS to read the string!
Re: Bug? - ReadProgramString() and unicode
Posted: Tue Apr 20, 2010 8:46 pm
by Justin
I did this function some time ago:
Code: Select all
procedure.s ReadProgramStringU(program)
define.ASCII achar
define.s text
text = ""
while ReadProgramData(program, @achar, sizeof(ASCII))
if achar\a = #CR
continue
elseif achar\a = #LF
break
endif
text = text + peeks(@achar, sizeof(ASCII), #PB_Ascii)
wend
procedurereturn text
endprocedure
Re: Bug? - ReadProgramString() and unicode
Posted: Tue Apr 20, 2010 9:04 pm
by c4s
Thanks, but I don't get it. This also doesn't work as expected because now several "lines" are in one:
Code: Select all
Define ProgramString.s, ProgramStringSize, ProgramNr
ProgramNr = RunProgram("help", "", GetPathPart(ProgramFilename()), #PB_Program_Open | #PB_Program_Read | #PB_Program_Hide)
If ProgramNr
While ProgramRunning(ProgramNr)
ProgramStringSize = AvailableProgramOutput(ProgramNr)
If ProgramStringSize > 0
ProgramString = Space(ProgramStringSize)
ReadProgramData(ProgramNr, @ProgramString, ProgramStringSize)
ProgramString = PeekS(@ProgramString, ProgramStringSize, #PB_Ascii)
Debug ProgramString
EndIf
Wend
CloseProgram(ProgramNr)
EndIf
Besides it seems that ReadProgramError() also doesn't work in unicode mode because trying a program where I should get some messages returns nothing (however in nonunicode mode everything is fine).
edit:
@Justin
Thank you, works perfectly. Do you have something similar for ReadProgramError()?
Re: Bug? - ReadProgramString() and unicode
Posted: Tue Apr 20, 2010 9:30 pm
by ts-soft
Not tested, but your code should like this:
Code: Select all
Define *ProgramStringbuffer, ProgramString.s, ProgramStringSize, ProgramNr
ProgramNr = RunProgram("help", "", GetPathPart(ProgramFilename()), #PB_Program_Open | #PB_Program_Read | #PB_Program_Hide)
If ProgramNr
While ProgramRunning(ProgramNr)
ProgramStringSize = AvailableProgramOutput(ProgramNr)
If ProgramStringSize > 0
*ProgramStringbuffer = AllocateMemory(ProgramStringSize + 1)
ReadProgramData(ProgramNr, *ProgramStringbuffer, ProgramStringSize)
ProgramString + PeekS(*ProgramStringbuffer, -1, #PB_Ascii) + #LF$
FreeMemory(*ProgramStringbuffer)
Debug ProgramString
EndIf
Wend
CloseProgram(ProgramNr)
EndIf
Re: Bug? - ReadProgramString() and unicode
Posted: Wed Apr 21, 2010 8:15 pm
by Justin
I did this include that works in ascii and unicode, it's based on an ols code i found by Rings. It reads the standard output and error, you can use #PROCESS_JOIN_OUTPUT to read everything at once.
Code: Select all
;process.pb
;Justin 04/10
enableexplicit
structure PROCESS_OBJ
hReadStdOut.i
hWriteStdOut.i
hReadStdErr.i
hWwriteStdErr.i
process.PROCESS_INFORMATION
dataRead.i
lastErrChar.ASCII
lastStdChar.ASCII
endstructure
#PROCESS_JOIN_OUTPUT = 2 ;stdout and stderr are both redirected to the stdout pipe
declare.s proc__ReadLine(*lastChar.ASCII, *dataRead.i, hpipe.i)
;Public functions
procedure proc_RunProgram(program.s, commad.s, flags.l=0, *err.INTEGER=#null)
define.PROCESS_OBJ *this
define.STARTUPINFO start
define.SECURITY_ATTRIBUTES sa
define.i error
*this = allocatememory(sizeof(PROCESS_OBJ))
error = 0
;Create the Pipes
sa\nLength =SizeOf(SECURITY_ATTRIBUTES)
sa\bInheritHandle = 1
sa\lpSecurityDescriptor = 0
if CreatePipe_(@*this\hReadStdOut, @*this\hWriteStdOut, @sa, 0)
if CreatePipe_(@*this\hReadStdErr, @*this\hWwriteStdErr, @sa, 0)
start\cb = SizeOf(STARTUPINFO)
start\dwFlags = #STARTF_USESHOWWINDOW | #STARTF_USESTDHANDLES
start\hStdOutput = *this\hWriteStdOut
if flags & #PROCESS_JOIN_OUTPUT = #PROCESS_JOIN_OUTPUT
start\hStdError = *this\hWriteStdOut
else
start\hStdError = *this\hWwriteStdErr
endif
if CreateProcess_(0, program + " " + commad, @sa, @sa, 1, #NORMAL_PRIORITY_CLASS, 0, 0, @start, @*this\process)
CloseHandle_(*this\hWriteStdOut)
CloseHandle_(*this\hWwriteStdErr)
else ;CreateProcess error
error = -3
endif
else ;pipe error
error = -2
endif
else ;pipe error
error = -1
endif
if *err : *err\i = error : endif
if error=0
procedurereturn *this
else ;error
CloseHandle_(*this\hReadStdErr)
CloseHandle_(*this\hReadStdOut)
CloseHandle_(*this\hWriteStdOut)
CloseHandle_(*this\hWwriteStdErr)
freememory(*this)
procedurereturn #null
endif
endprocedure
procedure proc_CloseProgram(*this.PROCESS_OBJ)
CloseHandle_(*this\process\hProcess)
CloseHandle_(*this\process\hThread)
CloseHandle_(*this\hReadStdErr)
CloseHandle_(*this\hReadStdOut)
freememory(*this)
endprocedure
macro proc_ReadStdOutLine(this)
proc__ReadLine(@this\lastStdChar, @this\dataRead, this\hReadStdOut)
endmacro
macro proc_ReadStdErrLine(this)
proc__ReadLine(@this\lastErrChar, @this\dataRead, this\hReadStdErr)
endmacro
procedure proc_GetExitCode(*this.PROCESS_OBJ)
define.i exitCode
if GetExitCodeProcess_(*this\process\hProcess, @exitCode)
procedurereturn exitCode
endif
endprocedure
macro proc_TerminateProcess(this, exitcode)
TerminateProcess_(this\process\hProcess, exitcode)
endmacro
macro proc_DataRead(this)
this\dataRead
endmacro
procedure.s proc__ReadLine(*lastChar.ASCII, *dataRead.INTEGER, hpipe.i)
define.ASCII achar
define.s text
text = ""
while ReadFile_(hpipe, @achar, sizeof(ASCII), *dataRead, 0)
if achar\a = #CR
*lastChar\a = achar\a
break
elseif achar\a = #LF and *lastChar\a = #CR
*lastChar\a = achar\a
continue
endif
text = text + peeks(@achar, sizeof(ASCII), #PB_Ascii)
*lastChar\a = achar\a
wend
procedurereturn text
endprocedure
Code: Select all
;test
define.s program, cmd, line, text
define.PROCESS_OBJ *proc
define.i prog, counter
program = "c:\lame\lame.exe"
cmd = "--abr 30 --nohist --noreplaygain C:\test.mp3 C:\test_out.mp3"
*proc = proc_RunProgram(program, cmd, 0)
if *proc
counter = 1
line = proc_ReadStdErrLine(*proc)
while proc_DataRead(*proc)
if counter=10
proc_TerminateProcess(*proc, 100)
endif
debug line
line = proc_ReadStdErrLine(*proc)
counter + 1
wend
debug proc_GetExitCode(*proc)
proc_CloseProgram(*proc)
endif
Re: Bug? - ReadProgramString() and unicode
Posted: Wed Apr 21, 2010 9:09 pm
by c4s
Thanks Justin, I'll take a look at it.
Too bad there isn't an easier solution that uses native functions like ReadProgramData() or so.
edit:
Just did a small test and it doesn't seem to work.
Also I'm missing ProgramRunning() and ProgramExitCode().
edit2:
Ok, works...somehow. But ProgramExitCode() is still important for me.

Re: Bug? - ReadProgramString() and unicode
Posted: Wed Apr 21, 2010 11:52 pm
by Justin
There was a bug, when an empty line was found it stopped reading, so you have to use this new method for reading, i added proc_ExitCode() too.
I noticed that the PB process lib can't read the Microsoft mc.exe while these ones works.
edit:code removed use previous include
Re: Bug? - ReadProgramString() and unicode
Posted: Thu Apr 22, 2010 9:11 am
by c4s
Justin, thank you again!
So proc_DataRead() is like ProgramRunning()?
But still not fully satisfying: Now proc_ReadStdErrLine() returns just a big string. It seems like no #LF$ is found although the program normally returns many lines.
(I also could need KillProgram().)
Re: Bug? - ReadProgramString() and unicode
Posted: Sat Apr 24, 2010 10:45 pm
by Justin
From wich program are you reading output?
Re: Bug? - ReadProgramString() and unicode
Posted: Sun Apr 25, 2010 5:48 am
by c4s
It's LAME.exe (the mp3 encoder).
Well searching for enough characters (75) also does the job.
Re: Bug? - ReadProgramString() and unicode
Posted: Sun Apr 25, 2010 10:15 am
by Justin
It seems to work well here, although i just get one error line because i try to convert a non audio file. Is there a way to generate an error with several lines? And using --help works well too.
Re: Bug? - ReadProgramString() and unicode
Posted: Mon Apr 26, 2010 8:16 am
by c4s
Maybe it has to do something with the flags?
For the test I'm using:
--abr 30 --nohist --noreplaygain C:\test.mp3 C:\test_out.mp3
By the way: For ProgramRunning() I'm using this now:
Code: Select all
Procedure ProgramRunning2(*this.PROCESS_OBJ)
Protected State
Protected Result = #False
If GetExitCodeProcess_(*this\process\hProcess, @State)
If State = #STILL_ACTIVE
Result = #True
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Re: Bug? - ReadProgramString() and unicode
Posted: Mon Apr 26, 2010 2:55 pm
by Justin
It seems the progress is shown in a single line although i have not test it, you can try this functions to split the line a show progress. it works here.
edit: code removed use previous include
Re: Bug? - ReadProgramString() and unicode
Posted: Mon Apr 26, 2010 4:07 pm
by c4s
Thanks, I will test it later.
The strange thing for me is that PureBasic is able to split it somehow even though #LF$ isn't send.
edit:
Ok, sure it works. But strange anyway.
Another small question: Does someone know how I can make my own "KillProgram()"?