On 12/9/2011 9:44 AM, tcoq wrote:
Hello,
I'm trying to poll the input stream to see whether there is a new character 
available, without blocking my software.

Maybe TInputPipeStream.NumBytesAvailable can help. You can find it in the documentation of the Pipes unit.

I tried an experiment to make sure it would work. I included the code for the experiment below. It works when stdin is from another process. It does not seem to work if stdin is from the console and I'm not sure why. I tried adding the Windows API call SetConsoleMode(StdInputHandle, 1) to disable line-input mode but it didn't seem to make any difference.

Regarding WaitForSingleObject, there are some comments on the MSDN documentation page regarding the use of this function for console input. In particular, one observation was that if the console is in line-input mode, WaitForSingleObject can return but ReadConsole will still block until a carriage return is entered. Perhaps the same is true for ReadFile. I have not tested this. See:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms687032%28v=vs.85%29.aspx

Code for the test: There are two programs. You can run WriteToPipe to see writing to the stdin stream of one process from another process. You can also test piped input using TestPipes by typing a command like:

type TestPipes.pas | TestPipes

However this does not seem to work:

TestPipes < TestPipes.pas

I don't know why exactly it doesn't appear to work with redirected input from a file or from the console. By the way, I'm using Windows XP Pro 64-bit. Here is the test code.

----- WriteToPipe.pas -----

program WriteToPipe;

{$MODE ObjFpc}

uses
  SysUtils,
  Process,
  Windows;

var
  AProc: TProcess;
  AString: string;
  ACount: Integer;
begin
  WriteLn('This will take about 20 seconds.');
  AProc := TProcess.Create(nil);
  try
    AProc.CommandLine := 'TestPipes.exe';
    AProc.Options := [poUsePipes];
    AProc.Execute;
    try
      for ACount := 0 to 5 do
      begin
        AString := IntToStr(ACount);
        AProc.Input.WriteBuffer(AString[1], Length(AString));
        Sleep (3000);
      end;
    finally
      AProc.Terminate(0);
    end;
  finally
    AProc.Free;
  end;
end.

----- End -----

----- TestPipes.pas -----

program TestPipes;

{$MODE ObjFpc}

uses
  Classes,
  Pipes,
  SysUtils,
  Windows;

var
  AStream: TInputPipeStream;
  AString: string;
  AFile: TextFile;
begin
  Assign(AFile, 'output.txt');
  Rewrite(AFile);
  try
    AStream := TInputPipeStream.Create(StdInputHandle);
    while True do
    begin
      if AStream.NumBytesAvailable > 0 then
      begin
        SetLength(AString, AStream.NumBytesAvailable);
        AStream.ReadBuffer(AString[1], Length(AString));
        WriteLn(AFile, 'I just got this: ', AString);
      end else
      begin
        WriteLn(AFile, 'Waiting...');
        Sleep(1000);
      end;
    end;
  finally
    Close(AFile);
  end;
end.

----- End -----
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to