{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Progress & log page for command line tools ------------------------------ } var CmdlineInstallCancel: Boolean; { ------------------------------ Splitting strings into lines and adding them to TStrings ------------------------------ } procedure StringsAddLine(Dest: TStrings; Line: String; var ReplaceLastLine: Boolean); begin if ReplaceLastLine then begin Dest.Strings[Dest.Count - 1] := Line; ReplaceLastLine := False; end else begin Dest.Add(Line); end; end; procedure StrSplitAppendToList(Text: String; Dest: TStrings; var LastLine: String); var pCR, pLF, Len: Integer; Tmp: String; ReplaceLastLine: Boolean; begin if Length(LastLine) > 0 then begin ReplaceLastLine := True; Text := LastLine + Text; end; repeat Len := Length(Text); pLF := Pos(#10, Text); pCR := Pos(#13, Text); if (pLF > 0) and ((pCR = 0) or (pLF < pCR) or (pLF = pCR + 1)) then begin if pLF < pCR then Tmp := Copy(Text, 1, pLF - 1) else Tmp := Copy(Text, 1, pLF - 2); StringsAddLine(Dest, Tmp, ReplaceLastLine); Text := Copy(Text, pLF + 1, Len) end else begin if (pCR = Len) or (pCR = 0) then begin break; end; Text := Copy(Text, pCR + 1, Len) end; until (pLF = 0) and (pCR = 0); LastLine := Text; if pCR = Len then begin Text := Copy(Text, 1, pCR - 1); end; if Length(LastLine) > 0 then begin StringsAddLine(Dest, Text, ReplaceLastLine); end; end; { ------------------------------ The actual command line install page ------------------------------ } procedure OnCmdlineInstallCancel(Sender: TObject); begin CmdlineInstallCancel := True; end; function DoCmdlineInstall(caption, description, command: String): Boolean; var CmdlineInstallPage: TOutputProgressWizardPage; Res: Integer; Handle: Longword; ExitCode: Integer; LogTextAnsi: AnsiString; LogText, LeftOver: String; Memo: TNewMemo; PrevCancelButtonOnClick: TNotifyEvent; begin CmdlineInstallPage := CreateOutputProgressPage('', '') CmdlineInstallPage.Caption := caption; CmdlineInstallPage.Description := description; Memo := TNewMemo.Create(CmdlineInstallPage); Memo.Top := CmdlineInstallPage.ProgressBar.Top + CmdlineInstallPage.ProgressBar.Height + ScaleY(8); Memo.Width := CmdlineInstallPage.SurfaceWidth; Memo.Height := ScaleY(120); Memo.ScrollBars := ssVertical; Memo.Parent := CmdlineInstallPage.Surface; Memo.Lines.Clear(); CmdlineInstallPage.Show(); try WizardForm.CancelButton.Visible := True; WizardForm.CancelButton.Enabled := True; PrevCancelButtonOnClick := WizardForm.CancelButton.OnClick; WizardForm.CancelButton.OnClick := @OnCmdlineInstallCancel; CmdlineInstallPage.SetProgress(0, 100); CmdlineInstallPage.ProgressBar.Style := npbstMarquee; ExitCode := -1; Memo.Lines.Append('Running command: ' + command); Handle := ProcStart(command, ExpandConstant('{tmp}')) if Handle = 0 then begin Log('ProcStart failed'); ExitCode := -2; end; while (ExitCode = -1) and not CmdlineInstallCancel do begin ExitCode := ProcGetExitCode(Handle); SetLength(LogTextAnsi, 4096); Res := ProcGetOutput(Handle, LogTextAnsi, 4096) if Res > 0 then begin SetLength(LogTextAnsi, Res); LogText := LeftOver + String(LogTextAnsi); StrSplitAppendToList(LogText, Memo.Lines, LeftOver); end; CmdlineInstallPage.SetProgress(0, 100); Sleep(10); end; ProcEnd(Handle); finally Log('Done, exit code=' + IntToStr(ExitCode)); Log('--------'); Log(Memo.Lines.Text); Log('--------'); if CmdlineInstallCancel then begin MsgBox('Installation has been cancelled.', mbError, MB_OK); Result := False; end else if ExitCode <> 0 then begin MsgBox('Installation has failed with exit code ' + IntToStr(ExitCode), mbError, MB_OK); Result := False; end else begin Result := True; end; CmdlineInstallPage.Hide; CmdlineInstallPage.Free; WizardForm.CancelButton.OnClick := PrevCancelButtonOnClick; end; if not Result then RaiseException('Installation has failed at step: ' + caption); end;