Есть ли способ запустить "dir" напрямую? - PullRequest
3 голосов
/ 23 марта 2010

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

Ответы [ 4 ]

17 голосов
/ 23 марта 2010

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

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:\'));
3 голосов
/ 23 марта 2010

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

3 голосов
/ 23 марта 2010

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

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 голосов
/ 23 марта 2010

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

sl := TStringList.Create;
if DSiExecuteAndCapture('cmd.exe /c dir', sl, 'c:\test', exitCode) = 0 then
  // exec error
else
  // use sl
sl.Free;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...