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 Function Example 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. |