Конференция "KOL" » CreateProcess() problem
 
  • Kizit (13.09.10 19:14) [0]
    hey guys, i'm having a problem with a custom function. i have the following function working on an usual VCL app:


    procedure RunConv(const ACommand, AParameters: String);
    const
      CReadBuffer = 1200;
    var
      saSecurity: TSecurityAttributes;
      hRead: THandle;
      hWrite: THandle;
      suiStartup: TStartupInfo;
      piProcess: TProcessInformation;
      pBuffer: array[0..CReadBuffer] of AnsiChar;
      dRead: DWord;
      dRunning: DWord;
    begin

      saSecurity.nLength := SizeOf(TSecurityAttributes);
      saSecurity.bInheritHandle := True;
      saSecurity.lpSecurityDescriptor := nil;

      if CreatePipe(hRead, hWrite, @saSecurity, 0) then
      begin
        FillChar(suiStartup, SizeOf(TStartupInfo), #0);
        suiStartup.cb := SizeOf(TStartupInfo);
        suiStartup.hStdInput := hRead;
        suiStartup.hStdOutput := hWrite;
        suiStartup.hStdError := hWrite;
        suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
        suiStartup.wShowWindow := SW_HIDE;

        if CreateProcess(nil, PChar('cmd.exe /C ' + ACommand + ' ' + AParameters), @saSecurity,
          @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess)
          then
        begin
          repeat
            dRunning  := WaitForSingleObject(piProcess.hProcess, 100);
            repeat
              dRead := 0;
              ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
              pBuffer[dRead] := #0;

              OemToAnsi(pBuffer, pBuffer);
              ProcessLine(String(pBuffer));
            until (dRead < CReadBuffer);
          until (dRunning <> WAIT_TIMEOUT);
          ProcessLine('-end-');
          CloseHandle(piProcess.hProcess);
          CloseHandle(piProcess.hThread);
        end
        else
         ShowMessage(':(');

        CloseHandle(hRead);
        CloseHandle(hWrite);
      end;
    end;



    it's purpose is to execute an external console app and returns the output (to be processed in the ProcessLine() procedure), while running. I need it to capture some ongoing processes, and can't wait for them to finish to return the output, so basically normal ExecuteAndWait() or ShellExecute() can't be used.

    Anyway, the same function doesn't work on KOL, or more precisely, CreateProcess() doesn't return true (it triggers ShowMessage()). I changed PChar() to PKOLChar(), but other than that no changes are made.

    any ideas what i can do to fix it ? maybe some issue with CreateProcess() ?

    thank you thank you
  • Jon © (14.09.10 01:32) [1]
    I didn't hae a problem with CreateProcess. What are your compiler conditional defines? This works for me (just minor mods to your code):


    program Test;

    uses
     Windows, KOL;

    var
     ButtonGo, ButtonStop, Memo: PControl;
     StopFlag: Boolean;

    procedure RunConv(const ACommand, AParameters: KOLString);
    const
     CReadBuffer = 1200;
    var
     saSecurity: TSecurityAttributes;
     hRead: THandle;
     hWrite: THandle;
     suiStartup: TStartupInfo;
     piProcess: TProcessInformation;
     pBuffer: array[0..CReadBuffer] of AnsiChar;
     dRead: DWord;
     dRunning: DWord;
    begin
     saSecurity.nLength := SizeOf(TSecurityAttributes);
     saSecurity.bInheritHandle := True;
     saSecurity.lpSecurityDescriptor := nil;
     if CreatePipe(hRead, hWrite, @saSecurity, 0) then
     begin
       FillChar(suiStartup, SizeOf(TStartupInfo), #0);
       suiStartup.cb := SizeOf(TStartupInfo);
       suiStartup.hStdInput := hRead;
       suiStartup.hStdOutput := hWrite;
       suiStartup.hStdError := hWrite;
       suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
       suiStartup.wShowWindow := SW_HIDE;
       if CreateProcess(nil, PKOLChar('cmd.exe /C ' + ACommand + ' ' + AParameters), @saSecurity,
         @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess) then
       begin
         repeat
           dRunning := WaitForSingleObject(piProcess.hProcess, 100);
           repeat
             if PeekNamedPipe(hRead, nil, 0, nil, @dRead, nil) and (dRead > 0) then
             begin
               ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
               pBuffer[dRead] := #0;
               OemToAnsi(pBuffer, pBuffer);
               Memo.Add(AnsiString(pBuffer));
               Applet.Caption := Int2Str(Memo.Count);
               Applet.ProcessMessagesEx;
             end;
           until (dRead < CReadBuffer) or (StopFlag = True);
         until (dRunning <> WAIT_TIMEOUT) or (StopFlag = True);
         Memo.Add('-end-');
         CloseHandle(piProcess.hProcess);
         CloseHandle(piProcess.hThread);
       end
       else
         ShowMessage(':(');
       CloseHandle(hRead);
       CloseHandle(hWrite);
     end;
     StopFlag := False;
     ButtonGo.Enabled := True;
    end;

    procedure ButtonGoClick(Dummy: Pointer; Sender: PControl);
    begin
     ButtonGo.Enabled := False;
     RunConv('dir', '\"%windir%\system32\*.*\" /a/s');
    end;

    procedure ButtonStopClick(Dummy: Pointer; Sender: PControl);
    begin
     StopFlag := True;
    end;

    begin
     Applet := NewForm(nil, 'Test').SetSize(380, 420).CenterOnParent;
     ButtonGo := NewButton(Applet, 'Go');
     ButtonGo.OnClick := TOnEvent(MakeMethod(nil, @ButtonGoClick));
     ButtonStop := NewButton(Applet, 'Stop').PlaceRight;
     ButtonStop.OnClick := TOnEvent(MakeMethod(nil, @ButtonStopClick));
     Memo := NewEditBox(Applet, [eoMultiline]).PlaceDown.SetSize(360, 360);
     Memo.Color := clWindow;
     Run(Applet);
    end.

  • Jon © (14.09.10 01:46) [2]
    Also, don't forget that you may need to terminate the process:


         TerminateProcess(piProcess.hProcess,0);
         CloseHandle(piProcess.hProcess);
         CloseHandle(piProcess.hThread);

 
Конференция "KOL" » CreateProcess() problem
Есть новые Нет новых   [134430   +4][b:0][p:0.003]