Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Встроить окно cmd в установщик Inno Setup

Delphi , Программа и Интерфейс , Инсталяция

В статье будет рассмотрен вопрос о том, как встроить окно cmd в установщик Inno Setup, чтобы отображать вывод командной строки на пользовательском странице. Это может быть полезно, если вам нужно показать пользователю результат выполнения какой-либо команды во время установки.

Проблема заключается в том, что при использовании функции Exec() в Inno Setup для запуска команды cmd, окно командной строки появляется на экране пользователя, что может быть нежелательно. Решением этой проблемы может быть перенаправление вывода команды в файл и мониторинг изменений в этом файле, чтобы отображать их в элементе управления, таком как ListBox или MemoBox.

Ниже приведен пример кода на Object Pascal (Delphi), который демонстрирует, как это можно сделать:

var
  ProgressPage: TOutputProgressWizardPage;
  ProgressListBox: TNewListBox;

function SetTimer(
  Wnd: LongWord; IDEvent, Elapse: LongWord; TimerFunc: LongWord): LongWord;
  external 'SetTimer@user32.dll stdcall';
function KillTimer(hWnd: LongWord; uIDEvent: LongWord): BOOL;
  external 'KillTimer@user32.dll stdcall';

var
  ProgressFileName: string;

function BufferToAnsi(const Buffer: string): AnsiString;
var
  W: Word;
  I: Integer;
begin
  SetLength(Result, Length(Buffer) * 2);
  for I := 1 to Length(Buffer) do
  begin
    W := Ord(Buffer[I]);
    Result[(I * 2)] := Chr(W shr 8); // high byte
    Result[(I * 2) - 1] := Chr(Byte(W)); // low byte
  end;
end;

procedure UpdateProgress;
var
  S: AnsiString;
  I, L, Max: Integer;
  Buffer: string;
  Stream: TFileStream;
  Lines: TStringList;
begin
  if not FileExists(ProgressFileName) then
  begin
    Log(Format('Progress file %s does not exist', [ProgressFileName]));
  end
    else
  begin
    try
      // Need shared read as the output file is locked for writing,
      // so we cannot use LoadStringFromFile
      Stream :=
        TFileStream.Create(ProgressFileName, fmOpenRead or fmShareDenyNone);
      try
        L := Stream.Size;
        Max := 100*2014;
        if L > Max then
        begin
          Stream.Position := L - Max;
          L := Max;
        end;
        SetLength(Buffer, (L div 2) + (L mod 2));
        Stream.ReadBuffer(Buffer, L);
        S := BufferToAnsi(Buffer);
      finally
        Stream.Free;
      end;
    except
      Log(Format('Failed to read progress from file %s - %s', [
                 ProgressFileName, GetExceptionMessage]));
    end;
  end;

  if S <> '' then
  begin
    Log('Progress len = ' + IntToStr(Length(S)));
    Lines := TStringList.Create();
    Lines.Text := S;
    for I := 0 to Lines.Count - 1 do
    begin
      if I < ProgressListBox.Items.Count then
      begin
        ProgressListBox.Items[I] := Lines[I];
      end
        else
      begin
        ProgressListBox.Items.Add(Lines[I]);
      end
    end;
    ProgressListBox.ItemIndex := ProgressListBox.Items.Count - 1;
    ProgressListBox.Selected[ProgressListBox.ItemIndex] := False;
    Lines.Free;
  end;

  // Just to pump a Windows message queue (maybe not be needed)
  ProgressPage.SetProgress(0, 1);
end;

procedure UpdateProgressProc(
  H: LongWord; Msg: LongWord; Event: LongWord; Time: LongWord);
begin
  UpdateProgress;
end;

procedure BotonIniciarOnClick(Sender: TObject);
var
  ResultCode: Integer;
  Timer: LongWord;
  AppPath: string;
  AppError: string;
  Command: string;
begin
  ProgressPage :=
    CreateOutputProgressPage(
      'Installing something', 'Please wait until this finishes...');
  ProgressPage.Show();
  ProgressListBox := TNewListBox.Create(WizardForm);
  ProgressListBox.Parent := ProgressPage.Surface;
  ProgressListBox.Top := 0;
  ProgressListBox.Left := 0;
  ProgressListBox.Width := ProgressPage.SurfaceWidth;
  ProgressListBox.Height := ProgressPage.SurfaceHeight;

  // Fake SetProgress call in UpdateProgressProc will show it,
  // make sure that user won't see it
  ProgressPage.ProgressBar.Top := -100;

  try
    Timer := SetTimer(0, 0, 250, CreateCallback(@UpdateProgressProc));

    ExtractTemporaryFile('install.bat');
    AppPath := ExpandConstant('{tmp}\install.bat');
    ProgressFileName := ExpandConstant('{tmp}\progress.txt');
    Log(Format('Expecting progress in %s', [ProgressFileName]));
    Command := Format('""%s" > "%s"', [AppPath, ProgressFileName]);
    if not Exec(ExpandConstant('{cmd}'), '/c ' + Command, '', SW_HIDE,
         ewWaitUntilTerminated, ResultCode) then
    begin
      AppError := 'Cannot start app';
    end
      else
    if ResultCode <> 0 then
    begin
      AppError := Format('App failed with code %d', [ResultCode]);
    end;
    UpdateProgress;
  finally
    // Clean up
    KillTimer(0, Timer);
    ProgressPage.Hide;
    DeleteFile(ProgressFileName);
    ProgressPage.Free();
  end;

  if AppError <> '' then
  begin
    // RaiseException does not work properly while
    // TOutputProgressWizardPage is shown
    RaiseException(AppError);
  end;
end;

В этом примере создается страница прогресса с помощью CreateOutputProgressPage(), на которой отображается ProgressListBox. При нажатии кнопки BotonIniciar запускается установщик с помощью функции Exec(), и вывод команды перенаправляется в файл progress.txt. Функция UpdateProgress() мониторит изменения в файле и обновляет ProgressListBox, чтобы отображать вывод команды. Функция UpdateProgressProc() запускается каждые 250 миллисекунд с помощью SetTimer() и вызывает UpdateProgress().

Примечание: Если вам нужно отображать вывод команды в качестве части процесса установки, а не при нажатии кнопки, см. Execute a batch file after installation and display its output on a custom page before Finished page in Inno Setup. Если вам нужно permettre пользователю прервать выполнение команды, см. Create a button on Inno Setup custom wizard page to interrupt an program executed from the installer.

Надеюсь, это поможет вам встроить окно cmd в установщик Inno Setup и отображать вывод команды на пользовательской странице.

Создано по материалам из источника по ссылке.

В статье рассматривается вопрос о том, как встроить окно cmd в установщик Inno Setup, чтобы отображать вывод командной строки на пользовательской странице во время установки.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: Инсталяция ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 12:04:59/0.0055878162384033/1