bobby wrote:

Michalis Kamburelis wrote:

bobby wrote:

Hi everyone,
I'm stuck with an assignment for my studies.
My assignment is to make a GUI for a disassembler.
Now, the professor want it to be multi-platform (Win32/Linux).

I saw a output-redirection example in Lazarus WIKI (one with memory stream), but the problem is that it's limited to very small amount of data. I don't have a clue how to make it to deal with more amount of data. I've try to clean the memory stream when it's going to be full, but it seems that I didn't do it like it should be done.

The example from wiki is at:
http://wiki.lazarus.freepascal.org/index.php/Executing_External_Programs

Can somebody help me with redirecting the output to SynMemo component? I need it to work on both Win32 and Linux.

As for now, the following lines gives me 106kb (same amount like example from the wiki), but the output should be 800kb (amount of data from 'disasm.exe test.exe > output.txt').

  with TProcess.Create(self) do begin
  Options := [poUsePipes];
  CommandLine := 'disasm.exe test.exe';
  Execute;

  while running do
  begin
       S := TStringList.Create;
       S.LoadFromStream(OutPut);
       for n := 0 to S.Count - 1 do
       SynMemo1.Lines.Add(S[n]);
       S.Free;
  end;

After a lot of experimenting, only clue a got is that the pipes are somehow limited, not the other components. The previous example has proved that the StringLists are not the ones who make that limitation (created and destroyed on every cycle of the loop).
Where is the problem?

Thanks in advance for every clue/advice you can give me.
If someone can give me the example of executing the external file, and redirecting the stdout to text file, also, working on both Win and Lin, that will also solve my problem.


On the page [http://wiki.lazarus.freepascal.org/index.php/Executing_External_Programs] the example "Reading large output" looks suited for reading large data. Are you sure you're using the exact code from this example, and you still don't get the full output ?

In particular, see the section "// read last part" in that example: when program ends, you must read remaining data from the pipe. This is something that is missing from your snippet above: you do

  while running do
  begin
    ... read next chunk from Output ...
  end;

but *after* this loop terminates (when Running = false) you must remember to read the rest of Output. In other words, the process may (and often will) terminate *before* you finished reading the pipe.

Michalis

_________________________________________________________________
    To unsubscribe: mail [EMAIL PROTECTED] with
               "unsubscribe" as the Subject
  archives at http://www.lazarus.freepascal.org/mailarchives

This code gives the same result as the previous code:

begin

  with TProcess.Create(self) do begin
  Options := [poUsePipes];
  CommandLine := 'disasm.exe test.exe';
  Execute;

  while running do
  begin
       S := TStringList.Create;
       S.LoadFromStream(OutPut);
       for n := 0 to S.Count - 1 do
       SynMemo1.Lines.Add(S[n]);
       S.Free;
  end;
       S := TStringList.Create;
       S.LoadFromStream(OutPut);
       for n := 0 to S.Count - 1 do
       SynMemo1.Lines.Add(S[n]);
       S.Free;
 end;
end;

The received data is still 106kb (it should be 800kb). Is there any possibility that the pipe is waiting for some signal /command to resume?

About the example from wiki, the process will never terminate under Win32, and also the writeln commands throws errors. Deleting all writeln commands will make example working, but as I've mentioned, the child process will never terminate, I must close the console window manually.
After doing so, the piped data is also 106kb, and not the expected 800kb.

I am just guessing but doesn't S.LoadFromStream block until the Program exits?

You should create a buffer and a MemoryStream.  then use
var
 Buffer: array [0..2047] of byte;
 MemoryStream: TMemoryStream;
 S: TStringList;
begin
.....
MemoryStream := TMemoryStream.Create;
 while Running  or (DataCount > 0) do begin
   DataCount := Output.Read(Buffer, 2048);
   MemoryStream.Write(Buffer, DataCount);
 end;
 S := TStringList.Create;
 S.LoadFromStream(MemoryStream);
 ...
end;

I am not extremely familiar with how streams work, but using LoadFromStream(Output) may not "Read" the data so it can be replaced with new data. Also as I said I think S.LoadFromStream is blocking until the end of the stream is reached, which can't happen until the program has ended possibly resulting in lost data. Someone please correct me if I am wrong ;)

HTH

Andrew

_________________________________________________________________
    To unsubscribe: mail [EMAIL PROTECTED] with
               "unsubscribe" as the Subject
  archives at http://www.lazarus.freepascal.org/mailarchives

Reply via email to