Non-blocking read from stdin

I need a function which returns all data from stdin, but which returns immediately if there is no data waiting.

On Windows I am using the following code, which works very well for me:

Function ReadFromStdIn() As string
  Soft Declare Function GetStdHandle Lib "Kernel32.dll" (nStdHandle as Integer) As Integer
  if hstdin=0 then
  end if
  Soft Declare Function ReadFile Lib "kernel32.dll" (hFile As integer, lpBuffer As ptr, nNumberOfBytesToRead As integer, byref lpNumberOfBytesRead As integer, lpOverlapped As integer) As integer
  Soft Declare Sub CloseHandle Lib "Kernel32.dll" (hobject as Integer)
  Soft Declare Function PeekNamedPipe Lib "kernel32.dll" (hNamedPipe as integer, lpBuffer as integer, nBufferSize as integer, lpBytesRead as integer, byref lpTotalBytesAvail as integer, lpBytesLeftThisMessage as integer) As Integer
  dim bytes_avail,bytes_read as integer
  dim buf as MemoryBlock = ""
  dim status1 as integer = PeekNamedPipe(hstdin,0,0,0,bytes_avail,0)
  if bytes_avail>0 then
    buf=new MemoryBlock(bytes_avail)
    dim status2 as integer = ReadFile(hstdin,buf,buf.size,bytes_read,0)
  end if
  return buf
End Function

The reason for this message is I would like to understand the potential pitfalls of the above code, if any. In particular, I read somewhere that GetStdHandle does not always return an object that can be used with PeekNamedPipe. Can anyone clarify this, such as under what circumstances this can fail?


What’s wrong with StdIn.ReadAll? Does that block on Windows?

Thank you for a very good point.

I neglected to mention that I am trying to achieve this in a GUI app if at all possible.

In any case, I just ran the following code to test StdIn.ReadAll in a Windows Console app:

    dim x as string = stdin.readall
    if x<>"" then
      print x
    end if
    app.DoEvents 500

As far as I can tell, stdin.readall returns empty string always. This occurs when launching the app through a console and typing text into the console. It also occurs when launching the test app through a Xojo Shell in a parent process and sending it data via Shell.WriteLine.

Is the above code missing an essential element?

Instead of printing x, print a string like “found” or something. This exact code works as expected on the Mac so I just want to make sure there isn’t some confusion.

@Thomas - I have no luck with your code, I even set the STD_INPUT to -10.

I’m also trying to have a loop running checking for input data available.
But the console is still blocking any input within this loop.