views:

85

answers:

1

I use the ShellExecute command to run an exe file which gets an input text file and returns an output text file. I've written it like this:

ShellExecute(mainFormHandle, 'open', 'Test.exe',
    'input.txt output.txt', nil, sw_shownormal);

//Read the output file...
S_List.LoadFromFile('output.txt');
Writeln(S_List[0])

I provide the input.txt file before running this command. In each run of my program, the input file changes and so does the output file.

The problem is this: I can't see the changes in the output file! The line written in the console is from the previous file, not the newly changes one. I mean, the file in the explorer is changed but the file that I read is still the old file.

It seems a little weird, but I was wondering is there any way to refresh the output file before reading it? Or I am missing something here?

Thanks in advance.

+10  A: 

ShellExecute does not wait for your program to finish work. This is what happens:

  • Test.exe starts
  • you read in output.txt
  • Test.exe writes new output.txt

Try something like this:

var
  StartUpInfo : TStartUpInfo;
  ProcessInfo : TProcessInformation;
  CreationFlags : Cardinal;
begin
  FillChar(StartUpInfo, SizeOf(TStartupInfo),0);
  StartupInfo.cb := SizeOf(TStartupInfo);
  CreationFlags := Normal_Priority_Class;

  if CreateProcess(nil, 'test.exe input.txt output.txt',
               nil, nil, False, CreationFlags,
               nil, 0, StartupInfo, ProcessInfo) then
  begin
    WaitforSingleObject(ProcessInfo.HProcess, INFINITE);
    CloseHandle(ProcessInfo.HProcess);

    //Read the output file...
    S_List.LoadFromFile('output.txt');
  end;

With WaitForSingleObject you can wait until a process finishes work.

bepe4711
Thanks for your answer. I put it into my project, but it gives me this exception:First chance exception at $75819617. Exception class EAccessViolation with message 'Access violation at address 75BB9783 in module 'kernel32.dll'. Write of address 004F70C2' Do you have any idea what the problem is? I am completely lost here!
Flom Enol
Delphi 2010 uses the Unicode version of CreateProcess() (aka CreateProcessW()). DO NOT pass string literals to CreateProcessW()! MSDN says that it can modify the input string, which would be very bad (as you have already discovered). You need to assign your literal to a reference-counted String variable first, ie: var S: String; S := 'test.exe input.txt output.txt'; UniqueString(S); if CreateProcess(nil, PChar(S), ...);
Remy Lebeau - TeamB
Thanks a lot Remy! You made my day, man. It worked like a charm! In a million years I wouldn't guess that was the problem! I HATE Delphi's exceptions! I never understand what they mean and refer to.
Flom Enol