2012-02-02 13 views
28

मेरे पास डेल्फी में कोड किया गया एक कमांडलाइन एप्लिकेशन है जिसे मुझे सामान्य डेस्कटॉप एप्लिकेशन (डेल्फी में कोडित) से कॉल करने की आवश्यकता है। संक्षेप में, मैं कमांडलाइन ऐप को कॉल करना चाहता हूं और उस सूची को प्रदर्शित करता हूं जो इसे सूची बॉक्स में "लाइव" आउटपुट करता है।एक शेल/डॉस ऐप से आउटपुट प्राप्त करना डेल्फी ऐप

यह उम्र है क्योंकि मैंने खोल के साथ खेला है, लेकिन मुझे स्पष्ट रूप से याद है कि कमांडलाइन ऐप से टेक्स्ट को पकड़ने के लिए - मुझे पाइप प्रतीक ">" का उपयोग करना होगा। इस तरह:

सी: /mycmdapp.exe> ​​c:

/result.txt यह हर उस पाठ खोल (writeLn उपयोग करते हुए) को मुद्रित लेने के लिए और एक textfile "result.txt" कहा जाता है के लिए यह डंप हो जाएगा।

लेकिन .. (और यहां अचार आता है), मुझे बैकलॉग फ़ाइल की बजाय लाइव परिणाम चाहिए। एक विशिष्ट उदाहरण डेल्फी कंपाइलर स्वयं है - जो आईडीई को वापस रिपोर्ट करने का प्रबंधन करता है। अगर मेरी याददाश्त सही ढंग से मेरी सेवा करती है, तो मुझे याद है कि मुझे एक "पाइप" चैनल (?) बनाना होगा, और उसके बाद पाइप-नाम को खोल कॉल पर असाइन करना होगा।

मैंने इसे Google पर करने का प्रयास किया है, लेकिन मैं ईमानदारी से इसे तैयार करने के बारे में अनिश्चित था। उम्मीद है कि समुदाय से कोई मुझे सही दिशा में इंगित कर सकता है।

अपडेट किया गया: यह प्रश्न How do I run a command-line program in Delphi? के समान हो सकता है। कुछ जवाब जो मैं ढूंढ रहा हूं उसे फिट करता हूं, हालांकि शीर्षक और प्रश्न स्वयं समान नहीं है।

+5

[कंसोल आवेदन धावक क्लासेस] (हिंदुस्तान टाइम्स:

function Execute(const CommandLine: string; OutputLineCallback: TTextHandler; RawOutput: Boolean = False; AbortPtr: PBoolean = nil): Cardinal; 

आप इसे एक कॉलबैक प्रक्रिया के साथ की आपूर्ति कर सकते हैं: लाइब्रेरी) आपको क्या चाहिए होता है tp: //www.delphidabbler.com/software/consoleapp/main? mid = 3.2) - डेल्फी XE2 का उपयोग कर – kobik

+0

Im का वादा करता है (हालांकि मेरे पास डेल्फी 4 और ऊपर से अधिकांश डेल्फी संस्करण हैं)। पहले बड़ी खबरों में से एक नहीं था कि डेल्फी 2010+ एक्सई और एक्सई 2 के साथ बाइनरी संगत है? उस स्थिति में कक्षाओं को काम करना चाहिए। आपके लिए प्रतिक्रिया के लिए बहुत बहुत धन्यवाद! –

+0

@ जोन: नहीं, यह गलत है। डेल्फी कंपाइलर संस्करणों के बीच कोई बाइनरी संगतता नहीं है (डी 6 और डी 7 के बीच एक अपवाद के साथ)। आप स्रोत को पुन: संकलित किए बिना डेल्फी के किसी भी अन्य संस्करण के साथ डी 2010 द्वारा संकलित .dcu फ़ाइलों का उपयोग नहीं कर सकते हैं। –

उत्तर

45

जितनी बार ज़ारको गजिक का समाधान होता है: Capture the output from a DOS (command/console) Window। भविष्य के संदर्भ के लिए यह उनके लेख से एक प्रति है:

उदाहरण 'chkdsk.exe c: \' चलाता है और आउटपुट को मेमो 1 पर प्रदर्शित करता है। अपने फॉर्म पर एक टीएममो (मेमो 1) और एक टीबटन (बटन 1) रखें। Button1 के लिए OnCLick घटना की प्रक्रिया में इस कोड डालें:

procedure RunDosInMemo(DosApp: string; AMemo:TMemo); 
const 
    READ_BUFFER_SIZE = 2400; 
var 
    Security: TSecurityAttributes; 
    readableEndOfPipe, writeableEndOfPipe: THandle; 
    start: TStartUpInfo; 
    ProcessInfo: TProcessInformation; 
    Buffer: PAnsiChar; 
    BytesRead: DWORD; 
    AppRunning: DWORD; 
