سؤال

أحتاج إلى تنفيذ أمر Windows "Find" من برنامج Delphi. لقد حاولت استخدام ShellExecute الأمر، لكنه لا يبدو للعمل. في ج، كنت أستخدم system الإجراء، ولكن هنا ... أنا لا أعرف. أود أن أفعل شيئا مثل هذا:

System('find "320" in.txt > out.txt');

تحرير: شكرا للإجابة :) كنت أحاول تشغيل "البحث" كقابل قابل للتنفيذ، وليس كوسيطة ل cmd.exe.

هل كانت مفيدة؟

المحلول

مثال باستخدام ShellExecute():

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShellExecute(0, nil, 'cmd.exe', '/C find "320" in.txt > out.txt', nil, SW_HIDE);
  Sleep(1000);
  Memo1.Lines.LoadFromFile('out.txt');
end;

لاحظ أن استخدام CreateProcess() بدلا من ShellExecute() يسمح للتحكم بشكل أفضل بكثير في العملية.

من الناحية المثالية، ستدعو هذا أيضا في مؤشر ترابط ثانوي، والاتصال WaitForSingleObject() على مقبض العملية لانتظار إكمال العملية. ال Sleep() في المثال هو مجرد اختراق للانتظار بعض الوقت للبرنامج الذي بدأه ShellExecute() لانهاء - ShellExecute() لن تفعل ذلك. إذا لم تستطع على سبيل المثال فتح ما notepad مثيل لتحرير ملف، ShellExecute() من شأنه أن يحظر التطبيق الوالدي حتى تم إغلاق المحرر.

نصائح أخرى

variant1:

سيقوم هذا بتشغيل برنامج "DOS" واسترداد إخراجه:

function GetDosOutput(CommandLine: string; Work: string = 'C:\'): string;  { Run a DOS program and retrieve its output dynamically while it is running. }
var
  SecAtrrs: TSecurityAttributes;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  StdOutPipeRead, StdOutPipeWrite: THandle;
  WasOK: Boolean;
  pCommandLine: array[0..255] of AnsiChar;
  BytesRead: Cardinal;
  WorkDir: string;
  Handle: Boolean;
begin
  Result := '';
  with SecAtrrs do begin
    nLength := SizeOf(SecAtrrs);
    bInheritHandle := True;
    lpSecurityDescriptor := nil;
  end;
  CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SecAtrrs, 0);
  try
    with StartupInfo do
    begin
      FillChar(StartupInfo, SizeOf(StartupInfo), 0);
      cb := SizeOf(StartupInfo);
      dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
      wShowWindow := SW_HIDE;
      hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
      hStdOutput := StdOutPipeWrite;
      hStdError := StdOutPipeWrite;
    end;
    WorkDir := Work;
    Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine),
                            nil, nil, True, 0, nil,
                            PChar(WorkDir), StartupInfo, ProcessInfo);
    CloseHandle(StdOutPipeWrite);
    if Handle then
      try
        repeat
          WasOK := windows.ReadFile(StdOutPipeRead, pCommandLine, 255, BytesRead, nil);
          if BytesRead > 0 then
          begin
            pCommandLine[BytesRead] := #0;
            Result := Result + pCommandLine;
          end;
        until not WasOK or (BytesRead = 0);
        WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
      finally
        CloseHandle(ProcessInfo.hThread);
        CloseHandle(ProcessInfo.hProcess);
      end;
  finally
    CloseHandle(StdOutPipeRead);
  end;
end;

البديل 2:

التقاط إخراج وحدة التحكم في [في الوقت الحقيقي] وكيف في TMEMO:

procedure CaptureConsoleOutput(const ACommand, AParameters: String; AMemo: TMemo);
 const
   CReadBuffer = 2400;
 var
   saSecurity: TSecurityAttributes;
   hRead: THandle;
   hWrite: THandle;
   suiStartup: TStartupInfo;
   piProcess: TProcessInformation;
   pBuffer: array[0..CReadBuffer] of AnsiChar;      <----- update
   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(ACommand + ' ' + AParameters), @saSecurity,
       @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess)
       then
     begin
       repeat
         dRunning  := WaitForSingleObject(piProcess.hProcess, 100);        
         Application.ProcessMessages(); 
         repeat
           dRead := 0;
           ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);          
           pBuffer[dRead] := #0; 

           OemToAnsi(pBuffer, pBuffer);
           AMemo.Lines.Add(String(pBuffer));
         until (dRead < CReadBuffer);      
       until (dRunning <> WAIT_TIMEOUT);
       CloseHandle(piProcess.hProcess);
       CloseHandle(piProcess.hThread);    
     end; 

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

المصدر: Delphi.wikia.com.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top