Inno设置命令行进度

时间:2013-05-02 14:22:42

标签: delphi inno-setup

当我从命令行编译器(iscc.exe)执行inno脚本时,如何取得进展?

我可以管道输出,但我也想完成%。

1 个答案:

答案 0 :(得分:6)

请改用ISCmplr库。一个灵感,一个非常基本的Delphi InnoSetup编译器可能看起来像这样(当然没有硬编码路径)。它使用InnoSetup源包中的原始CompInt.pas单元:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls, ComCtrls, CompInt;

const
  CompLib = ISCmplrDLL;
  CompPath = 'c:\Program Files (x86)\Inno Setup 5\';
  CompScriptProc = {$IFNDEF UNICODE}'ISDllCompileScript'{$ELSE}'ISDllCompileScriptW'{$ENDIF};

type
  TCompScriptProc = function(const Params: TCompileScriptParamsEx): Integer; stdcall;

  PAppData = ^TAppData;
  TAppData = record
    Lines: TStringList;
    LineNumber: Integer;
    StatusLabel: TLabel;
    ProgressBar: TProgressBar;
  end;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    FCompLibHandle: HMODULE;
    FCompScriptProc: TCompScriptProc;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FCompLibHandle := SafeLoadLibrary(CompPath + CompLib);
  if FCompLibHandle <> 0 then
    FCompScriptProc := GetProcAddress(FCompLibHandle, CompScriptProc);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if FCompLibHandle <> 0 then
    FreeLibrary(FCompLibHandle);
end;

function CompilerCallbackProc(Code: Integer; var Data: TCompilerCallbackData;
  AppData: Longint): Integer; stdcall;
begin
// in every stage you can cancel the compilation if you pass e.g. a Boolean
// field through the AppData by using the following line:
// Result := iscrRequestAbort;

  Result := iscrSuccess;
  case Code of
    iscbReadScript:
    with PAppData(AppData)^ do
    begin
      if Data.Reset then
        LineNumber := 0;
      if LineNumber < Lines.Count then
      begin
        Data.LineRead := PChar(Lines[LineNumber]);
        Inc(LineNumber);
      end;
    end;
    iscbNotifyStatus:
      Form1.Label1.Caption := Data.StatusMsg;
    iscbNotifyIdle:
    begin
      with PAppData(AppData)^ do
      begin
        ProgressBar.Max := Data.CompressProgressMax;
        ProgressBar.Position := Data.CompressProgress;
        StatusLabel.Caption := Format('Bitrate: %d B/s; Remaining time: %d s',
          [Data.BytesCompressedPerSecond, Data.SecondsRemaining]);
        Application.ProcessMessages;
      end;
    end;
    iscbNotifySuccess:
      ShowMessageFmt('Yipee! Compilation succeeded; Output: %s', [Data.OutputExeFilename]);
    iscbNotifyError:
      ShowMessageFmt('An error occured! File: %s; Line: %d; Message: %s', [Data.ErrorFilename,
        Data.ErrorLine, Data.ErrorMsg]);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  CustData: TAppData;
  CompParams: TCompileScriptParamsEx;
begin
  if Assigned(FCompScriptProc) then
  begin
    CustData.Lines := TStringList.Create;
    try
      CustData.Lines.LoadFromFile('c:\Program Files (x86)\Inno Setup 5\Examples\Example1.iss');
      CustData.LineNumber := 0;
      CustData.StatusLabel := Label1;
      CustData.ProgressBar := ProgressBar1;

      CompParams.Size := SizeOf(CompParams);
      CompParams.CompilerPath := CompPath;                                                  // path to the folder containing *.e32 files (InnoSetup install folder)
      CompParams.SourcePath := 'c:\Program Files (x86)\Inno Setup 5\Examples\';             // path to the script file to be compiled
      CompParams.CallbackProc := CompilerCallbackProc;                                      // callback procedure which the compiler calls to read the script and for status notifications
      Pointer(CompParams.AppData) := @CustData;                                             // custom data passed to the callback procedure
      CompParams.Options := '';                                                             // additional options; see CompInt.pas for description

      if FCompScriptProc(CompParams) <> isceNoError then
        ShowMessage('Compiler Error');
    finally
      CustData.Lines.Free;
    end;
  end;
end;

end.