begin 
    Security.nLength := SizeOf(TSecurityAttributes); 
    Security.bInheritHandle := True; 
    Security.lpSecurityDescriptor := nil; 

    if CreatePipe({var}readableEndOfPipe, {var}writeableEndOfPipe, @Security, 0) then 
    begin 
     Buffer := AllocMem(READ_BUFFER_SIZE+1); 
     FillChar(Start, Sizeof(Start), #0); 
     start.cb := SizeOf(start); 

     // Set up members of the STARTUPINFO structure. 
     // This structure specifies the STDIN and STDOUT handles for redirection. 
     // - Redirect the output and error to the writeable end of our pipe. 
     // - We must still supply a valid StdInput handle (because we used STARTF_USESTDHANDLES to swear that all three handles will be valid) 
     start.dwFlags := start.dwFlags or STARTF_USESTDHANDLES; 
     start.hStdInput := GetStdHandle(STD_INPUT_HANDLE); //we're not redirecting stdInput; but we still have to give it a valid handle 
     start.hStdOutput := writeableEndOfPipe; //we give the writeable end of the pipe to the child process; we read from the readable end 
     start.hStdError := writeableEndOfPipe; 

     //We can also choose to say that the wShowWindow member contains a value. 
     //In our case we want to force the console window to be hidden. 
     start.dwFlags := start.dwFlags + STARTF_USESHOWWINDOW; 
     start.wShowWindow := SW_HIDE; 

     // Don't forget to set up members of the PROCESS_INFORMATION structure. 
     ProcessInfo := Default(TProcessInformation); 

     //WARNING: The unicode version of CreateProcess (CreateProcessW) can modify the command-line "DosApp" string. 
     //Therefore "DosApp" cannot be a pointer to read-only memory, or an ACCESS_VIOLATION will occur. 
     //We can ensure it's not read-only with the RTL function: UniqueString 
     UniqueString({var}DosApp); 

     if CreateProcess(nil, PChar(DosApp), nil, nil, True, NORMAL_PRIORITY_CLASS, nil, nil, start, {var}ProcessInfo) then 
     begin 
      //Wait for the application to terminate, as it writes it's output to the pipe. 
      //WARNING: If the console app outputs more than 2400 bytes (ReadBuffer), 
      //it will block on writing to the pipe and *never* close. 
      repeat 
       Apprunning := WaitForSingleObject(ProcessInfo.hProcess, 100); 
       Application.ProcessMessages; 
      until (Apprunning <> WAIT_TIMEOUT); 

      //Read the contents of the pipe out of the readable end 
      //WARNING: if the console app never writes anything to the StdOutput, then ReadFile will block and never return 
      repeat 
       BytesRead := 0; 
       ReadFile(readableEndOfPipe, Buffer[0], READ_BUFFER_SIZE, {var}BytesRead, nil); 
       Buffer[BytesRead]:= #0; 
       OemToAnsi(Buffer,Buffer); 
       AMemo.Text := AMemo.text + String(Buffer); 
      until (BytesRead < READ_BUFFER_SIZE); 
     end; 
     FreeMem(Buffer); 
     CloseHandle(ProcessInfo.hProcess); 
     CloseHandle(ProcessInfo.hThread); 
     CloseHandle(readableEndOfPipe); 
     CloseHandle(writeableEndOfPipe); 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin {button 1 code} 
    RunDosInMemo('chkdsk.exe c:\',Memo1); 
end; 

अद्यतन: ऊपर के उदाहरण एक ही चरण में उत्पादन पढ़ता है। JCL की JclSysUtils इकाई में Execute समारोह (JEDI कोड:

function GetDosOutput(CommandLine: string; Work: string = 'C:\'): string; 
var 
    SA: TSecurityAttributes; 
    SI: TStartupInfo; 
    PI: TProcessInformation; 
    StdOutPipeRead, StdOutPipeWrite: THandle; 
    WasOK: Boolean; 
    Buffer: array[0..255] of AnsiChar; 
    BytesRead: Cardinal; 
    WorkDir: string; 
    Handle: Boolean; 
begin 
    Result := ''; 
    with SA do begin 
    nLength := SizeOf(SA); 
    bInheritHandle := True; 
    lpSecurityDescriptor := nil; 
    end; 
    CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0); 
    try 
    with SI do 
    begin 
     FillChar(SI, SizeOf(SI), 0); 
     cb := SizeOf(SI); 
     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), SI, PI); 
    CloseHandle(StdOutPipeWrite); 
    if Handle then 
     try 
     repeat 
      WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil); 
      if BytesRead > 0 then 
      begin 
      Buffer[BytesRead] := #0; 
      Result := Result + Buffer; 
      end; 
     until not WasOK or (BytesRead = 0); 
     WaitForSingleObject(PI.hProcess, INFINITE); 
     finally 
     CloseHandle(PI.hThread); 
     CloseHandle(PI.hProcess); 
     end; 
    finally 
    CloseHandle(StdOutPipeRead); 
    end; 
end; 
+0

यह सही है! आपको बहुत - बहुत धन्यवाद! मैंने delphi.about.com की जांच करने के बारे में सोचा नहीं, बहुत बढ़िया! –

+3

@ जोनलेनर्टएसेन्डेन, मैंने एक दूसरा उदाहरण जोड़ा जो बेहतर दृष्टिकोण दिखा रहा है। –

+0

आपका आदमी उवे! धन्यवाद! –

13

आप शायद पहले से ही अपने हार्डडिस्क पर कोड है: यहाँ DelphiDabbler से एक और उदाहरण दिखा कैसे उत्पादन, जबकि प्रक्रिया अभी भी चल रहा है पढ़ा जा सकता है है
TTextHandler = procedure(const Text: string) of object;

संबंधित मुद्दे