如何在Inno Setup中获得Exec'ed程序的输出?

32 inno-setup

是否可以获得Exec'ed可执行文件的输出?

我想向用户显示一个信息查询页面,但在输入框中显示MAC地址的默认值.有没有其他方法来实现这一目标?

mgh*_*hie 36

是的,使用标准输出重定向到文件:

[Code]

function NextButtonClick(CurPage: Integer): Boolean;
var
  TmpFileName, ExecStdout: string;
  ResultCode: integer;
begin
  if CurPage = wpWelcome then begin
    TmpFileName := ExpandConstant('{tmp}') + '\ipconfig_results.txt';
    Exec('cmd.exe', '/C ipconfig /ALL > "' + TmpFileName + '"', '', SW_HIDE,
      ewWaitUntilTerminated, ResultCode);
    if LoadStringFromFile(TmpFileName, ExecStdout) then begin
      MsgBox(ExecStdout, mbInformation, MB_OK);
      { do something with contents of file... }
    end;
    DeleteFile(TmpFileName);
  end;
  Result := True;
end;
Run Code Online (Sandbox Code Playgroud)

请注意,可能有多个网络适配器,因此可以选择多个MAC地址.

  • 请注意,不是硬编码"cmd.exe",最好使用`ExpandConstant('{cmd}')`.(当然,最好还是使用正确的API,而不是试图捕获控制台命令的输出,因为后者可能会在没有通知的情况下发生变化,因为它适用于人类.) (4认同)
  • 为了澄清:您需要通过命令提示符运行程序以获取重定向.我最初看了这个答案并且很困惑为什么这对我不起作用,原因是因为我没有意识到重定向是命令提示符而不是windows的函数,所以你需要在cmd.exe/c上执行exec <command> <parameters> (4认同)
  • 对于unicode安装,必须使用:`var ExecStdout:AnsiString;` (2认同)

Tob*_*s81 17

我必须这样做(执行命令行调用并获得结果)并提出了更通用的解决方案.

它还修复了奇怪的错误,如果在实际调用中使用引用路径,则使用/S标志cmd.exe.

{ Exec with output stored in result. }
{ ResultString will only be altered if True is returned. }
function ExecWithResult(const Filename, Params, WorkingDir: String; const ShowCmd: Integer;
  const Wait: TExecWait; var ResultCode: Integer; var ResultString: String): Boolean;
var
  TempFilename: String;
  Command: String;
begin
  TempFilename := ExpandConstant('{tmp}\~execwithresult.txt');
  { Exec via cmd and redirect output to file. Must use special string-behavior to work. }
  Command :=
    Format('"%s" /S /C ""%s" %s > "%s""', [
      ExpandConstant('{cmd}'), Filename, Params, TempFilename]);
  Result := Exec(ExpandConstant('{cmd}'), Command, WorkingDir, ShowCmd, Wait, ResultCode);
  if not Result then
    Exit;
  LoadStringFromFile(TempFilename, ResultString);  { Cannot fail }
  DeleteFile(TempFilename);
  { Remove new-line at the end }
  if (Length(ResultString) >= 2) and (ResultString[Length(ResultString) - 1] = #13) and
     (ResultString[Length(ResultString)] = #10) then
    Delete(ResultString, Length(ResultString) - 1, 2);
end;
Run Code Online (Sandbox Code Playgroud)

用法:

Success :=
  ExecWithResult('ipconfig', '/all', '', SW_HIDE, ewWaitUntilTerminated,
    ResultCode, ExecStdout) or
  (ResultCode <> 0);
Run Code Online (Sandbox Code Playgroud)

结果也可以加载到TStringList对象中以获取所有行:

Lines := TStringList.Create;
Lines.Text := ExecStdout;
{ ... some code ... }
Lines.Free;
Run Code Online (Sandbox Code Playgroud)