当我从命令行编译器 (iscc.exe) 执行 inno 脚本时,如何取得进展?
我可以管道输出,但我也想完成 % 。
改为使用ISCmplr
库。作为灵感,一个非常基本的 Delphi InnoSetup 编译器可能看起来像这样(当然没有硬编码路径)。它使用CompInt.pas
InnoSetup 源包中的原始单元:
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.