2010-03-23 3 views
3

В my answer to this question, где запрашивающему нужен быстрый способ получить список каталогов на сетевом диске, я предложил использовать команду DOS «dir». К сожалению, это команда, а не программа, поэтому вы не можете выполнить ее с помощью CreateProcess, поэтому мне пришлось поместить ее в пакетный файл. Мне не нравится это решение. Мне кажется, что это взломать. Кто-нибудь знает способ запускать dir из Delphi, а не из внешнего командного файла?Есть ли способ запустить «dir» напрямую?

+0

Как использовать командный файл как взломать? Это довольно очевидное решение. – defines

+0

Да, вот почему я так быстро подумал об этом. Но «очевидное решение» не обязательно совпадает с «хорошим решением». –

+0

Кажется, что вы хотите что-то вроде DOS API, который будет принимать команды и возвращать результаты для отображения в любом текстовом поле в вашем приложении или что-то в этом роде, не так ли? – Marcelo

ответ

3

Вам не нужен пакетный файл, вы можете просто выполнить:

cmd.exe /c dir 

Вы можете проверить возможность командовать с cmd /?:

c:> cmd /? 
CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF] 
    [[/S] [/C | /K] string] 

/C Carries out the command specified by string and then terminates 
: : : : : 
+0

Есть ли способ сделать это невидимо? Вызов cmd.exe откроет окно DOS в середине вашего приложения. –

+2

@ Мейсон: См. Ответ Мефа. Хитрость заключается в том, чтобы установить wShowWIndow в SW_HIDE и включить STARTF_USESHOWWINDOW в dwFlags. – gabr

17

Невидимого решение (создать канал, выполните команда, перенаправить stdout на трубу, зачитать трубу):

function Console(const Command: String): String; 
var 
    StartupInfo: TStartupInfo; 
    ProcessInfo: TProcessInformation; 
    SecurityAttr: TSecurityAttributes; 
    OutputPipeRead, OutputPipeWrite: THandle; 
    Res: Boolean; 
    BufSize: Cardinal; 
    Buffer: String; 
    BytesRead: Cardinal; 
begin 
    FillChar(ProcessInfo, SizeOf(TProcessInformation), 0); 

    FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0); 
    SecurityAttr.nLength := SizeOf(SecurityAttr); 
    SecurityAttr.bInheritHandle := true; 
    SecurityAttr.lpSecurityDescriptor := nil; 

    CreatePipe(OutputPipeRead, OutputPipeWrite, @SecurityAttr, 0); 

    FillChar(StartupInfo, SizeOf(TStartupInfo), 0); 
    StartupInfo.cb:=SizeOf(StartupInfo); 
    StartupInfo.hStdInput := 0; 
    StartupInfo.hStdOutput := OutputPipeWrite; 
    StartupInfo.hStdError := OutputPipeWrite; 
    StartupInfo.wShowWindow := SW_HIDE; 
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; 

    Res := CreateProcess(nil, PChar(command), nil, nil, true, 
        CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or 
        NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo); 

    CloseHandle(OutputPipeWrite); 

    Result := ''; 

    if Res then 
    begin 
    SetLength(Buffer, 5000); 
    BufSize := Length(Buffer); 
    repeat 
     Res := ReadFile(OutputPipeRead, Buffer[1], BufSize, BytesRead, nil); 
     Result := Result + Copy(Buffer, 1, BytesRead); 
    until not Res; 

    WaitForSingleObject(ProcessInfo.hProcess, INFINITE); 
    CloseHandle(ProcessInfo.hProcess); 
    end; 

    CloseHandle(OutputPipeRead); 
end; 

Образец использования :

ShowMessage(Console('cmd /c dir C:\')); 
0

Использование DSiWin32:

sl := TStringList.Create; 
if DSiExecuteAndCapture('cmd.exe /c dir', sl, 'c:\test', exitCode) = 0 then 
    // exec error 
else 
    // use sl 
sl.Free; 
3

Почему не FindFirstFile? Он возвращает атрибут для каждого элемента, который можно сравнить с FILE_ATTRIBUTE_DIRECTORY, чтобы проверить каталог. Я очень подозреваю, что dir ничего не делает. Использование команды dir похоже на использование строки на клавиатуре.

+0

Следуя за другим потоком, я думаю, что OP больше интересовался вызовом интерпретатора командной оболочки, а не «dir». –

Смежные вопросы