Консольное приложение никогда не возвращается при запуске с TProcess

Я использую Windows Server 2008 и хочу получить DNS-сервер. Поэтому я подумал, что самым быстрым способом должно быть выполнение ipconfig и последующий анализ его вывода с использованием TProcess.

Я придумал этот код:

  var
  proces : TProcess;
  begin
  ...
  proces := TProcess.Create(nil);
  proces.Executable := 'ipconfig';
  proces.Options := proces.Options + [poWaitOnExit,poUsePipes];
  try
  proces.Execute;
  except
        proces.Free;
  end;
  SetLength(rez,proces.Output.NumBytesAvailable);
  proces.Output.Read(rez[1],proces.Output.NumBytesAvailable);
  ShowMessage(rez);

Код работает, но после того, как я вручную закрываю окно консоли. Я попытался poNoConsole но все тот же результат, процесс ipconfig остается активным в диспетчере задач.

Почему консольное приложение ipconfig не завершается? Если я запускаю его, он завершает работу, выплевывая информацию о stdout.

Это моя конфигурация? Это ошибка? Помогите! Спасибо:)

1 ответ

Решение

Поскольку ipconfig может генерировать много выходных данных, не пытайтесь прочитать их за один раз, используйте метод чтения большого вывода из вики.

Следующая итерация FPC (2.6.2) будет иметь набор процедур runcommand, которые обрабатывают tprocess для ряда общих случаев и возвращают результат в одной строке.

Примечание API-решения также возможны:

{$mode delphi}

uses  JwaIpExport, JwaIpRtrMib, JwaIpTypes,jwawinerror,classes,jwaiphlpapi;

procedure GetDNSServers(AList: TStringList);
var
  pFI: PFixed_Info;
  pIPAddr: PIPAddrString;
  OutLen: Cardinal;
begin
  AList.Clear;
  OutLen := SizeOf(TFixedInfo);
  GetMem(pFI, SizeOf(TFixedInfo));
  try
    if GetNetworkParams(pFI, OutLen) = ERROR_BUFFER_OVERFLOW then
    begin
      ReallocMem(pFI, OutLen);
      if GetNetworkParams(pFI, OutLen) <> NO_ERROR then Exit;
    end;
    // If there is no network available there may be no DNS servers defined
    if pFI^.DnsServerList.IpAddress.s[0] = #0 then Exit;
    // Add first server
    AList.Add(pFI^.DnsServerList.IpAddress.s);
    // Add rest of servers
    pIPAddr := pFI^.DnsServerList.Next;
    while Assigned(pIPAddr) do
    begin
      AList.Add(pIPAddr^.IpAddress.s);
      pIPAddr := pIPAddr^.Next;
    end;
  finally
    FreeMem(pFI);
  end;
end;

var v : TStringList; 
    s : string;
begin
 v:=tstringlist.create;
 getdnsservers(v);
 for s in v do writeln(s);   // this probably requires 2.6+
 v.free;
end.
Другие вопросы по тегам