Console Applications & StdIN
BlitzMax Forums/BlitzMax Programming/Console Applications & StdIN
| ||
I have a console application that my client has asked me to extend. I've searched the forums investigating all sorts of avenues but the solution continues to evade me. I have seen suggestions to use TCStandardIO and all sorts, but either I'm approaching it incorrectly or these options do not work. The existing application does not have a window, it is a simple command line tool that takes various arguments and produces some results. Nothing special there. What the client wants is the following command line support: c:\app> app -c < control.txt c:\app> type control.txt | app I suggested an argument, but they are paying and thats what they want! To test this I've got this outline code, but if I uncomment the readline() code it waits for CR. I know this is because of the way TextStream is implemented. Print "STDIN" Local stdIN:TStream = ReadStream(StandardIOStream) If stdin Then Print " EOF: " + stdin.Eof() Print " POS: " + stdin.Pos() Print " SIZE: " + stdin.Size() ' Print ReadLine(Stdin) Else Print " Did not open" End If Print "TCSTANDARDIO" Local stdIOStream:TCStandardIO = New TCStandardIO If stdIOStream Then Print " EOF: " + StdIOStream.Eof() Print " POS: " + StdIOStream.pos() Print " SIZE: " + StdIOStream.size() ' Print ReadLine(StdIOStream) Else Print " Did not open" End If Print "object.stdio" Local StdIO:TStream = OpenStream("object.stdio") 'StdIoStream If StdIO Then Print " EOF: " + StdIO.Eof() Print " POS: " + StdIO.pos() Print " SIZE: " + StdIO.size() Else Print " Did not open" End If Is there a way to do this that is not blocking? or should I give up and use API calls? Last edited 2013 |
| ||
Command line tools are fun :-) Non-blocking you can use something like select() to test if there is any new data available on a file descriptor, such as stdin. I'm not sure if ReadByte (or whatever is the lowest-level call) will block or simply return 0 bytes if there is none available. You would need to try it. |
| ||
Readstdin(), Readbyte() and Reafile() all block too, so I went back to the API's. Here is what I came up with, just in case anyone else needs it: WIN32 ONLY SuperStrict '# ENSURE THIS IS NOT COMPILED IN GUI MODE Extern "Win32" Function GetStdHandle:Int( nStdHandle:Int ) Function PeekConsoleInputA( hConsoleInput:Int, lpBuffer:Byte Ptr, nLength:Int, lpNumberOfEventsRead:Int Ptr ) Function ReadFile%( hFile:Int, lpBuffer:Byte Ptr, nNumberOfBytesToRead:Int, lpNumberOfBytesRead:Int Ptr, lpOverlapped:Byte Ptr=Null ) End Extern If TSTDIN.Peek() Then Print TSTDIN.read() Else Print "No stdin data" End If '############################################################ Type TSTDIN Global stdIn% = getStdHandle( -10 ) Global Buffer:Byte[16384] '------------------------------------------------------------ Function Peek:Int() Local rd:Int Return Not peekconsoleinputA( stdIN, Varptr(buffer[0]), 1, Varptr(rd) ) End Function '------------------------------------------------------------ Function Read:String() Local rd:Int If ReadFile( stdin, Varptr(buffer[0]), buffer.length, Varptr(rd), Null ) Then Return String.FromCString( buffer ) Else Return "" End If End Function End Type |
| ||
For non blocking win32 console input I suggest you look at _kbhit() and _getch() documented here: http://msdn.microsoft.com/en-us/library/58w7c94c(v=vs.80).aspx |