How do you get pub.freeprocess to read i/o ??
BlitzMax Forums/BlitzMax Programming/How do you get pub.freeprocess to read i/o ??
| ||
| What am I doing wrong here ? Firstly, how do I get it to open the process silently. Secondly, how do I get the process input / ouput ? I tried reading from both the pipes but nothing works. Any help ? Framework brl.standardio
Import pub.freeprocess
Local temp_process:TProcess = CreateProcess("cmd.exe /c ~qipconfig~q")
Local temp_read:String
Print "started"
While temp_process.status()
temp_read = temp_process.pipe.readline()
Print "read = @"+temp_read+"@"
Wend
temp_process.close()
temp_process.terminate()
temp_process = Null
Print "ended" |
| ||
| Hi, First of all, because "ipconfig" is a program in its own right, you don't need to open it with a command prompt. If you wanted to run it manually to check an IP, you would have to use the command prompt as you need a program to catch and display ipconfig's output, however as your program is supposed to catch the output instead, you don't need it. Also, you may want to note that all processes you run are terminated when your blitz app ends, so no need to add this manually (notice the use on OnEnd at the bottom of freeprocess.bmx). The thing to remember is that the pipe field of TProcess can basically be read from and written to exactly like any other stream, as it extends TStream. Hope this helps, Seb |
| ||
| Thanks for the help seb, This is where im having strange issues. Your example (and myn) dont capture anything. The only thing i get from your example is shown below. Any ideas ? IPConfig Status: 1 ================================ ================================ IPConfig Status: 0 ... ? |
| ||
| That's strange... :S I get the following output with my example: What OS are you using? Also, what are the contents of C:\ipconfig.txt when you run ipconfig > "C:\ipconfig.txt" in the Command prompt normally. |
| ||
| My work computer (which im testing this on) is running.. XP pro v 2002 srv pack 2 Windows IP Configuration Ethernet adapter Local Area Connection: Connection-specific DNS Suffix . : IP Address. . . . . . . . . . . . : 10.0.0.42 Subnet Mask . . . . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . . . . : 10.0.0.201 |
| ||
| If it helps... I don't get any output either on W2K. |
| ||
| I'm running Vista and it seems to work fine. I think it might be that the IpConfig terminates immediately after it has output the data, and Pub.FreeProcess won't read anymore data from the stream if the process isn't "alive". The reason for me saying this is that although when I run it, it output information, it is cutting off more lines that you would normally get from the console. Maybe because you have super fast computers, it's cutting it off before it even get's going... Whereas I have loads of virtual adapters on my Vista box that take longer to output. Does this give you any better results? Can you post your output? |
| ||
| Multiple post deleted. Please remove. |
| ||
| Multiple post deleted. Please remove. |
| ||
| Multiple post deleted. Please remove. |
| ||
| Multiple post deleted. Please remove. |
| ||
| Multiple post deleted. Please remove. |
| ||
| Multiple post deleted. Please remove. |
| ||
| Multiple post deleted. Please remove. |
| ||
| Multiple post deleted. Please remove. |
| ||
| It doesn't print anything here either (XP). Your second example does work though. I also had another example using a TTextStream wrapping the Pipe stream, which also works. Just too bad both methods freeze for 10-15 seconds before there is any output :/ EDIT: maybe vista is the source of your "multiple post" problem as well? ;) hehe |
| ||
| LOL - that's really strange. I just posted like I normally do! Hopefully a moderator can clean this little problem up. Anyways, I think the pause could be partly because of the fact that IpConfig seems to output it's title, then gather the info, then output it, and depending on your hardware, it can take a few seconds delay. However, my second method works fine on my end too. I think the idea is to grab all the data that's available when you loop (using ReadPipe() ) as oppose to line by line as it's slower. Also, there is a inbuilt function that converts byte arrays into string, so the whole process can be done on one line: |
| ||
| Your example now works. Now try this: SuperStrict
Framework brl.standardio
Import pub.freeprocess
?Win32
'Lets use OO for the hell of it, although you can use CreateProcess() if you prefer
'There is only 1 flag available - HIDECONSOLE that is supposed to hide console output ;-) but it doesn't make much difference either way on my Windows machine
Local temp_process:TProcess = TProcess.Create("net start THIS_SERVICE_DOESNT_EXIST",HIDECONSOLE)
Print ""
Print "IPConfig Status: " + temp_process.Status() 'Show that the program is running
Print "================================"
While temp_process.Status() 'Checks to see if the process is still running
'Temp variable that stores output from the pipe before it is converted to a string
Local tmpBytes:Byte[]
'Check if the pipe contains any data that hasn't been read and if so, load data into variable array, and convert array to string
If temp_process.pipe.ReadAvail() Then tmpBytes = temp_process.pipe.ReadPipe();Print String.FromBytes( Varptr tmpBytes[0], tmpBytes.length )
Wend
'Terminate process manually (the fact that is has escaped the above loop means it has already closed but put it in as an example)
temp_process.Close()
'This is a quick way you can terminate all processes without bothering to loop through them all (again not needed)
TProcess.TerminateAll()
Print "================================"
Print "IPConfig Status: " + temp_process.Status() 'Show that the program has ended
Print ""
?MacOs
Print "Mac OS X doesn't have IpConfig."
?Linux
Print "Linux doesn't have IpConfig."
?
Why does this not work ??? |
| ||
| Aha! - What you have here is that net.exe wants to output an error, so instead of writing to the normal pipe stream, it outputs to a dedicated error pipe stream... This error stream can be used in exactly the same way as term_process.pipe, except it's term_process.err: Notice the additional line I've added to catch error messages! It's useful that you can separate out error messages from standard output without even having to parse - usually if a process outputs there then this is an important error that would affect the normal output and it can be identified immediately. Sorry I forgot to mention this, I don't think there is anything else you have to look out for. ;-) |
| ||
| You sir are a star! Brill! Saved me some headaches at work tommorow! I think we need to pertition for this to be added to the docs :) |
| ||
| Yep, thanks Seb. Been following this and very informative. |
| ||
| No probs! Glad I can be of some help to someone on these forums! It's usually me asking all the questions. ;-) |
| ||
| Yes, Thanks are due. I think I understand the Readline method a bit better now. (At first I thought it was completely borked, shame on me!). It is non blocking, and sits in front of a 4k buffer. In this case pretty much all the output from these commands is available at once unless as you say it is a slow machine or a lot is going on, so it is buffered immediately and readline starts to work on the buffer, but by that time the process has finished. Fortunately Bufferpos is exposed as a field in TPipeStream so you can check that.
SuperStrict
Framework brl.standardio
Import pub.freeprocess
Local temp_process:TProcess = CreateProcess("ipconfig /?",HIDECONSOLE)
Local temp_read:String, avail:Int
Print "started"
Repeat
' loop until data available. In practice of course you would be doing other things.
Repeat
avail = temp_process.pipe.readavail()
If temp_process.status()=0 Then Exit
Until avail>0
Print "Status "+temp_process.status()
Print "Avail "+avail
If avail=0 Then Exit
' get available data
Repeat
temp_read = temp_process.pipe.readline()
Print temp_process.pipe.bufferpos +" read >"+temp_read
Until temp_process.pipe.bufferpos<=0
Forever
temp_process.close()
temp_process.terminate()
temp_process = Null
Print "ended"
|
| ||
How about this then ,with thanks from all!Import pub.freeprocess
Type tproc Extends TProcess
Method close:Int()
super.close()
terminate()
End Method
Method avail:Int()
Return err.bufferpos Or err.readavail() Or pipe.bufferpos Or pipe.readavail()
End Method
Method read:String()
If err.bufferpos > 0 Or err.readavail() > 0 Return err.ReadLine().Replace("~r","").Replace("~n","")
If pipe.bufferpos > 0 Or pipe.readavail() > 0 Return pipe.ReadLine().Replace("~r","").Replace("~n","")
End Method
Method readpipe:String()
If pipe.bufferpos > 0 Or pipe.readavail() > 0 Return pipe.ReadLine().Replace("~r","").Replace("~n","")
End Method
Method readerr:String()
If err.bufferpos > 0 Or err.readavail() > 0 Return err.ReadLine().Replace("~r","").Replace("~n","")
End Method
Method pipeavail:Int()
Return pipe.bufferpos Or pipe.readavail()
End Method
Method erravail:Int()
Return err.bufferpos Or err.readavail()
End Method
Method Eof:Int()
If status() = 1 Return False
If pipe.readavail() > 0 Return False
If err.readavail() > 0 Return False
If pipe.bufferpos > 0 Return False
If err.bufferpos > 0 Return False
Return True
End Method
Function Create:TProc(ncmd:String,nflags:Int)
Local temp_proc:TProc
Local infd,outfd,errfd
'do mac speciffic stuff
?MacOS
If FileType(ncmd)=2
ncmd :+ "/Contents/MacOS/" + StripExt(StripDir(ncmd))
EndIf
?
'create the proc object
temp_proc = New TProc
'setup the proc
temp_proc.name = ncmd
'attempt to start the process
temp_proc.handle = fdProcess(ncmd,Varptr(infd),Varptr(outfd),Varptr(errfd),nflags)
If Not temp_proc.handle Return Null
'creat teh process pipes
temp_proc.pipe = TPipeStream.Create(infd,outfd)
temp_proc.err = TPipeStream.Create(errfd,0)
'add process to process list
If Not ProcessList ProcessList = New TList
ProcessList.AddLast temp_proc
'return the proc object
Return temp_proc
End Function
End Type
Function CreateProc:tproc(ncmd:String,nhidden:Int = True)
Return tproc.create(ncmd,nhidden)
End FunctionExample 1: Local temp_proc:tproc = CreateProc("net start MOO_MOO_MOO")
While temp_proc.eof() = False
If temp_proc.avail() Print "read: " + temp_proc.read()
Wend
temp_proc.close()Example 2: Local temp_proc:tproc = CreateProc("net start MOO_MOO_MOO")
While temp_proc.eof() = False
If temp_proc.pipeavail() Print "pipe: " + temp_proc.readpipe()
If temp_proc.erravail() Print "err: " + temp_proc.readerr()
Wend
temp_proc.close() |
| ||
| Looks good. You have even implemented the missing EOF method. One for the code archives. |