Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Автоматическая установка приложений (http://forum.oszone.net/forumdisplay.php?f=61)
-   -   Скрипты Inno Setup. Помощь и советы [часть 9] (http://forum.oszone.net/showthread.php?t=334142)

El Sanchez 04-04-2018 16:09 2807008

Скрипты Inno Setup. Помощь и советы [часть 9]
 
Вложений: 4
Внимание! Данная тема предназначена только для обсуждения написания скриптов!
Остальные вопросы, а также последние версии компилятора в теме
Inno Setup. Прочие вопросы.


Показать/скрыть: Справка, руководство, примеры:

Показать/скрыть: Ссылки на примеры скриптов:

Показать/скрыть: Дополнительные программы для Inno Setup:
  • ISTool - неплохой редактор скриптов Inno Setup.
    Последняя версия: 5.3.0.1 [29.09.2009] - Скачать | зеркало;

  • Inno Script Generator - генератор скриптов Inno Setup. Обладает некоторыми полезными функциями, которых нет ни у самого Inno Setup, ни у ISTool.
    Последняя версия: 1.0.3.1 [23.03.2008] - Скачать | зеркало на русифицированную программу;
    Примечание: Родной сайт www.hisoft2000.de более недоступен, поэтому здесь расположены сторонние ссылки.

  • Inno Setup Form Designer - редактор страниц Inno Setup, можно создавать свои страницы.
    Последняя версия: 2.0.8 [12.11.2006] - Скачать;
    Примечание: Родной сайт http://isfd.kaju74.de/index.php?isfd более недоступен, поэтому здесь расположены сторонние ссылки.

  • Inno Setup GameScript Generator - программа генерирует скрипты для Inno Setup . С помощью GameScript Generator и Inno Setup вы сможете быстро создать простенький инсталляционный пакет для любой игры. В инсталлятор можно встроить музыку, слайдшоу и фоновый рисунок. Для специалистов созданный скрипт, возможно, будет неплохой заготовкой для дальнейшей модернизации;

  • ISSkin - Программа для создания и добавления в инсталлятор скинов. Инструкция.
    Последняя версия: 3.0.0.0 [19.01.2010] - Скачать;

  • ISSJoiner - Программа для объединения нескольких скриптов InnoSetup в один.
    Последняя версия: 3.0 [23.07.2009]

  • Converter - Программа конвертирует reg-файлы в формат *.iss (формат скриптов Inno Setup).
    Последняя версия: 0.1.4 [13.03.2010] - Скачать;

  • RegExporter - Бесплатная утилита для экспорта реестра и конвертации файлов *.reg и *.ini в инсталляционные скрипты Inno Setup и NSIS.
    Последняя версия: 1.3.0 [17.01.2015] - Скачать;



Предыдущие ветки обсуждения по ссылкам ниже и в прикреплённых архивах:

Скрипты Inno Setup. Помощь и советы [часть 6] | Файл 152035
Скрипты Inno Setup. Помощь и советы [часть 7] | Файл 152036
Скрипты Inno Setup. Помощь и советы [часть 8] | Файл 152037

ABBAT 04-04-2018 21:00 2807060

Привет всем. Как можно определить системный диск ({sd}) ssd или hdd.
Что-то вроде этого:
Код:

    if ssd then
        ....
    else
        ....
  end

El Sanchez,
Цитата:

прилипание мастер формы к краям экрана
Отличный скрипт. Спасибо.

Хмм... нашёл пока на AutoIt3 (в.3.3.14.2) подогнал под себя, вроде работает. Может кому пригодится для установки Windows.
Код:

#NoTrayIcon
$Gui = @SW_HIDE

; Some constants
Const $DT_DRIVETYPE = 1
Const $DT_SSDSTATUS = 2
Const $DT_BUSTYPE = 3

; Drive letter to check
Const $DriveLetter = @homedrive;

$ssd = DriveGetType($DriveLetter, $DT_SSDSTATUS)
If $ssd <> "" Then
    Run(@ComSpec & ' /C ssd.bat', '', @SW_HIDE) ;@SW_SHOW
    Else
  Exit
EndIf

Хотелось бы на Inno но... на безрыбье .... )

TheLeon 05-04-2018 20:38 2807267

habib2302,
Цитата:

Из кода удалите строку WizardForm.TypesCombo.Visible := False;. В строке WizardForm.ComponentsList.Top := ScaleX(15); замените на 26 и добавьте эту строку в InitializeWizard WizardForm.TypesCombo.Top := ScaleY(0);
Спасибо, выбор типа установки работает, правда, возникла другая проблема: половину вкладки выбора закрывает задний фон, хотя сделал всё, как вы сказали. Это придётся мне уменьшать размер списка компонентов и превью компонента?
Файл 152052

habib2302 05-04-2018 20:51 2807271

Цитата:

Цитата TheLeon
Это придётся мне уменьшать размер списка компонентов и превью компонента? »

да.

TheLeon 06-04-2018 16:10 2807427

Вложений: 3
habib2302, ещё раз здравствуй, возникла проблема с надписью "Сделано кем-то..." и т.д., с каждым переходом на следующую страницу накладывается слой этого же текста..
Секция CODE
пусто


А также второй вопрос: сделал, как вы сказали, сместил список компонентов и их превью, но все равно половину вкладки выбора типа установки перекрывает. Скорее всего это место было для инструкции, пример: "выберите из списка нужный компонент....", если это так, то можно ли это убрать? Заранее спасибо.

habib2302 06-04-2018 16:49 2807438

Цитата:

Цитата TheLeon
А также второй вопрос: сделал, как вы сказали, сместил список компонентов и их превью, но все равно половину вкладки выбора типа установки перекрывает. Скорее всего это место было для инструкции, пример: "выберите из списка нужный компонент....", если это так, то можно ли это убрать? Заранее спасибо. »

добавьте в InitializeWizard эту строку WizardForm.SelectComponentsLabel.Hide
Цитата:

Цитата TheLeon
возникла проблема с надписью "Сделано кем-то..." и т.д., с каждым переходом на следующую страницу накладывается слой этого же текста.. »

у вас же в примере все понятно расписано.
Код:

Label1 := TLabel.Create(WizardForm);
with Label1 do
begin
Parent := WizardForm;
Caption := 'Сделано в фирме TheLeon';
SetBounds(ScaleX(16),ScaleY(330),ScaleX(132),ScaleY(13));
end;

должен быть в процедуре InitializeWizard, а у вас он каким то образом оказался в функции NextButtonClick и
Код:

Image1 := TBitmapImage.Create(WizardForm);
with Image1 do
begin
Parent := WizardForm.SelectDirPage;
SetBounds(ScaleX(0),ScaleY(110),ScaleX(417),ScaleY(140));
ExtractTemporaryFile('BMP.bmp');
Bitmap.LoadFromFile(ExpandConstant('{tmp}\BMP.bmp'));
end;

и
Код:

  WizardForm.SelectDirBitmapImage.Hide;
  WizardForm.DiskSpaceLabel.Hide;
  WizardForm.SelectDirLabel.SetBounds(ScaleX(0),ScaleY(9),ScaleX(417),ScaleY(14));

тоже должен быть в процедуре InitializeWizard

TheLeon 06-04-2018 18:43 2807458

Вложений: 1
habib2302, обращаюсь ещё раз, всё сделал, но текст не передвинулся, опять накосячил где-то? (см.скрин 1)

P.S: за остальное же спасибо, слепой, что с меня взять...
Секция CODE
пусто

habib2302 06-04-2018 19:16 2807470

Цитата:

Цитата TheLeon
всё сделал, но текст не передвинулся, опять накосячил где-то? »

по поводу текста вы у меня не спрашивали.
вот добавьте это в InitializeWizard
Код:

WizardForm.DirBrowseButton.SetBounds(ScaleX(342),ScaleY(36),ScaleX(75),ScaleY(23));
WizardForm.DirEdit.SetBounds(ScaleX(0),ScaleY(37),ScaleX(332),ScaleY(21));
WizardForm.SelectDirBrowseLabel.SetBounds(ScaleX(0),ScaleY(0),ScaleX(417),ScaleY(27));


TheLeon 07-04-2018 12:39 2807551

Ребят, нужна помощь! Пытался-пытался, не соображаю, как добавить, чтобы при наведении показывалось превью, именно в мой код.

P.S: смотрел статью, опять же пытался - ничего не получилось.
Секция Code

Пусто

habib2302 07-04-2018 19:35 2807627

TheLeon, вот другой вариант. потому что скрипт из этой статьи в виде всплывающего уведомления
Код:

[Setup]
AppName=Моя программа
AppVersion=1.5
AppPublisher=YURSHAT
AppPublisherURL=http://krinkels.org/
DefaultDirName={pf}\Моя программа

[Languages]
Name: "RU"; MessagesFile: "compiler:Languages\Russian.isl"

[CustomMessages]
RU.CompName1=Компонент 1
RU.CompName2=Компонент 2

[Files]
Source: "compiler:WizModernImage.bmp"; DestName: "CompDescImg1.bmp"; Flags: dontcopy
Source: "compiler:WizModernImage-IS.bmp"; DestName: "CompDescImg2.bmp"; Flags: dontcopy

[Types]
Name: full; Description: Full installation; Flags: iscustom

[Components]
Name: comp1; Description: "{cm:CompName1}"; Types: full
Name: comp2; Description: "{cm:CompName2}"; Types: full

[Code]

type
    TComponentDesc = record
    Description: String;
    ImageName: String;
    Index: Integer;
end;

var
  CompDescs: array of TComponentDesc;
  CompDescPanel, CompDescImgPanel: TPanel;
  CompIndex, LastIndex: Integer;
  CompDescImg: TBitmapImage;

procedure ShowCompDescription(Sender: TObject; X, Y, Index: Integer; Area: TItemArea);
var
  i: Integer;
begin
  if Index = LastIndex then Exit;
  CompIndex := -1;
  for i := 0 to GetArrayLength(CompDescs) -1 do
  begin
    if (CompDescs[i].Index = Index) then
    begin
      CompIndex := i;
      Break;
    end;
  end;
  if (CompIndex >= 0) and (Area = iaItem) then
  begin
    if not FileExists(ExpandConstant('{tmp}\') + CompDescs[CompIndex].ImageName) then
      ExtractTemporaryFile(CompDescs[CompIndex].ImageName);
    CompDescImg.Bitmap.LoadFromFile(ExpandConstant('{tmp}\') + CompDescs[CompIndex].ImageName);
    CompDescImg.Show;
  end;
  LastIndex := Index;
end;

procedure CompListMouseLeave(Sender: TObject);
begin
  CompDescImg.Hide;
  LastIndex := -1;
end;

procedure AddCompDescription(AIndex: Integer; ADescription: String; AImageName: String);
var
  i: Integer;
begin
  i := GetArrayLength(CompDescs);
  SetArrayLength(CompDescs, i + 1);
  CompDescs[i].Description := ADescription;
  CompDescs[i].ImageName := AImageName;
  CompDescs[i].Index := AIndex - 1
end;

procedure InitializeWizard();
begin
  WizardForm.SelectComponentsLabel.Hide;
  WizardForm.TypesCombo.Hide;
  WizardForm.ComponentsList.SetBounds(ScaleX(0), ScaleY(0), ScaleX(184), ScaleY(205));
  WizardForm.ComponentsList.OnItemMouseMove:= @ShowCompDescription;
  WizardForm.ComponentsList.OnMouseLeave := @CompListMouseLeave;

  CompDescImgPanel := TPanel.Create(WizardForm);
  with CompDescImgPanel do
  begin
    Parent := WizardForm.SelectComponentsPage;
    SetBounds(ScaleX(192), ScaleY(0), ScaleX(225), ScaleY(205));
    BevelInner := bvLowered;
  end;

  CompDescImg := TBitmapImage.Create(WizardForm);
  with CompDescImg do
  begin
    Parent := CompDescImgPanel;
    SetBounds(ScaleX(5), ScaleY(5), CompDescImgPanel.Width - ScaleX(10), CompDescImgPanel.Height - ScaleY(10));
    Stretch := True;
    Hide;
  end;

  AddCompDescription(1, (''), 'CompDescImg1.bmp');
  AddCompDescription(2, (''), 'CompDescImg2.bmp');
end;


TheLeon 07-04-2018 21:26 2807663

Вложений: 1
habib2302, да, возник вопрос, а можно ли отключить на первом пункте меню изображение, чтобы писалось "Наведите курсор.."?(см.скрин)

Секция code
пусто

habib2302 07-04-2018 21:54 2807665

TheLeon, дайте мне полный скрипт вместе с картинками

habib2302 08-04-2018 00:08 2807678

Цитата:

Цитата TheLeon
да, возник вопрос, а можно ли отключить на первом пункте меню изображение, чтобы писалось "Наведите курсор.."?(см.скрин) »

нет. т.к. в TBitmapImage нельзя добавлять текст. для текста специально предназначена TLabel. Вот полный вариант скрипта
Код:

[Setup]
AppName=Моя программа
AppVersion=1.5
AppPublisher=YURSHAT
AppPublisherURL=http://krinkels.org/
DefaultDirName={pf}\Моя программа

[Languages]
Name: "RU"; MessagesFile: "compiler:Languages\Russian.isl"

[CustomMessages]
RU.CompName1=Компонент 1
RU.CompName2=Компонент 2
RU.ComponentsInfo=Наведите курсор мыши на компонент, чтобы прочитать его описание.
RU.ComponentsImgInfo=Наведите курсор мыши на компонент, чтобы посмотреть его превью.
RU.CompDesc1=Описание первого компонента
RU.CompDesc2=Описание второго компонента

[Files]
Source: "compiler:WizModernImage.bmp"; DestName: "CompDescImg1.bmp"; Flags: dontcopy
Source: "compiler:WizModernImage-IS.bmp"; DestName: "CompDescImg2.bmp"; Flags: dontcopy

[Types]
Name: full; Description: Full installation; Flags: iscustom

[Components]
Name: comp1; Description: "{cm:CompName1}"; Types: full
Name: comp2; Description: "{cm:CompName2}"; Types: full

[Code]
type
  TComponentDesc = record
    Description: String;
    ImageName: String;
    Index: Integer;
  end;

var
  CompDescs: array of TComponentDesc;
  CompDescPanel, CompDescImgPanel: TPanel;
  CompDescText: array[1..2] of TLabel;
  CompIndex, LastIndex: Integer;
  CompDescImg: TBitmapImage;

procedure ShowCompDescription(Sender: TObject; X, Y, Index: Integer; Area: TItemArea);
var
  i: Integer;
begin
  if Index = LastIndex then Exit;
  CompIndex := -1;
  for i := 0 to GetArrayLength(CompDescs) -1 do
  begin
    if (CompDescs[i].Index = Index) then
    begin
      CompIndex := i;
      Break;
    end;
  end;
  if (CompIndex >= 0) and (Area = iaItem) then
  begin
    if not FileExists(ExpandConstant('{tmp}\') + CompDescs[CompIndex].ImageName) then
      ExtractTemporaryFile(CompDescs[CompIndex].ImageName);
    CompDescImg.Bitmap.LoadFromFile(ExpandConstant('{tmp}\') + CompDescs[CompIndex].ImageName);
    CompDescImg.Show;

    CompDescText[2].Caption := CompDescs[CompIndex].Description;
    CompDescText[2].Enabled := True;
  end else
  begin
    CompDescText[2].Caption := CustomMessage('ComponentsInfo');
    CompDescText[2].Enabled := False;
    CompDescImg.Hide;
  end;
  LastIndex := Index;
end;

procedure CompListMouseLeave(Sender: TObject);
begin
  CompDescImg.Hide;
  CompDescText[2].Caption := CustomMessage('ComponentsInfo');
  CompDescText[2].Enabled := False;
  LastIndex := -1;
end;

procedure AddCompDescription(AIndex: Integer; ADescription: String; AImageName: String);
var
  i: Integer;
begin
  i := GetArrayLength(CompDescs);
  SetArrayLength(CompDescs, i + 1);
  CompDescs[i].Description := ADescription;
  CompDescs[i].ImageName := AImageName;
  CompDescs[i].Index := AIndex - 1
end;

procedure InitializeWizard();
begin
  WizardForm.SelectComponentsLabel.Hide;
  WizardForm.TypesCombo.Hide;
  WizardForm.ComponentsList.SetBounds(ScaleX(0), ScaleY(0), ScaleX(184), ScaleY(205));
  WizardForm.ComponentsList.OnItemMouseMove:= @ShowCompDescription;
  WizardForm.ComponentsList.OnMouseLeave := @CompListMouseLeave;

  CompDescImgPanel := TPanel.Create(WizardForm);
  with CompDescImgPanel do
  begin
    Parent := WizardForm.SelectComponentsPage;
    SetBounds(ScaleX(192), ScaleY(0), ScaleX(225), ScaleY(120));
    BevelInner := bvLowered;
  end;

  CompDescText[1] := TLabel.Create(WizardForm);
  with CompDescText[1] do
  begin
    Parent := CompDescImgPanel;
    SetBounds(ScaleX(5), ScaleY(5), CompDescImgPanel.Width - ScaleX(10), CompDescImgPanel.Height - ScaleY(10));
    AutoSize := False;
    WordWrap := True;
    Enabled := False;
    Caption := CustomMessage('ComponentsImgInfo');
  end;

  CompDescImg := TBitmapImage.Create(WizardForm);
  with CompDescImg do
  begin
    Parent := CompDescImgPanel;
    SetBounds(ScaleX(5), ScaleY(5), CompDescImgPanel.Width - ScaleX(10), CompDescImgPanel.Height - ScaleY(10));
    Stretch := True;
    Hide;
  end;

  CompDescPanel := TPanel.Create(WizardForm);
  with CompDescPanel do
  begin
    Parent := WizardForm.SelectComponentsPage;
    SetBounds(ScaleX(192), ScaleY(125), ScaleX(225), ScaleY(80));
    BevelInner := bvLowered;
  end;

  CompDescText[2] := TLabel.Create(WizardForm);
  with CompDescText[2] do
  begin
    Parent := CompDescPanel;
    SetBounds(ScaleX(5), ScaleY(5), CompDescPanel.Width - ScaleX(10), CompDescPanel.Height - ScaleY(10));
    AutoSize := False;
    WordWrap := True;
    Enabled := False;
    Caption := CustomMessage('ComponentsInfo');
  end;

  AddCompDescription(1, CustomMessage('CompDesc1'), 'CompDescImg1.bmp');
  AddCompDescription(2, CustomMessage('CompDesc2'), 'CompDescImg2.bmp');
end;


TheLeon 08-04-2018 12:04 2807726

Вложений: 1
habib2302, тут с описанием компонента, то, что мне не нужно. Да, хотел спросить, можно ли сделать кликабельный баннер и кликабельный текст "сделано в фирме..." (при клике открывался браузер), коды которых вы мне давали?

Секция CODE
пусто

habib2302 08-04-2018 14:17 2807734

Цитата:

Цитата TheLeon
кликабельный текст "сделано в фирме..." (при клике открывался браузер) »

Код:

var
  Label1: TLabel;

procedure Label1Click(Sender: TObject);
var ErrorCode: Integer;
begin
ShellExec('open','http://www.innosetup.com','', '', SW_SHOW, ewNoWait, ErrorCode)
end;

procedure InitializeWizard();
begin
  Label1 := TLabel.Create(WizardForm);
  with Label1 do
  begin
    Parent  := WizardForm;
    Caption := 'Developed by Leon and OSzone.net';
    SetBounds(ScaleX(15),ScaleY(338),ScaleX(132),ScaleY(130));
    Font.Size := 7;
    OnClick:=@Label1Click;
    Font.Color:=clBlue;
    Enabled:=True;
    Cursor:=crHand;
  end;
end;

Цитата:

Цитата TheLeon
кликабельный баннер »

Код:

var
  Image1: TBitmapImage;

procedure Image1Click(Sender: TObject);
var ErrorCode: Integer;
begin
ShellExec('open','http://www.innosetup.com','', '', SW_SHOW, ewNoWait, ErrorCode)
end;

procedure InitializeWizard();
begin
  Image1 := TBitmapImage.Create(WizardForm);
  with Image1 do
  begin
    Parent  := WizardForm.SelectDirPage;
    SetBounds(ScaleX(0),ScaleY(70),ScaleX(416),ScaleY(170));
    ExtractTemporaryFile('BMP.bmp');
    Bitmap.LoadFromFile(ExpandConstant('{tmp}\BMP.bmp'));
    OnClick:=@Image1Click;
    Enabled:=True;
    Cursor:=crHand;
  end;
end;


El Sanchez 08-04-2018 15:28 2807742

Цитата:

Цитата ABBAT
Как можно определить системный диск ({sd}) ssd или hdd. »

ABBAT, пробуйте.
Скрытый текст

Код:

[Setup]
AppName=test
AppVerName=test
CreateAppDir=no
DefaultDirName={tmp}
Uninstallable=no
CreateUninstallRegKey=no

[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl

[Code]
#define A = (Defined UNICODE) ? "W" : "A"
const
 
GENERIC_READ = $80000000;
  GENERIC_WRITE = $40000000;
  FILE_SHARE_READ = $1;
  FILE_SHARE_WRITE = $2;
  OPEN_EXISTING = 3;
  INVALID_HANDLE_VALUE = -1;
  IOCTL_ATA_PASS_THROUGH = $0004D02C;
  ATA_FLAGS_DRDY_REQUIRED = $0001;
  ATA_FLAGS_DATA_IN = $0002;
  ID_CMD = $EC;

type
 
TATAPassThroughEx = record
   
Length: WORD;
    AtaFlags: WORD;
    PathId: Byte;
    TargetId: Byte;
    Lun: Byte;
    ReservedAsUchar: Byte;
    DataTransferLength: DWORD;
    TimeOutValue: DWORD;
    ReservedAsUlong: DWORD;
    DataBufferOffset: DWORD;
    PreviousTaskFile: array [0..7] of Byte;
    CurrentTaskFile: array [0..7] of Byte;
  end;

  TATAIdentifyDeviceQuery = record
   
Header: TATAPassThroughEx;
    Data: array [0..255] of WORD;
  end;

// Device Management Functions
function DeviceIoControlATAIdentifyDeviceQuery(hDevice: THandle; dwIoControlCode: DWORD; var lpInBuffer: TATAIdentifyDeviceQuery; nInBufferSize: DWORD; out lpOutBuffer: TATAIdentifyDeviceQuery; nOutBufferSize: DWORD; out lpBytesReturned: DWORD; lpOverlapped: DWORD): BOOL; external 'DeviceIoControl@kernel32.dll stdcall';

// File Management Functions
function CreateFile(lpFileName: string; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: Longint; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; external 'CreateFile{#A}@kernel32.dll stdcall';

// Handle and Object Functions
function CloseHandle(hObject: THandle): BOOL; external 'CloseHandle@kernel32.dll stdcall';

/////////////////////////////////////////////////////////
function IsDriveSSD(const ADriveLetter: string): Boolean;
var
 
BytesReturned: DWORD;
  DeviceHandle: THandle;
  ATAIdentifyDeviceQuery: TATAIdentifyDeviceQuery;
begin
 
Result := False;
  try
   
DeviceHandle := CreateFile(Format('\\.\%s', [ADriveLetter]), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if DeviceHandle = INVALID_HANDLE_VALUE then
     
RaiseException(SysErrorMessage(DLLGetLastError));

    ATAIdentifyDeviceQuery.Header.Length := SizeOf(ATAIdentifyDeviceQuery.Header);
    ATAIdentifyDeviceQuery.Header.AtaFlags := ATA_FLAGS_DATA_IN or ATA_FLAGS_DRDY_REQUIRED;
    ATAIdentifyDeviceQuery.Header.DataTransferLength := SizeOf(ATAIdentifyDeviceQuery.Data);
    ATAIdentifyDeviceQuery.Header.TimeOutValue := 3;
    ATAIdentifyDeviceQuery.Header.DataBufferOffset := SizeOf(ATAIdentifyDeviceQuery.Header);
    ATAIdentifyDeviceQuery.Header.CurrentTaskFile[6{ = Command/Status register }] := ID_CMD; // ATA IDENTIFY DEVICE command

   
if not DeviceIoControlATAIdentifyDeviceQuery(DeviceHandle, IOCTL_ATA_PASS_THROUGH, ATAIdentifyDeviceQuery, SizeOf(ATAIdentifyDeviceQuery), ATAIdentifyDeviceQuery, SizeOf(ATAIdentifyDeviceQuery), BytesReturned, 0) then
    begin
     
Log(Format('DeviceIoControl failed: %s', [SysErrorMessage(DLLGetLastError)]));
      Exit;
    end;
    Result := ATAIdentifyDeviceQuery.Data[{ Word }217{: Nominal media rotation rate }] = 1;
  finally
    if
DeviceHandle > 0 then
     
CloseHandle(DeviceHandle);
  end;
end;

///////////////////////////
procedure InitializeWizard;
begin
  if
IsDriveSSD(ExpandConstant('{sd}')) then
   
MsgBox('SSD', mbInformation, MB_OK)
  else
   
MsgBox('No SSD', mbInformation, MB_OK);
end;


ABBAT 08-04-2018 21:58 2807801

El Sanchez,
Цитата:

пробуйте
Спасибо большое. Отлично работает.

TheLeon 10-04-2018 19:09 2808169

El Sanchez, здравствуйте, сможете ли помочь с задуманным?

1.Можно ли сделать шапку, похожую на данную, также текст, слева иконка(любого формата), а справа иконка "Вопроса", при наведении на которую, вылезает подсказка? (см.скрин 1)
2.Можно ли сделать анимированный баннер(или слайд-шоу)? (см.скрин 2)
3.Можно ли при наведении, именно на первый пункт, показывало в превью изображения "Наведите курсор..."? (см.скрин 3)
4.Можно ли сделать подобный стиль для кнопок(не меня размеры, просто стиль)? (см.скрин 4)

Скрин 1: https://a.radikal.ru/a05/1804/e9/0e14377bc14b.jpg
Скрин 2: https://d.radikal.ru/d28/1804/c9/5c42c37af7fe.png
Скрин 3: https://d.radikal.ru/d43/1804/92/c9c776c58eaa.png
Скрин 4: https://d.radikal.ru/d26/1804/fa/eaa9c86a90f9.jpg

.ISS
пусто

El Sanchez 11-04-2018 18:12 2808328

Цитата:

Цитата TheLeon
1.Можно ли сделать шапку, похожую на данную, также текст, слева иконка(любого формата), а справа иконка "Вопроса", при наведении на которую, вылезает подсказка? (см.скрин 1) »

TheLeon, пример
Скрытый текст

Код:

[Setup]
AppName=test
AppVerName=test
DefaultDirName={tmp}
Uninstallable=no
CreateUninstallRegKey=no
LicenseFile=compiler:license.txt

[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl

[Messages]
ru.WizardLicense=Сканирование...

[Code]
//////////////////////////
procedure ChangeMainPanel;
var
 
HelpBitmap: TBitmapImage;
begin
 
WizardForm.PageDescriptionLabel.Hide;

  with WizardForm.WizardSmallBitmapImage do
  begin
   
Left := ScaleX(10);
    Top := (Parent.Height - Height) div 2;
  end;

  HelpBitmap := TBitmapImage.Create(WizardForm.MainPanel);
  with HelpBitmap do
  begin
   
Parent := WizardForm.MainPanel;
    Bitmap.LoadFromFile('{#CompilerPath }\WizModernSmallImage-IS.bmp');
    AutoSize := True;
    Left := Parent.Width - Width - ScaleX(10);
    Top := (Parent.Height - Height) div 2;
    ShowHint := True;
    Hint := 'Sample text';
  end;

  with WizardForm.PageNameLabel do
  begin
   
Font.Color := clGray;
    Font.Size := 14;
    Font.Style := [];
    AdjustHeight;
    Left := WizardForm.WizardSmallBitmapImage.Left + WizardForm.WizardSmallBitmapImage.Width + ScaleX(10);
    Top := (Parent.Height - Height) div 2;
    Width := HelpBitmap.Left - Left - ScaleX(10);
  end;
end;

///////////////////////////
procedure InitializeWizard;
begin
 
ChangeMainPanel;
end;


Цитата:

Цитата TheLeon
2.Можно ли сделать анимированный баннер(или слайд-шоу)? (см.скрин 2) »

TheLeon, пример
Скрытый текст

Код:

[Setup]
AppName=test
AppVerName=test
DefaultDirName={tmp}
Uninstallable=no
CreateUninstallRegKey=no

[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl

[Code]
#define A = (Defined UNICODE) ? "W" : "A"
const
 
WS_CHILD = $40000000;
  WS_VISIBLE = $10000000;
  WS_DISABLED = $08000000;

// ATL Functions
function AtlAxWinInit: BOOL; external 'AtlAxWinInit@atl.dll stdcall';
function AtlAxCreateControl(lpszName: string; hWnd: HWND; pStream, ppUnkContainer: Longint): HResult; external 'AtlAxCreateControl@atl.dll stdcall';

// Window Functions
function GetSysColor(nIndex: Integer): DWORD; external 'GetSysColor@user32.dll stdcall';
function CreateWindowEx(dwExStyle: DWORD; lpClassName, lpWindowName: string; dwStyle: DWORD; x, y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: HMENU; hInstance, lpParam: Longint): HWND; external 'CreateWindowEx{#A}@user32.dll stdcall';
function DestroyWindow(hWnd: HWND): BOOL; external 'DestroyWindow@user32.dll stdcall';

var
 
GIFWndHandle: HWND;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function ShowAnimatedGIF(AWndParent: HWND; ALeft, ATop, AWidth, AHeight: Integer; AUrl: string; AColor: TColor): HWND;
(*
Parameters:
  AWndParent...: A handle to the parent window
  ALeft........: The initial horizontal position of the window
  ATop.........: The initial vertical position of the window
  AWidth.......: The width of the window
  AHeight......: The height of the window
  AUrl.........: The URL or full path of the GIF file
  AColor.......: Color background
Return value:
  A handle to ActiveX control host window
*)
var
 
HTMLStr: string;
  ResultCode: HResult;
begin
  if not
AtlAxWinInit then Exit;
  Result := CreateWindowEx(0, 'AtlAxWin', '', WS_CHILD or WS_VISIBLE or WS_DISABLED, ALeft, ATop, AWidth, AHeight, AWndParent, 0, 0, 0);
  if Result = 0 then
   
RaiseException(SysErrorMessage(DLLGetLastError));

  if AColor < 0 then
   
AColor := GetSysColor(AColor and $0000FF);
  HTMLStr := Format('about:<html><body leftmargin="0" topmargin="0" scroll="no" bgcolor="#%.2x%.2x%.2x"><p align="center"><img src="%s" height="100%%"></img></p></body></html>', [AColor and $0000FF, AColor and $00FF00 shr 8, AColor and $FF0000 shr 16, AUrl]);

  ResultCode := AtlAxCreateControl(HTMLStr, Result, 0, 0);
  if ResultCode <> 0 then
   
RaiseException(SysErrorMessage(ResultCode));
end;

///////////////////////////
procedure InitializeWizard;
begin
 
GIFWndHandle := ShowAnimatedGIF(WizardForm.SelectDirPage.Handle,
    0, WizardForm.DirEdit.Top + WizardForm.DirEdit.Height + ScaleY(5), WizardForm.SelectDirPage.Width, WizardForm.DiskSpaceLabel.Top - WizardForm.DirEdit.Top - WizardForm.DirEdit.Height - ScaleY(5),
    'https://media.giphy.com/media/9y0qXExCElAgU/giphy.gif', WizardForm.SelectDirPage.Color);
end;

////////////////////////////
procedure DeinitializeSetup;
begin
  if
GIFWndHandle <> 0 then
   
DestroyWindow(GIFWndHandle);
end;


Цитата:

Цитата TheLeon
3.Можно ли при наведении, именно на первый пункт, показывало в превью изображения "Наведите курсор..."? (см.скрин 3) »

TheLeon, в ShowCompDescription после CompDescImg.Show; дописываете:
Скрытый текст

Код:

if Index = 0 then
 
CompDescText.Caption := 'Наведите курсор...'
else
 
CompDescText.Caption := '';


Цитата:

Цитата TheLeon
4.Можно ли сделать подобный стиль для кнопок(не меня размеры, просто стиль)? (см.скрин 4) »

TheLeon, ISSkin, ISSkinEx, vcl-styles-plugins, SkinSharp.

ROMKA-1977 24-04-2018 21:14 2810531

Здраствуйте, ув. форумчане. Подскажите пож. Возникла следующая проблема:
1. Создана кастомная страница
Код:

var
  Page: TWizardPage;

procedure InitializeWizard();
begin
 Page := CreateCustomPage(wpWelcome, 'ISCustomPage1_Caption', 'ISCustomPage1_Description');
end;

2. Необходимо создать панель расположенную на WizardForm но так чтобы она отображалась только при отображении кастомной страницы.
Код:

var
  Test_pnl: TPanel;

procedure InitializeWizard();
begin
  Test_pnl:= TPanel.Create(WizardForm);
  with Test_pnl do
  begin
    Top:= ScaleY(60);
    Width:= ScaleX(497);
    Height:= ScaleY(253);
    BevelOuter:= bvNone;
    Color := clLime;
    Parent:= WizardForm;
  end;
end;

Со стандартными страницами всё ясно на как быть в таком случае ?

nik1967 25-04-2018 08:06 2810567

ROMKA-1977,
Скрытый текст

Код:

[Setup]
AppName = MyApp
AppVerName = MyApp
DefaultDirname = {pf}\MyApp
OutputDir=.

[code]
var
  Page: TWizardPage;
  Test_pnl: TPanel;

procedure InitializeWizard();
begin
 
Page:= CreateCustomPage(wpWelcome, 'ISCustomPage1_Caption', 'ISCustomPage1_Description');

  Test_pnl:= TPanel.Create(WizardForm);
  with Test_pnl do begin
   
Top:= ScaleY(60);
    Width:= ScaleX(497);
    Height:= ScaleY(253);
    BevelOuter:= bvNone;
    Color:= clLime;
    ParentBackground:= false;
    Parent:= Page.Surface;
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  case
CurPageID of
   
Page.ID: MsgBox('Hello.', mbInformation, MB_OK);
  end;
end;


ROMKA-1977 25-04-2018 13:28 2810630

Вложений: 1
nik1967, в вашем примере панель отображается на кастомной странице. Мне же необходимо создать её на WizardForm но так чтобы она отображалась при кастомной странице, примерно так:
http://forum.oszone.net/attachment.p...1&d=1524651856
Вслучае стандартных страниц я указывал так :

procedure CurPageChanged(CurPageID: Integer);
begin
Test_pnl.Hide;
case CurPageID of
wpInfoBefore: Test_pnl.Show;
end;
end;

Из справки Inno Setup: Значения PageID для определенных ранее страниц мастера
wpWelcome, wpLicense, wpPassword, wpInfoBefore, wpUserInfo, wpSelectDir, wpSelectComponents, wpSelectProgramGroup, wpSelectTasks, wpReady, wpPreparing, wpInstalling, wpInfoAfter, wpFinished

Как же вывести панель на WizardForm только при отображении кастомной страницы ?

nik1967 25-04-2018 13:50 2810637

ROMKA-1977,
Скрытый текст

Код:

[Setup]
AppName = MyApp
AppVerName = MyApp
DefaultDirname = {pf}\MyApp
OutputDir=.

[code]
var
  Page: TWizardPage;
  Test_pnl: TPanel;

procedure InitializeWizard();
begin
 
Page:= CreateCustomPage(wpWelcome, 'ISCustomPage1_Caption', 'ISCustomPage1_Description');

  Test_pnl:= TPanel.Create(WizardForm);
  with Test_pnl do begin
   
Top:= ScaleY(60);
    Width:= ScaleX(497);
    Height:= ScaleY(253);
    BevelOuter:= bvNone;
    Color:= clLime;
    ParentBackground:= false;
    Parent:= WizardForm;
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
 
Test_pnl.Hide;
  case CurPageID of
   
Page.ID: Test_pnl.Show;
  end;
end;


TheLeon 09-05-2018 18:17 2812823

Здравствуйте, уважаемые форумчане OSZone.net.
-
1. Опять нужна ваша помощь в моих безумных идеях. Проще говоря: происходит долгий запуск установщика дополнений на игру, затем, перейдя на страницу выбора компонента(картинки на каждый компонент присутствуют), начинаются дикие тормоза установщика. Я думаю, что скорее всего, это большое кол-во и объём файлов установщика(весит 335 МБ). Если ли какие-нибудь решения по этой ситуации?
-
2. Проблема с установкой дополнений на игру, которая расположена в Program Files, прогресс бар в самом установщике показывает, что идёт установка, но, перейдя в папку игры, после окончания, ничего не изменилось/не добавилось.

Сам скрипт(.iss)

[Setup]
AppName=Vehicles for SpinTires™
AppVersion=1.0
AllowNoIcons=yes
AppPublisher=Leon
DefaultDirName=C:\Program Files (x86)\Spintires
DisableProgramGroupPage=auto
DisableReadyPage=yes
DirExistsWarning=no
DisableWelcomePage=yes
DisableFinishedPage=no
OutputBaseFilename=Vehicles for Spintires
OutputDir=C:\Users\Unknown\Documents\Inno Setup\Examples
LicenseFile=licence.rtf
SetupIconFile=images\SetupIcon.ico
WizardSmallImageFile=images\WizardSmallImage.bmp
WizardImageFile=images\WizardImage.bmp
PrivilegesRequired=admin
Compression=zip/9
InternalCompressLevel=ultra
CompressionThreads=2
SolidCompression=True
CreateUninstallRegKey=no
Uninstallable=no

[Languages]
Name: "RU"; MessagesFile: "Russian.isl"

[Types]
Name: full; Description: Полная установка;
Name: iscustom; Description: Выборочная установка;

[Components]
Name: CAR1; Description: {code:CompHelper|Bentley Continental Supersports}; Types: full;
Name: CAR2; Description: {code:CompHelper|BMW X5 M}; Types: full;
Name: CAR3; Description: {code:CompHelper|Chevrolet Silverado 2500}; Types: full;
Name: CAR4; Description: {code:CompHelper|Fiat Ducato (250)}; Types: full;
Name: CAR5; Description: {code:CompHelper|Ford Raptor Pre-Runner}; Types: full;
Name: CAR6; Description: {code:CompHelper|Hummer H3}; Types: full;
Name: CAR7; Description: {code:CompHelper|Jeep Grand Cherokee}; Types: full;
Name: CAR8; Description: {code:CompHelper|LADA Vesta (ВАЗ-2180)}; Types: full;
Name: CAR9; Description: {code:CompHelper|MAN TGX}; Types: full;
Name: CAR10; Description: {code:CompHelper|Mercedes-Benz G65 AMG}; Types: full;
Name: CAR11; Description: {code:CompHelper|Nissan Pathfinder (R51)}; Types: full;
Name: CAR12; Description: {code:CompHelper|Range Rover Evoque LRX}; Types: full;
Name: CAR13; Description: {code:CompHelper|Range Rover Vogue (L405)}; Types: full;
Name: CAR14; Description: {code:CompHelper|Subaru Impreza STI}; Types: full;
Name: CAR15; Description: {code:CompHelper|Toyota Hilux Tonka Concept 2017}; Types: full;
Name: CAR16; Description: {code:CompHelper|Volkswagen Touareg}; Types: full;
Name: CAR17; Description: {code:CompHelper|Volvo FM}; Types: full;
Name: CAR18; Description: {code:CompHelper|Volvo XC90}; Types: full;
Name: CAR19; Description: {code:CompHelper|ВАЗ 2103 Жигули}; Types: full;
Name: CAR20; Description: {code:CompHelper|ВАЗ-21213 Нива}; Types: full;

[Dirs]
Name: "{app}\Vehicles"; Permissions: everyone-full

[Files]
;------------------------------Bentley Continental Supersports------------------------------
Source: "Files\Bentley Continental Supersports\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR1;
Source: "Files\Bentley Continental Supersports\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR1;
Source: "Files\Bentley Continental Supersports\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR1;
Source: "Files\Bentley Continental Supersports\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR1;
Source: "Files\Bentley Continental Supersports\sounds\engine\bentley_porsche\*"; DestDir: "{app}\Vehicles\sounds\engine\bentley_porsche"; Flags: ignoreversion; Components: CAR1;

;------------------------------------------BMW X5 M-----------------------------------------
Source: "Files\BMW X5 M\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR2;
Source: "Files\BMW X5 M\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR2;
Source: "Files\BMW X5 M\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR2;
Source: "Files\BMW X5 M\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR2;
Source: "Files\BMW X5 M\sounds\*"; DestDir: "{app}\Vehicles\sounds"; Flags: ignoreversion; Components: CAR2;

;---------------------------------Chevrolet Silverado 2500----------------------------------
Source: "Files\Chevrolet Silverado 2500\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR3;
Source: "Files\Chevrolet Silverado 2500\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR3;
Source: "Files\Chevrolet Silverado 2500\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR3;
Source: "Files\Chevrolet Silverado 2500\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR3;
Source: "Files\Chevrolet Silverado 2500\sounds\engine\*"; DestDir: "{app}\Vehicles\sounds\engine"; Flags: ignoreversion; Components: CAR3;
Source: "Files\Chevrolet Silverado 2500\textures\trucks\*"; DestDir: "{app}\Vehicles\textures\trucks"; Flags: ignoreversion; Components: CAR3;

;-------------------------------------Fiat Ducato (250)-------------------------------------
Source: "Files\Fiat Ducato (250)\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR4;
Source: "Files\Fiat Ducato (250)\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR4;
Source: "Files\Fiat Ducato (250)\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR4;
Source: "Files\Fiat Ducato (250)\meshes\trucks\*"; DestDir: "{app}\Vehicles\meshes\trucks"; Flags: ignoreversion; Components: CAR4;
Source: "Files\Fiat Ducato (250)\meshes\wheels\*"; DestDir: "{app}\Vehicles\meshes\wheels"; Flags: ignoreversion; Components: CAR4;
Source: "Files\Fiat Ducato (250)\sounds\mentura\*"; DestDir: "{app}\Vehicles\sounds\mentura"; Flags: ignoreversion; Components: CAR4;
Source: "Files\Fiat Ducato (250)\textures\trucks\police\*"; DestDir: "{app}\Vehicles\textures\trucks\police"; Flags: ignoreversion; Components: CAR4;

;----------------------------------Ford Raptor Pre-Runner-----------------------------------
Source: "Files\Ford Raptor Pre-Runner\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR5;
Source: "Files\Ford Raptor Pre-Runner\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR5;
Source: "Files\Ford Raptor Pre-Runner\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR5;
Source: "Files\Ford Raptor Pre-Runner\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR5;
Source: "Files\Ford Raptor Pre-Runner\sounds\engine\SID-V8\*"; DestDir: "{app}\Vehicles\sounds\engine\SID-V8"; Flags: ignoreversion; Components: CAR5;

;-----------------------------------------Hummer H3-----------------------------------------
Source: "Files\Hummer H3\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR6;
Source: "Files\Hummer H3\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR6;
Source: "Files\Hummer H3\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR6;
Source: "Files\Hummer H3\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR6;
Source: "Files\Hummer H3\sounds\engine\*"; DestDir: "{app}\Vehicles\sounds\engine"; Flags: ignoreversion; Components: CAR6;

;------------------------------------Jeep Grand Cherokee------------------------------------
Source: "Files\Jeep Grand Cherokee\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR7;
Source: "Files\Jeep Grand Cherokee\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR7;
Source: "Files\Jeep Grand Cherokee\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR7;
Source: "Files\Jeep Grand Cherokee\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR7;
Source: "Files\Jeep Grand Cherokee\sounds\engine\V8\*"; DestDir: "{app}\Vehicles\sounds\engine\V8"; Flags: ignoreversion; Components: CAR7;

;-----------------------------------LADA Vesta (ВАЗ-2180)-----------------------------------
Source: "Files\LADA Vesta (ВАЗ-2180)\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR8;
Source: "Files\LADA Vesta (ВАЗ-2180)\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR8;
Source: "Files\LADA Vesta (ВАЗ-2180)\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR8;
Source: "Files\LADA Vesta (ВАЗ-2180)\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR8;
Source: "Files\LADA Vesta (ВАЗ-2180)\sounds\laaadaaa_veeesttas\*"; DestDir: "{app}\Vehicles\sounds\laaadaaa_veeesttas"; Flags: ignoreversion; Components: CAR8;
Source: "Files\LADA Vesta (ВАЗ-2180)\sounds\laaadaaa_veeesttas\niZZmsa\*"; DestDir: "{app}\Vehicles\sounds\laaadaaa_veeesttas\niZZmsa"; Flags: ignoreversion; Components: CAR8;

;-------------------------------------------MAN TGX-----------------------------------------
Source: "Files\MAN TGX\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR9;
Source: "Files\MAN TGX\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR9;
Source: "Files\MAN TGX\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR9;
Source: "Files\MAN TGX\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR9;
Source: "Files\MAN TGX\sounds\*"; DestDir: "{app}\Vehicles\sounds"; Flags: ignoreversion; Components: CAR9;

;-----------------------------------Mercedes-Benz G65 AMG-----------------------------------
Source: "Files\Mercedes-Benz G65 AMG\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR11;
Source: "Files\Mercedes-Benz G65 AMG\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR10;
Source: "Files\Mercedes-Benz G65 AMG\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR10;
Source: "Files\Mercedes-Benz G65 AMG\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR10;
Source: "Files\Mercedes-Benz G65 AMG\meshes\trucks\*"; DestDir: "{app}\Vehicles\meshes\trucks"; Flags: ignoreversion; Components: CAR10;
Source: "Files\Mercedes-Benz G65 AMG\meshes\wheels\*"; DestDir: "{app}\Vehicles\meshes\wheels"; Flags: ignoreversion; Components: CAR10;
Source: "Files\Mercedes-Benz G65 AMG\sounds\*"; DestDir: "{app}\Vehicles\sounds"; Flags: ignoreversion; Components: CAR11;
Source: "Files\Mercedes-Benz G65 AMG\textures\merc_g65\*"; DestDir: "{app}\Vehicles\textures\merc_g65"; Flags: ignoreversion; Components: CAR10;

;-----------------------------------Nissan Pathfinder (R51)---------------------------------
Source: "Files\Nissan Pathfinder (R51)\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR11;
Source: "Files\Nissan Pathfinder (R51)\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR11;
Source: "Files\Nissan Pathfinder (R51)\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR11;
Source: "Files\Nissan Pathfinder (R51)\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR11;
Source: "Files\Nissan Pathfinder (R51)\sounds\engine\V1\*"; DestDir: "{app}\Vehicles\sounds\engine\V1"; Flags: ignoreversion; Components: CAR11;
Source: "Files\Nissan Pathfinder (R51)\sounds\env\*"; DestDir: "{app}\Vehicles\sounds\env"; Flags: ignoreversion; Components: CAR11;

;-----------------------------------Range Rover Evoque LRX----------------------------------
Source: "Files\Range Rover Evoque LRX\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR12;
Source: "Files\Range Rover Evoque LRX\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR12;
Source: "Files\Range Rover Evoque LRX\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR12;
Source: "Files\Range Rover Evoque LRX\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR12;
Source: "Files\Range Rover Evoque LRX\sounds\engine\*"; DestDir: "{app}\Vehicles\sounds\engine"; Flags: ignoreversion; Components: CAR12;

;---------------------------------Range Rover Vogue (L405)----------------------------------
Source: "Files\Range Rover Vogue (L405)\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR13;
Source: "Files\Range Rover Vogue (L405)\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR13;
Source: "Files\Range Rover Vogue (L405)\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR13;
Source: "Files\Range Rover Vogue (L405)\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR13;
Source: "Files\Range Rover Vogue (L405)\sounds\*"; DestDir: "{app}\Vehicles\sounds"; Flags: ignoreversion; Components: CAR13;

;------------------------------------Subaru Impreza STI-------------------------------------
Source: "Files\Subaru Impreza STI\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR14;
Source: "Files\Subaru Impreza STI\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR14;
Source: "Files\Subaru Impreza STI\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR14;
Source: "Files\Subaru Impreza STI\meshes\trucks\*"; DestDir: "{app}\Vehicles\meshes\trucks"; Flags: ignoreversion; Components: CAR14;
Source: "Files\Subaru Impreza STI\meshes\wheels\*"; DestDir: "{app}\Vehicles\meshes\wheels"; Flags: ignoreversion; Components: CAR14;
Source: "Files\Subaru Impreza STI\sounds\enginesti\*"; DestDir: "{app}\Vehicles\sounds\enginesti"; Flags: ignoreversion; Components: CAR14;
Source: "Files\Subaru Impreza STI\textures\*"; DestDir: "{app}\Vehicles\textures"; Flags: ignoreversion; Components: CAR14;
Source: "Files\Subaru Impreza STI\textures\sti\*"; DestDir: "{app}\Vehicles\textures\sti"; Flags: ignoreversion; Components: CAR14;
Source: "Files\Subaru Impreza STI\textures\sub\*"; DestDir: "{app}\Vehicles\textures\sub"; Flags: ignoreversion; Components: CAR14;
Source: "Files\Subaru Impreza STI\textures\wh1\*"; DestDir: "{app}\Vehicles\textures\wh1"; Flags: ignoreversion; Components: CAR14;

;------------------------------Toyota Hilux Tonka Concept 2017------------------------------
Source: "Files\Toyota Hilux Tonka Concept 2017\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR15;
Source: "Files\Toyota Hilux Tonka Concept 2017\_templates\*"; DestDir: "{app}\Vehicles\_templates"; Flags: ignoreversion; Components: CAR15;
Source: "Files\Toyota Hilux Tonka Concept 2017\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR15;
Source: "Files\Toyota Hilux Tonka Concept 2017\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR15;
Source: "Files\Toyota Hilux Tonka Concept 2017\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR15;
Source: "Files\Toyota Hilux Tonka Concept 2017\sounds\*"; DestDir: "{app}\Vehicles\sounds"; Flags: ignoreversion; Components: CAR15;
Source: "Files\Toyota Hilux Tonka Concept 2017\sounds\engine\*"; DestDir: "{app}\Vehicles\sounds\engine"; Flags: ignoreversion; Components: CAR15;
Source: "Files\Toyota Hilux Tonka Concept 2017\sounds\env\*"; DestDir: "{app}\Vehicles\sounds\env"; Flags: ignoreversion; Components: CAR15;
Source: "Files\Toyota Hilux Tonka Concept 2017\sounds\truck\*"; DestDir: "{app}\Vehicles\sounds\truck"; Flags: ignoreversion; Components: CAR15;
Source: "Files\Toyota Hilux Tonka Concept 2017\sounds\engine\V1\*"; DestDir: "{app}\Vehicles\sounds\engine\V1"; Flags: ignoreversion; Components: CAR15;

;------------------------------------Volkswagen Touareg-------------------------------------
Source: "Files\Volkswagen Touareg\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR16;
Source: "Files\Volkswagen Touareg\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR16;
Source: "Files\Volkswagen Touareg\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR16;
Source: "Files\Volkswagen Touareg\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR16;
Source: "Files\Volkswagen Touareg\sounds\*"; DestDir: "{app}\Vehicles\sounds"; Flags: ignoreversion; Components: CAR16;

;------------------------------------------Volvo FM-----------------------------------------
Source: "Files\Volvo FM\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR17;
Source: "Files\Volvo FM\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR17;
Source: "Files\Volvo FM\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR17;
Source: "Files\Volvo FM\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR17;
Source: "Files\Volvo FM\sounds\*"; DestDir: "{app}\Vehicles\sounds"; Flags: ignoreversion; Components: CAR17;

;-----------------------------------------Volvo XC90----------------------------------------
Source: "Files\Volvo XC90\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR18;
Source: "Files\Volvo XC90\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR18;
Source: "Files\Volvo XC90\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR18;
Source: "Files\Volvo XC90\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR18;
Source: "Files\Volvo XC90\sounds\*"; DestDir: "{app}\Vehicles\sounds"; Flags: ignoreversion; Components: CAR18;

;--------------------------------------ВАЗ 2103 Жигули--------------------------------------
Source: "Files\ВАЗ 2103 Жигули\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR19;
Source: "Files\ВАЗ 2103 Жигули\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR19;
Source: "Files\ВАЗ 2103 Жигули\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR19;
Source: "Files\ВАЗ 2103 Жигули\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR19;
Source: "Files\ВАЗ 2103 Жигули\sounds\LADA1500_nEw\*"; DestDir: "{app}\Vehicles\sounds\LADA1500_nEw"; Flags: ignoreversion; Components: CAR19;

;--------------------------------------Нива (ВАЗ-21213)-------------------------------------
Source: "Files\Нива (ВАЗ-21213)\*"; DestDir: "{app}\Vehicles"; Flags: ignoreversion; Components: CAR20;
Source: "Files\Нива (ВАЗ-21213)\billboards\trucks\*"; DestDir: "{app}\Vehicles\billboards\trucks"; Flags: ignoreversion; Components: CAR20;
Source: "Files\Нива (ВАЗ-21213)\classes\trucks\*"; DestDir: "{app}\Vehicles\classes\trucks"; Flags: ignoreversion; Components: CAR20;
Source: "Files\Нива (ВАЗ-21213)\classes\wheels\*"; DestDir: "{app}\Vehicles\classes\wheels"; Flags: ignoreversion; Components: CAR20;
Source: "Files\Нива (ВАЗ-21213)\sounds\2106\*"; DestDir: "{app}\Vehicles\sounds\2106"; Flags: ignoreversion; Components: CAR20;

;----------------------------------------Русификатор----------------------------------------
Source: "Files\translate\strings\ru\*"; DestDir: "{app}\Vehicles\strings\ru"; Flags: ignoreversion;

;--------------------------------------Временные файлы--------------------------------------
Source: "images\ad.bmp"; DestDir: "{tmp}"; Flags: dontcopy
Source: "images\vehicles\*"; DestDir: "{tmp}"; Flags: dontcopy

[code]
type
TComponentDesc = record
Description: String;
ImageName: String;
Index: Integer;
end;
var
ComponentsInfoImage: TBitmapImage;
ComponentHelper: TStringList;
CompDescText: TLabel;
Image1: TBitmapImage;
DelTmp: TNewCheckBox;
function CompHelper(Param: string): string;
var
Image: TBitmap;
Index: Integer;
begin
Result := '';
with TStringList.Create do
try
StringChangeEx(Param, '|', #13#10, True);
Text := Param;
if Count = 0 then Exit;
if Count > 0 then
Index := ComponentHelper.Add(Strings[0]);
if Count > 1 then
begin
if not FileExists(ExpandConstant('{tmp}\') + Strings[1]) then
ExtractTemporaryFile(Strings[1]);
Image := TBitmap.Create;
Image.LoadFromFile(ExpandConstant('{tmp}\') + Strings[1]);
ComponentHelper.Objects[Index] := Image;
end;
Result := ComponentHelper[Index];
finally
Free;
end;
end;

function DelTmpCheck(): boolean;
begin
result := DelTmp.Checked;
end;

procedure ComponentsListClickCheck(Sender: TObject);
begin
if not Assigned(Sender) or (TNewCheckListBox(Sender).ItemIndex = -1) then Exit;
ComponentsInfoImage.Bitmap.Assign(TBitmap(ComponentHelper.Objects[TNewCheckListBox(Sender).ItemIndex]));
end;

function InitializeSetup(): Boolean;
begin
Result := True;
ComponentHelper := TStringList.Create;
ComponentHelper.Duplicates := dupIgnore;
end;

var
CheckLicense: TCheckBox;

procedure LicenseOnClick(Sender: TObject);
begin
if (CheckLicense.Checked) = True then
begin
WizardForm.LicenseAcceptedRadio.Checked := True;
end else
begin
WizardForm.LicenseNotAcceptedRadio.Checked := True;
end;
end;

var
CompDescs: array of TComponentDesc;
CompDescImgPanel: TPanel;
CompIndex, LastIndex: Integer;
CompDescImg: TBitmapImage;

procedure ShowCompDescription(Sender: TObject; X, Y, Index: Integer; Area: TItemArea);
var
i: Integer;
begin
if Index = LastIndex then Exit;
CompIndex := -1;
for i := 0 to GetArrayLength(CompDescs) -1 do
begin
if (CompDescs[i].Index = Index) then
begin
CompIndex := i;
Break;
end;
end;
if (CompIndex >= 0) and (Area = iaItem) then
begin
if not FileExists(ExpandConstant('{tmp}\') + CompDescs[CompIndex].ImageName) then
ExtractTemporaryFile(CompDescs[CompIndex].ImageName);
CompDescImg.Bitmap.LoadFromFile(ExpandConstant('{tmp}\') + CompDescs[CompIndex].ImageName);
CompDescImg.Show;
if Index = 0 then
CompDescText.Caption := 'Наведите курсор мыши на компонент, чтобы посмотреть его превью.';
end;
LastIndex := Index;
end;

procedure CompListMouseLeave(Sender: TObject);
begin
CompDescImg.Hide;
LastIndex := -1;
end;

procedure AddCompDescription(AIndex: Integer; ADescription: String; AImageName: String);
var
i: Integer;
begin
i := GetArrayLength(CompDescs);
SetArrayLength(CompDescs, i + 1);
CompDescs[i].Description := ADescription;
CompDescs[i].ImageName := AImageName;
CompDescs[i].Index := AIndex - 1
end;

procedure Image1Click(Sender: TObject);
var ErrorCode: Integer;
begin
ShellExec('open','https://www.nssro.ga','', '', SW_SHOW, ewNoWait, ErrorCode)
end;

procedure InitializeWizard();
var
i: Integer;
begin
WizardForm.SelectComponentsLabel.Hide;
WizardForm.SelectDirBitmapImage.Hide;
WizardForm.DiskSpaceLabel.Hide;
WizardForm.DirBrowseButton.SetBounds(ScaleX(342),ScaleY(39),ScaleX(75),ScaleY(22));
WizardForm.DirEdit.SetBounds(ScaleX(0),ScaleY(40),ScaleX(332),ScaleY(20));
WizardForm.SelectDirBrowseLabel.SetBounds(ScaleX(0),ScaleY(13),ScaleX(417),ScaleY(27));
WizardForm.SelectDirLabel.SetBounds(ScaleX(0),ScaleY(1),ScaleX(417),ScaleY(14));
WizardForm.TypesCombo.Top := ScaleY(0)
WizardForm.ComponentsList.OnItemMouseMove:= @ShowCompDescription;
WizardForm.ComponentsList.OnMouseLeave := @CompListMouseLeave;
WizardForm.ComponentsList.Visible := True;
WizardForm.ComponentsList.Height := ScaleX(204);
WizardForm.ComponentsList.Top := ScaleX(31);
WizardForm.ComponentsList.Width := ScaleX(200);
for i := 0 to WizardForm.ComponentsList.Items.Count - 1 do
if not WizardForm.ComponentsList.ItemEnabled[i] then
WizardForm.ComponentsList.ItemSubItem[i] := '';
WizardForm.ComponentsDiskSpaceLabel.Visible := True;
WizardForm.LicenseNotAcceptedRadio.Hide;
WizardForm.LicenseAcceptedRadio.Hide;
WizardForm.LicenseMemo.Height := ScaleY(175);

DelTmp := TNewCheckBox.Create(WizardForm);
DelTmp.Parent := WizardForm.FinishedPage;
DelTmp.Caption := 'Удалить временные файлы';
DelTmp.Left := ScaleX(180);
DelTmp.Top := ScaleY(207);
DelTmp.Width := ScaleX(300);
DelTmp.Height := ScaleY(15);;
DelTmp.Checked := true;

CheckLicense:= TCheckBox.Create(WizardForm);
CheckLicense.Left:= ScaleX(0);
CheckLicense.Top:= ScaleY(216);
CheckLicense.Caption:= WizardForm.LicenseAcceptedRadio.Caption;
CheckLicense.Width:= ScaleX(417);
CheckLicense.OnClick:= @LicenseOnClick;
CheckLicense.Parent:= WizardForm.LicensePage;

Image1 := TBitmapImage.Create(WizardForm);
with Image1 do
begin
Parent := WizardForm.SelectDirPage;
SetBounds(ScaleX(0),ScaleY(70),ScaleX(416),ScaleY(170));
ExtractTemporaryFile('ad.bmp');
Bitmap.LoadFromFile(ExpandConstant('{tmp}\ad.bmp'));
OnClick:=@Image1Click;
Enabled:=True;
Cursor:=crHand;
end;

CompDescImgPanel := TPanel.Create(WizardForm);
with CompDescImgPanel do
begin
Parent := WizardForm.SelectComponentsPage;
SetBounds(ScaleX(212), ScaleY(30), ScaleX(205), ScaleY(205));
BevelInner := bvLowered;
end;

CompDescText := TLabel.Create(WizardForm);
with CompDescText do
begin
Parent := CompDescImgPanel;
SetBounds(ScaleX(5), ScaleY(5), CompDescImgPanel.Width - ScaleX(10), CompDescImgPanel.Height - ScaleY(10));
AutoSize := False;
WordWrap := True;
Enabled := False;
Caption := 'Наведите курсор мыши на компонент, чтобы посмотреть его превью.';
end;

CompDescImg := TBitmapImage.Create(WizardForm);
with CompDescImg do
begin
Parent := CompDescImgPanel;
SetBounds(ScaleX(4), ScaleY(4), CompDescImgPanel.Width - ScaleX(7), CompDescImgPanel.Height - ScaleY(7));
Stretch := True;
Hide;
end;
AddCompDescription(1, (''), 'car1.bmp');
AddCompDescription(2, (''), 'car2.bmp');
AddCompDescription(3, (''), 'car3.bmp');
AddCompDescription(4, (''), 'car4.bmp');
AddCompDescription(5, (''), 'car5.bmp');
AddCompDescription(6, (''), 'car6.bmp');
AddCompDescription(7, (''), 'car7.bmp');
AddCompDescription(8, (''), 'car8.bmp');
AddCompDescription(9, (''), 'car9.bmp');
AddCompDescription(10, (''), 'car10.bmp');
AddCompDescription(11, (''), 'car11.bmp');
AddCompDescription(12, (''), 'car12.bmp');
AddCompDescription(13, (''), 'car13.bmp');
AddCompDescription(14, (''), 'car14.bmp');
AddCompDescription(15, (''), 'car15.bmp');
AddCompDescription(16, (''), 'car16.bmp');
AddCompDescription(17, (''), 'car17.bmp');
AddCompDescription(18, (''), 'car18.bmp');
AddCompDescription(19, (''), 'car19.bmp');
AddCompDescription(20, (''), 'car20.bmp');
end;

procedure CurPageChanged(CurPageID: Integer);
begin
case CurPageID of
wpSelectComponents: ComponentsListClickCheck(nil);
end;
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
case CurStep of
ssDone:
begin
if DelTmpCheck then
begin
DelTree(ExpandConstant('{localappdata}\Temp'), false, true, true);
end;
end;
end;
end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
Result := True;
case CurPageID of
wpSelectDir:
if not FileExists(ExpandConstant('{app}\SpinTires.exe')) then begin
MsgBox('Ошибка! Вы должны указать путь до папки Spintires.', mbError, MB_OK);
Result := False;
end;
end;
end;

[Run]
Filename: "https://www.worldofmods.ru"; Description: "Посетить сайт WorldOfMods.ru"; Flags: postinstall shellexec;
Filename: "https://www.nsspro.ga"; Description: "«Not So Serious» в Steam"; Flags: postinstall shellexec;
Filename: "mailto:support@nsspro.ga"; Description: "Написать в поддержку"; Flags: postinstall shellexec unchecked;

habib2302 09-05-2018 19:09 2812827

TheLeon, Временные файлы ставьте вверх списка т.к. инсталлятор выгружает файлы с верху в низ. Из-за этого инсталлятор и тормозит после запуска

TheLeon 11-05-2018 13:54 2813164

habib2302, здравствуй, а возможно ли отключить размерность на всех компонентах установщика?

habib2302 11-05-2018 14:08 2813167

TheLeon, я как понял, чтобы инсталлятор не показывал размеры компонентов?
Поменяйте WizardForm.ComponentsDiskSpaceLabel.Visible := True; на False

habib2302 11-05-2018 14:27 2813171

TheLeon, попробуйте поменять WizardForm.ComponentsDiskSpaceLabel.Visible := False; на WizardForm.ComponentsDiskSpaceLabel.Hide;

TheLeon 11-05-2018 14:51 2813178

habib2302, проблему решил, а именно: особо не заморачиваясь, зашёл в russian.isl и нашёл строчки ComponentSize=... и стёр всё, что после знака равно. Но всё равно спасибо вам.
-
Да, опять же возник вопрос: возможно ли сдвинуть поле тип установки вверх, а то я пытался, но у меня половина этого элемента перекрывал задний фон.
https://c.radikal.ru/c14/1805/73/252847181f0e.png

habib2302 11-05-2018 15:12 2813183

TheLeon, ваша ссылка не работает. ПЕРЕЙДИТЕ ПО ССЫЛКЕ НИЖЕ
http://forum.oszone.net/faq.php?faq=...chment_explain
Ссылка на прикрепленный файл не работает. Надо прикреплять в свое сообщение или загружать на облако или файлообм....

habib2302 11-05-2018 15:30 2813185

TheLeon, тут без понятия. если был бы полный скрипт со всеми необходимыми файлами для работы инсталлятора, то помог.

TheLeon 11-05-2018 15:47 2813191

habib2302. Ещё, если не трудно, посмотрите, почему не хочет устанавливать дополнения в program files и подобные директории.

habib2302 11-05-2018 16:50 2813216

TheLeon, поле тип установки и так находится на 0 отметке WizardForm.TypesCombo.Top := ScaleY(0).
Цитата:

Цитата TheLeon
не хочет устанавливать дополнения в program files и подобные директории. »

в параметре DefaultDirName у вас указанно C:\Program Files (x86)\Spintires когда вместо C:\Program Files (x86) должна быть указана константа {pf} (подробнее читайте справку). Для наилучшего сжатия инсталлятора
замените
Compression=zip/9
InternalCompressLevel=ultra
CompressionThreads=2
SolidCompression=True

на
Compression=lzma2/Ultra64
SolidCompression=true
InternalCompressLevel=Ultra64
LZMADictionarySize=65536
LZMAMatchFinder=BT
LZMANumFastBytes=273
MergeDuplicateFiles=yes

habib2302 11-05-2018 21:03 2813289

TheLeon, если вам нужно, чтобы инсталлятор устанавливал допы в папку с игрой, то надо делать через реестр
DefaultDirName={reg:HKxx\SubkeyName,ValueName|Default}
для установки в program files добавьте в раздел setup
ArchitecturesInstallIn64BitMode=x64
ArchitecturesAllowed=x86 x64

TheLeon 18-05-2018 19:21 2814397

habib2302, нужна помощь, опять:
1. Как сделать так, чтобы после установки запускался bat файл(в зависимости оттого какой ты компонент выбрал), от имени администратора + скрытая установка(не высвечивалась командная строка)?
2. Как через bat открыть файл(.txt) и в конце дописать строчки(если они отсутствуют, если же нет, то ничего не делать):

habib2302 18-05-2018 20:32 2814410

Цитата:

Цитата TheLeon
2. Как через bat открыть файл(.txt) и в конце дописать строчки(если они отсутствуют, если же нет, то ничего не делать): »

Цитата:

Цитата TheLeon
от имени администратора »

вам сюда
Цитата:

Цитата TheLeon
1. Как сделать так, чтобы после установки запускался bat файл(в зависимости оттого какой ты компонент выбрал), скрытая установка(не высвечивалась командная строка)? »

Если у вас не запускается батник добавьте
Flags: ShellExec;
для скрытой установки добавьте
Flags: RunHidden;
в зависимости от выбранного компонента добавьте
Components: имя компонента; к нужным строкам из раздела run. если вам нужно добавить несколько компонентов к одной строке, то добавляйте имя компонента через пробел Components: AFP\INSTALL\AX AFP\INSTALL\ALL;

Iska 18-05-2018 21:37 2814418

Цитата:

Цитата habib2302
вам сюда »

С чего бы это туда. Встроенный язык InnoSetup — это, как раз-таки, здесь. Никакие «bat'ы» здесь не нужны.

Я и это: [решено] Замена строк в файле формата .xml предлагал, чтобы сделали здесь же на том же самом встроенном Паскале.

El Sanchez 19-05-2018 13:01 2814461

Цитата:

Цитата Iska
Я и это: [решено] Замена строк в файле формата .xml предлагал, чтобы сделали здесь же на том же самом встроенном Паскале. »

Iska, да легко:
Скрытый текст

Код:


[Code]
/////////////////////////////////////////////////
procedure VehiclesConfig(const FileName: string);
var
 
XMLDoc, XMLNodes, XMLNode: Variant;
  XPath: string;
begin
  try
   
XMLDoc := CreateOleObject('Msxml2.DOMDocument');
    XMLDoc.setProperty('SelectionLanguage', 'XPath');
    XMLDoc.async := False;
    XMLDoc.load(FileName);
    if XMLDoc.parseError.errorCode <> 0 then
     
RaiseException(string(XMLDoc.parseError.reason));

    XMLNode := XMLDoc.createElement('MediaPath');
    XMLNode.setAttribute('Path', 'Vehicles');

    XPath := '/Config/MediaPath[@Path="Media" and not(following-sibling::*[1][self::MediaPath[@Path="Vehicles"]])]/following-sibling::*[1]';
  #if (Ver < 0x5050600) ; avoid VarIsNull
   
XMLNodes := XMLDoc.selectNodes(XPath);
    if XMLNodes.length = 1 then
     
XMLDoc.documentElement.insertBefore(XMLNode, XMLNodes.item(0));
  #else
   
XMLNodes := XMLDoc.selectSingleNode(XPath);
    if not VarIsClear(XMLNodes) then
     
XMLDoc.documentElement.insertBefore(XMLNode, XMLNodes);
  #endif
   
XMLDoc.save(FileName);
  except
   
ShowExceptionMessage;
  finally
  end
;
end;

///////////////////////////
procedure InitializeWizard;
begin
 
VehiclesConfig('{#SourcePath}\example.xml');
end;


ROMKA-1977 28-05-2018 11:31 2815884

Здраствуйте. Помогите пож. объединить два кода.

К инсталятору добавил код фонового изображения используя isgsg.dll:
Скрытый текст

[Setup]
SourceDir=.
OutputDir=Setup
AppName=My Program
AppVerName=1.0
AppVersion=1.0
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
DisableWelcomePage=false
DisableDirPage=false
DisableProgramGroupPage=false

[Languages]
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"

[Files]
Source: "Fon.jpg"; DestDir: {tmp}; Flags: ignoreversion dontcopy nocompression
Source: "isgsg.dll"; DestDir: {tmp}; Flags: ignoreversion dontcopy nocompression
Source: {win}\help\*; DestDir: {app}\Files; Flags: external recursesubdirs createallsubdirs;

[UninstallDelete]
Type: filesandordirs; Name: "{app}"

[_Code]
function GetWindowLong(hWnd: HWND; nIndex: Integer): Longint; external 'GetWindowLongA@user32.dll stdcall delayload';
function ssInitialize(hParent:HWND;ssTimeShow:integer;FadeOut:boolean;StretchMode:integer;BkgColor:DWORD):boo lean; external 'ssInitialize@files:isgsg.dll stdcall delayload';
procedure ssDeInitialize; external 'ssDeInitialize@files:isgsg.dll stdcall delayload';
procedure ssSetBkgImage(FileName:PChar); external 'ssSetBkgImage@files:isgsg.dll stdcall delayload';

procedure InitializeWizard;
begin
ssInitialize(GetWindowLong(MainForm.Handle,-8),0,False,1,$FF000000);
ExtractTemporaryFile('Fon.jpg');
ssSetBkgImage(ExpandConstant('{tmp}')+'\Fon.jpg');
end;

procedure DeinitializeSetup;
begin
ssDeInitialize;
end;

На странице InstallingPage прописал код минимизации окна:
Скрытый текст

[_Code]
var
ResizeButton: TButton;
PageResized, Show: Boolean;

function GetSystemMetrics(nIndex:Integer):integer;
external 'GetSystemMetrics@user32.dll stdcall delayload';
function GetSystemMenu(hWnd: HWND; bRevert: BOOL): LongWord;
external 'GetSystemMenu@user32.dll stdcall';
function DeleteMenu(hMenu: LongWord; uPosition, uFlags: UINT): BOOL;
external 'DeleteMenu@user32.dll stdcall';

procedure MinimizeInstallPage();
begin
WizardForm.MainPanel.Hide;
WizardForm.Bevel1.Hide;
WizardForm.Width:= ScaleX(395);
WizardForm.Height:= ScaleY(142);
WizardForm.Left:= GetSystemMetrics(16)-ScaleX(420);
WizardForm.Top:= GetSystemMetrics(17)-ScaleX(150);
WizardForm.InnerNotebook.Left:= ScaleX(10);
WizardForm.InnerNotebook.Top:= ScaleY(10);
WizardForm.InnerNotebook.Width:= ScaleX(370);
WizardForm.StatusLabel.Left:= ScaleX(0);
WizardForm.StatusLabel.Top:= ScaleY(0);
WizardForm.StatusLabel.Width:=WizardForm.InnerNotebook.Width;
WizardForm.FileNameLabel.Left:= ScaleX(0);
WizardForm.FileNameLabel.Top:= ScaleY(20);
WizardForm.FileNameLabel.Width:= WizardForm.InnerNotebook.Width;
WizardForm.ProgressGauge.Top:= ScaleY(40);
WizardForm.ProgressGauge.Width:= WizardForm.InnerNotebook.Width;
WizardForm.CancelButton.Left:= ScaleX(220);
WizardForm.CancelButton.Top:= ScaleY(80);
WizardForm.CancelButton.BringToFront;
ResizeButton.Left:= ScaleX(60);
ResizeButton.Top:= ScaleY(80);
ResizeButton.Caption:= 'Max.';
PageResized:= True;
end;

procedure ResumeInstallPage();
begin
WizardForm.Width:= ScaleX(503);
WizardForm.Height:= ScaleY(388);
WizardForm.Position:= poScreenCenter;
if Show then begin
WizardForm.MainPanel.SetBounds(ScaleX(0), ScaleY(0), ScaleX(497), ScaleY(58));
WizardForm.MainPanel.Show;
WizardForm.Bevel1.Show;
end;
WizardForm.InnerNotebook.SetBounds(ScaleX(40), ScaleY(72), ScaleX(417), ScaleY(237));
WizardForm.StatusLabel.SetBounds(ScaleX(0), ScaleY(0), ScaleX(417), ScaleY(16));
WizardForm.FilenameLabel.SetBounds(ScaleX(0), ScaleY(16), ScaleX(417), ScaleY(16));
WizardForm.ProgressGauge.SetBounds(ScaleX(0), ScaleY(42), ScaleX(417), ScaleY(21));
WizardForm.CancelButton.SetBounds(ScaleX(412), ScaleY(327), ScaleX(75), ScaleY(23));
ResizeButton.SetBounds(ScaleX(20), ScaleY(327),ScaleX(75), ScaleY(23));
ResizeButton.Caption:= 'Min.';
PageResized:= False;
end;

procedure ResizeButtonOnClick(Sender: TObject);
begin
If PageResized then
ResumeInstallPage
else
MinimizeInstallPage;
end;

procedure InitializeWizard();
begin
ResizeButton:= TButton.Create(WizardForm);
ResizeButton.SetBounds(ScaleX(20), ScaleY(327),ScaleX(75), ScaleY(23));
ResizeButton.OnClick:= @ResizeButtonOnClick;
ResizeButton.Caption:= 'Min.';
ResizeButton.Hide;
ResizeButton.Parent:= WizardForm;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
ResizeButton.Hide;
case CurPageID of
wpInstalling:
begin
Show:= true;
ResizeButton.Show;
end;
wpFinished:
begin
Show:= false;
ResumeInstallPage;
DeleteMenu(GetSystemMenu(WizardForm.Handle,False),$F060,0);
end;
end;
end;

procedure BtnDisable();
begin
ResizeButton.Enabled := False;
end;

Необходимо выполнить следующее:
1. При клике на кнопку "Min" фоновое изображение закрывается
2. При клике на кнопку "Max" фоновое изображение отображается

El Sanchez 29-05-2018 17:15 2816073

Цитата:

Цитата ROMKA-1977
Необходимо выполнить следующее:
1. При клике на кнопку "Min" фоновое изображение закрывается
2. При клике на кнопку "Max" фоновое изображение отображается »

ROMKA-1977, в секцию Setup добавить WindowVisible=yes и WindowShowCaption=no, в процедуре ResizeButtonOnClick в конце дописать MainForm.Visible := not PageResized;

ROMKA-1977 30-05-2018 09:29 2816141

Цитата:

Цитата El Sanchez
в секцию Setup добавить WindowVisible=yes и WindowShowCaption=no, в процедуре ResizeButtonOnClick в конце дописать MainForm.Visible := not PageResized; »

Получилось но не совсем то. Поверх фонового изображения "xxx.jpg" теперь накладывается стандартный синий фон Inno Setup вот он закрывается и отображается при кликах на кнопки "Min" и "Max", а фоновое изображение "xxx.jpg" как и ранее отображается на экране при клике на кнопку "Min".

Nikolay4 30-05-2018 16:42 2816182

Добрый день, подскажите, возможно ли как-то прикрутить inno download plugin к скрипту "Opera"
чтоб прогресс скачивания нормально отображался перед распаковкой.

Сам скрипт

El Sanchez 31-05-2018 10:08 2816246

Цитата:

Цитата ROMKA-1977
Получилось но не совсем то. Поверх фонового изображения "xxx.jpg" теперь накладывается стандартный синий фон Inno Setup вот он закрывается и отображается при кликах на кнопки "Min" и "Max", а фоновое изображение "xxx.jpg" как и ранее отображается на экране при клике на кнопку "Min". »

ROMKA-1977, не проверял, не хочу библиотеку искать :). Попробуйте вместо ssInitialize(GetWindowLong(MainForm.Handle,-8),0,False,1,$FF000000); написать ssInitialize(MainForm.Handle,0,False,1,$FF000000);
P.S. GetWindowLong(MainForm.Handle,-8) - попытка автора библиотеки Application.Handle получить. Ужас.

Sotonisto 13-06-2018 02:13 2818046

Доброго времени суток. Будьте добры подскажите:
1. Как изменить цвет текста лицензионного соглашения? WizardForm.LicenseMemo.Font.Color не даёт никакого эффекта.
2. Существует ли способ разместить текст на Splash изображении?
3. Можно ли в WizardForm.ComponentsList добавить название колонок (как в таблицах)? По сути над списком чекбоксов должна размещаться линия, поделенная на 3 "колонки", такого вида: [ Пустая ячейка | Компоненты | Размер компонента].

El Sanchez 14-06-2018 12:04 2818213

Цитата:

Цитата Sotonisto
1. Как изменить цвет текста лицензионного соглашения? WizardForm.LicenseMemo.Font.Color не даёт никакого эффекта. »

Sotonisto, используйте rtf-файл
Цитата:

Цитата Sotonisto
3. Можно ли в WizardForm.ComponentsList добавить название колонок (как в таблицах)? По сути над списком чекбоксов должна размещаться линия, поделенная на 3 "колонки", такого вида: [ Пустая ячейка | Компоненты | Размер компонента]. »

Sotonisto,
Скрытый текст

Код:

[Code]
#define A = (Defined UNICODE) ? "W" : "A"
#ifndef IS_ENHANCED
const
 
WC_HEADER = 'SysHeader32';
  WS_CHILD = $40000000;
  WS_VISIBLE = $10000000;
  WS_DISABLED = $08000000;
  WM_SETFONT = $0030;
  HDI_WIDTH = $0001;
  HDI_TEXT = $0002;
  HDI_FORMAT = $0004;
  HDF_CENTER = $0002;
  HDF_STRING = $4000;
  HDM_FIRST = $1200;
  HDM_INSERTITEM = HDM_FIRST + {#ifdef UNICODE}10{#else}1{#endif};

type
 
THDItem = record
   
Mask: LongWord;
    cxy: Integer;
    pszText: string;
    hbm: HBITMAP;
    cchTextMax: Integer;
    fmt: Integer;
    lParam: LongWord;
    iImage: Integer;
    iOrder: Integer;
    _type: LongWord;
    pvFilter: LongWord;
    state: LongWord;
  end;

// Window Functions
function CreateWindowEx(dwExStyle: DWORD; lpClassName, lpWindowName: string; dwStyle: DWORD; x, y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: THandle; hInstance, lpParam: Longint): HWND; external 'CreateWindowEx{#A}@user32.dll stdcall';
function DestroyWindow(hWnd: HWND): BOOL; external 'DestroyWindow@user32.dll stdcall';
// Message Functions
function SendMessageHDItem(hWnd: HWND; Msg: LongWord; wParam: Longint; var lParam: THDItem): Longint; external 'SendMessage{#A}@user32.dll stdcall';

var
 
HeaderHandle: HWND;
#endif

procedure CreateHeader;
var
#ifdef IS_ENHANCED
 
HeaderControl: THeaderControl;
  HeaderSection: THeaderSection;
#else
 
HDItem: THDItem;
#endif
begin
  with
WizardForm.ComponentsList do
  begin
#ifdef IS_ENHANCED
   
HeaderControl := THeaderControl.Create(WizardForm);
    HeaderControl.Parent := WizardForm.ComponentsList;
    HeaderControl.Enabled := False;
    HeaderSection := HeaderControl.Sections.Add;
    HeaderSection.Width := ClientWidth div 3;
    HeaderSection.Alignment := taCenter;
    HeaderSection.Text := '';
    HeaderSection := HeaderControl.Sections.Add;
    HeaderSection.Width := ClientWidth div 3;
    HeaderSection.Alignment := taCenter;
    HeaderSection.Text := 'Компоненты';
    HeaderSection := HeaderControl.Sections.Add;
    HeaderSection.Width := ClientWidth div 3;
    HeaderSection.Alignment := taCenter;
    HeaderSection.Text := 'Размер компонента';
#else
   
HeaderHandle := CreateWindowEx(0, WC_HEADER, '', WS_VISIBLE or WS_CHILD or WS_DISABLED, 0, 0, ClientWidth, MinItemHeight, Handle, 0, 0, 0);
    if HeaderHandle = 0 then Exit;
    SendMessage(HeaderHandle, WM_SETFONT, Font.Handle, 1);
    HDItem.Mask := HDI_WIDTH or HDI_TEXT or HDI_FORMAT;
    HDItem.cxy := ClientWidth div 3;
    HDItem.fmt := HDF_CENTER or HDF_STRING;
    HDItem.pszText := '';
    SendMessageHDItem(HeaderHandle, HDM_INSERTITEM, 0, HDItem);
    HDItem.pszText := 'Компоненты';
    SendMessageHDItem(HeaderHandle, HDM_INSERTITEM, 1, HDItem);
    HDItem.pszText := 'Размер компонента';
    SendMessageHDItem(HeaderHandle, HDM_INSERTITEM, 2, HDItem);
#endif
 
end;
end;

procedure InitializeWizard;
begin
 
CreateHeader;
end;

procedure DeinitializeSetup;
begin
#ifndef IS_ENHANCED
 
if HeaderHandle <> 0 then
   
DestroyWindow(HeaderHandle);
#endif
end;


Sotonisto 15-06-2018 03:57 2818301

El Sanchez, скрипт для ComponentsList работает, но название колонок скрывает первый компонент. Каким образом можно разместить название колонок до первого компонента? Или же сделать отступ определенного размера перед списком компонентов?

El Sanchez 15-06-2018 14:37 2818342

Цитата:

Цитата Sotonisto
скрипт для ComponentsList работает, но название колонок скрывает первый компонент. »

Sotonisto, точно, еще и стирается при нажатии на первый компонент. Вот вариант на расширенной версии, где заголовок рисуется на неклиентской части ComponentsList:
Скрытый текст

Код:

[Code]
#define A = (Defined UNICODE) ? "W" : "A"
type
 
TNCCalcSizeParams = record
   
rgrc0: TRect;
    rgrc1: TRect;
    rgrc2: TRect;
  end;

// Shell Functions
function SetWindowSubclass(hWnd: HWND; pfnSubclass: Longint; uIdSubclass: UINT_PTR; dwRefData: DWORD_PTR): BOOL; external 'SetWindowSubclass@comctl32.dll stdcall';
function RemoveWindowSubclass(hWnd: HWND; pfnSubclass: Longint; uIdSubclass: UINT_PTR): BOOL; external 'RemoveWindowSubclass@comctl32.dll stdcall';
function DefSubclassProc(hWnd: HWND; uMsg: UINT; wParam, lParam: Longint): Longint; external 'DefSubclassProc@comctl32.dll stdcall';
// Run-Time Library (RTL) Routines
function ReadNCCalcSizeParams(out Destination: TNCCalcSizeParams; const Source: LongWord; len: Integer): Integer; external 'RtlMoveMemory@kernel32.dll stdcall';
// Debugging Functions
function WriteNCCalcSizeParams(hProcess: THandle; lpBaseAddress: Longint; var lpBuffer: TNCCalcSizeParams; nSize: DWORD; out lpNumberOfBytesWritten: DWORD): BOOL; external 'WriteProcessMemory@kernel32.dll stdcall';
// Process and Thread Functions
function GetCurrentProcess: THandle; external 'GetCurrentProcess@kernel32.dll stdcall';
// Device Context Functions
function GetDCEx(hWnd: HWND; hrgnClip: THandle; flags: DWORD): THandle; external 'GetDCEx@user32.dll stdcall';
function ReleaseDC(hWnd: HWND; hDC: THandle): Integer; external 'ReleaseDC@user32.dll stdcall';
//  Painting and Drawing Functions
function GetWindowDC(hWnd: HWND): THandle; external 'GetWindowDC@user32.dll stdcall';
// Window Functions
function GetWindowRect(hWnd: HWND; var lpRect: TRect): BOOL; external 'GetWindowRect@user32.dll stdcall';
function SetWindowPos(hWnd, hWndInsertAfter: HWND; X, Y, cx, cy: Integer; uFlags: UINT): BOOL; external 'SetWindowPos@user32.dll stdcall';

const
 
WM_NCCALCSIZE = $0083;
  WM_NCPAINT = $0085;

  SWP_NOSIZE = 1;
  SWP_NOMOVE = 2;
  SWP_NOZORDER = 4;
  SWP_FRAMECHANGED = $20;
  SWP_NOOWNERZORDER = $200;

  DCX_WINDOW = 1;
  DCX_CACHE = 2;
  DCX_INTERSECTRGN = $80;
  DCX_USESTYLE = $10000;
  DCX_KEEPCLIPRGN = $40000;

var
 
PCheckListBoxWndProc: LongWord;
  HeaderControl: THeaderControl;

function CheckListBoxWndProc(hWnd: HWND; uMsg: UINT; wParam, lParam: Longint; uIdSubclass: UINT_PTR; dwRefData: DWORD_PTR): LongWord;
var
 
DC: THandle;
  NCCalcSizeParams: TNCCalcSizeParams;
  NumberOfBytesWritten: DWORD;
  P: TPoint;
  R: TRect;
begin
  case
uMsg of
   
WM_NCCALCSIZE:
      begin
       
Result := DefSubclassProc(hWnd, uMsg, wParam, lParam);
        ReadNCCalcSizeParams(NCCalcSizeParams, lParam, SizeOf(NCCalcSizeParams));
        NCCalcSizeParams.rgrc0.Top := NCCalcSizeParams.rgrc0.Top + HeaderControl.Height;
        WriteNCCalcSizeParams(GetCurrentProcess, lParam, NCCalcSizeParams, SizeOf(NCCalcSizeParams), NumberOfBytesWritten);
      end;
    WM_NCPAINT:
      begin
        if
(wParam <> 0) and (wParam <> 1) then
         
DC := GetDCEx(hWnd, wParam, DCX_WINDOW or DCX_CACHE or DCX_INTERSECTRGN or DCX_KEEPCLIPRGN or DCX_USESTYLE)
        else
         
DC := GetWindowDC(hWnd);
        try
         
Result := DefSubclassProc(hWnd, uMsg, wParam, lParam);
          GetWindowRect(hWnd, R);
          P.x := 0;
          P.y := -HeaderControl.Height;
          P := HeaderControl.ClientToScreen(P);
          HeaderControl.PaintTo(DC, P.x - R.Left, P.y - R.Top);
        finally
         
ReleaseDC(hWnd, DC);
        end;
      end;
  else
   
Result := DefSubclassProc(hWnd, uMsg, wParam, lParam);
  end;
end;

procedure CreateHeader;
var
 
HeaderSection: THeaderSection;
begin
  with
WizardForm.ComponentsList do
  begin
   
HeaderControl := THeaderControl.Create(WizardForm);
    HeaderControl.Parent := WizardForm.ComponentsList;
    HeaderControl.Enabled := False;
    HeaderSection := HeaderControl.Sections.Add;
    HeaderSection.Width := ClientWidth div 3;
    HeaderSection.Alignment := taCenter;
    HeaderSection.Text := '';
    HeaderSection := HeaderControl.Sections.Add;
    HeaderSection.Width := ClientWidth div 3;
    HeaderSection.Alignment := taCenter;
    HeaderSection.Text := 'Компоненты';
    HeaderSection := HeaderControl.Sections.Add;
    HeaderSection.Width := ClientWidth div 3;
    HeaderSection.Alignment := taCenter;
    HeaderSection.Text := 'Размер компонента';

    // sublass
   
PCheckListBoxWndProc := CallbackAddr('CheckListBoxWndProc');
    SetWindowSubclass(Handle, PCheckListBoxWndProc, 0, 0);
    // send WM_NCCALCSIZE
   
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or SWP_NOMOVE or SWP_NOOWNERZORDER or SWP_NOSIZE or SWP_NOZORDER);
    HeaderControl.Visible := False;
  end;
end;

procedure InitializeWizard;
begin
 
CreateHeader;
end;

procedure DeinitializeSetup;
begin
  if
PCheckListBoxWndProc <> 0 then
   
RemoveWindowSubclass(WizardForm.ComponentsList.Handle, PCheckListBoxWndProc, 0);
end;


usermode 15-06-2018 14:40 2818343

Всем привет! Есть код:

Код:

procedure RtlMoveMemory(Dest: string; Source: PAnsiChar; Len: Integer);
external 'RtlMoveMemory@kernel32.dll stdcall';

function LoadStringFromUTF16LEFile(FileName: string; var S: string): Boolean;
var
  A: AnsiString;
begin
  Result := LoadStringFromFile(FileName, A);
  if Result then
  begin
    SetLength(S, Length(A) div 2);
    RtlMoveMemory(S, A, Length(S) * 2);
    { Trim BOM, if any }
    if (Length(S) >= 1) and (Ord(S[1]) = $FEFF) then
      Delete(S, 1, 1);
  end;
end;

Помогите переделать данную функцию для загрузки UTF-8 файла.

Сама задача решаема через перекодировки в скрипте ConvertString.iss, но в этом примере кода поменьше.

// еще одна задача
необходимо запустить юникодный батник через функцию Exec или ShellExec (или через api), чтобы внутренние команды выполнились, например, bat-ник с содержимым:

copy "c:\嗨 русский.txt" "c:\嗨 русский.txt.bak"

в самой Windows, если вставить данную строку в cmd, то, пусть она и не отобразит правильно имена файлов в окне (что не требуется), но зато выполнит операцию корректно с названиями файлов в Unicode кодировке.

как добиться этого в Inno, чтобы можно было выполнять юникодные батники?
(просьба при возможности сделать пример для стандартной версии IS)

Sotonisto 15-06-2018 20:55 2818381

El Sanchez, у меня всё снова не как у людей. Вместо названий колонок отображается пустое место (зато с отступом). В первой версии скрипта все отображалось корректно. Я обнаружил, что причина проблемы в том, что у меня WizardForm является родительским элементом для ComponentsList (Parent:=WizardForm). Прошу у Вас помощи еще раз, подскажите что нужно изменить, чтобы колонки отображались.

El Sanchez 16-06-2018 12:16 2818417

Цитата:

Цитата Sotonisto
Я обнаружил, что причина проблемы в том, что у меня WizardForm является родительским элементом для ComponentsList (Parent:=WizardForm). »

Sotonisto, переместите строку HeaderControl.Visible := False; после SetWindowPos.

Coломoн Keйн 16-06-2018 15:51 2818436

Здраствуйте. Подскажите, пожалуйста, как создать патч с помощью Inno Setup? Обыкновенный инсталятор непрактичен из-за своего веса. Вчера использовал софтинку Inno Setup XDELTA Patch Maker, но два факта огорчили меня сильно - во первых, файла два (exe и bin), не один, а во вторых, окно инсталла сильно упрощенно по сравнению с инсталлами от самого Inno Setup.
Грубо говоря, есть два архива - оригинальный и модифицированный. Надо, чтобы инсталл содержал только разницу между ними (патч-данные). Тогда он будет весить около всего 40 Мб, чего я и хочу добиться, но чтобы окно инсталла осталось неизменным.

habib2302 16-06-2018 22:29 2818460

Coломoн Keйн, можете попробовать Mole`s Smart Version Patch Constructor

Coломoн Keйн 16-06-2018 22:56 2818464

Цитата:

Цитата habib2302
Coломoн Keйн, можете попробовать Mole`s Smart Version Patch Constructor »

Обязательно попробую. Спасибо за совет!

usermode 16-06-2018 23:01 2818465

Coломoн Keйн, есть еще патчер Visual Patch от Indigo Rose, там патчи можно создать как мастер со страницами наподобие Inno Setup. А для создания автономного патча в ISXPM нужно убрать галку Create Launcher, если размер патча на выходе небольшой.

А чтобы самому включить в свой инсталлятор патч-файл и применить его при установке, это нужно консольные утилиты использовать, типа xdelta или jojodiff, разбираться, как они работают и использовать их в своем инсталляторе.

Coломoн Keйн 17-06-2018 14:47 2818516

Цитата:

Цитата usermode
есть еще патчер Visual Patch от Indigo Rose »

Да вот сижу над ней, но после компиляции говорит, мол моя софтинка не найдена. Хз как исправить.
Цитата:

Цитата Coломoн Keйн
Mole`s Smart Version Patch Constructor »

инсталл просто отвратительный получился.

Цитата:

Цитата usermode
А чтобы самому включить в свой инсталлятор патч-файл и применить его при установке, это нужно консольные утилиты использовать, типа xdelta или jojodiff, разбираться, как они работают и использовать их в своем инсталляторе. »

Если не разберусь, обращусь. $$$

usermode 17-06-2018 19:33 2818547

Цитата:

Цитата Coломoн Keйн
Если не разберусь, обращусь. $$$ »

Так а что там, вот, к примеру JojoDiff:
https://sourceforge.net/projects/jojodiff/
Для генерации патч-файла запустить из командной строки:

jdiff.exe -b "C:\original.file" "C:\modified.file" "C:\resultpatch.file"

а для применения, полученный файл с изменениями resultpatch.file включить в установку и после инсталляции выполнить в Exec или RunTask:
jptch.exe "C:\original.file" "C:\resultpatch.file" "C:\modified.file"
(естественно, с путями константами)

в итоге после установки указанный original.file будет пропатчен.
но для этого может понадобится манипуляция удаления старого файла с переименованием пропатченного файла в оригинальное имя стандартными средствами Inno.

А в ISXPM можно вообще сделать невидимый Silent патч без окна (или SilentForm - маленькая форма с индикатором прогресса выполнения, чтобы пользователю было понятно, что применяется обновление и ничего не зависло) с указанием параметров с путем для применения и запускать его из инсталлятора, вся информация есть в справке, в нем поддерживаются константы Inno Setup.
Просто когда нужно будет поставить апдейт с обновлением для сотни файлов, то делать вручную это не очень хорошая идея, поэтому создавалась данная программа, чтобы довести все до полного автоматизма.

Coломoн Keйн 17-06-2018 20:41 2818552

Цитата:

Цитата usermode
Для генерации патч-файла запустить из командной строки:
jdiff.exe -b "C:\original.file" "C:\modified.file" "C:\resultpatch.file" »

Ого, спасибище! 3 дня мучаюсь уже. С этим моментом понятно, с остальными - как начну, будет ясно. Или не ясно. Я не профи в инно сетапе. В любом случае, спасибо!

Просто этот файл, по которому патч-данные делаются - единственный, который устанавливается. Можно как то сделать применение патч-данных к оригинальному файлу как раз в момент установки, не после нее? Или я уже слишком требовательный к инсталлятору? И да, я так понимаю, можно же скомбинировать все это дело с существующим скриптом, чтобы не терять его главных функций?

usermode 17-06-2018 21:15 2818557

Цитата:

Цитата Coломoн Keйн
Можно как то сделать применение патч-данных к оригинальному файлу как раз в момент установки, не после нее? »

можно выполнить и перед установкой, можно как угодно в зависимости от алгоритма действий. но чтобы делать такие простейшие вещи, нужно время изучить хотя бы базово Inno Setup, опробовать примеры, почитать справку и руководства. все есть в шапке темы. а потом спрашивать, что именно не получается. ко всем модулям тоже нужно читать описания и мануалы, не лениться вобщем :)

Sotonisto 18-06-2018 19:36 2818647

Доброго всем вечера.
Будьте добры, подскажите, как реализовать сплеш с использованием botva2? Попытался сделать так, но содержимое формы не отображается (хотя при ShowModal все отображалось корректно):
И еще один вопрос: существует ли способ выровнять текст по правому краю? Например, как размещение по центру при помощи taCenter.

ZVSRus 21-06-2018 21:26 2819043

Цитата:

Цитата Sotonisto
И еще один вопрос: существует ли способ выровнять текст по правому краю? Например, как размещение по центру при помощи taCenter.

Так не пойдёт?
Скрытый текст

[Setup]
AppName=My Application
AppVersion=1.5
DefaultDirName={pf}\My Application

[code]
var
Text1: TLabel;
Text2: TLabel;
Text3: TLabel;

procedure InitializeWizard();
begin
Text1 := TLabel.Create(WizardForm);
with Text1 do
begin
Parent := WizardForm.SelectDirPage;
Alignment := taRightJustify;
Caption := 'Текст справа';
Font.Color := clBlue;
Font.Height := -13;
Font.Name := 'Tahoma';
Font.Style := [fsBold, fsItalic];
SetBounds(ScaleX(0),ScaleY(120),ScaleX(417),ScaleY(16));
end;

Text2 := TLabel.Create(WizardForm);
with Text2 do
begin
Parent := WizardForm.SelectDirPage;
Alignment := taCenter;
Caption := 'Текст по центру';
Font.Color := clBlue;
Font.Height := -13;
Font.Name := 'Tahoma';
Font.Style := [fsBold, fsItalic];
SetBounds(ScaleX(0),ScaleY(140),ScaleX(417),ScaleY(16));
end;

Text3 := TLabel.Create(WizardForm);
with Text3 do
begin
Parent := WizardForm.SelectDirPage;
// Alignment := taLeftJustify;
Caption := 'Текст слева';
Font.Color := clBlue;
Font.Height := -13;
Font.Name := 'Tahoma';
Font.Style := [fsBold, fsItalic];
SetBounds(ScaleX(0),ScaleY(160),ScaleX(417),ScaleY(16));
end;
end;


Sotonisto 22-06-2018 11:47 2819100

ZVSRus, благодарю. Я понятия не имел, что к taRight и taLeft необходимо добавить Justify.

pollipen 22-06-2018 12:39 2819115

парни что за проблема нажимаю установить вот такая ошибка , но программа устанавливается

habib2302 22-06-2018 13:18 2819122

pollipen, мы по вашему экстрасенсы? скрипт в студию!

TheLeon 08-07-2018 12:44 2821014

Здравствуйте, нужна помощь:
  • Не могу вместо кнопок инсталлятора вставить свои изображения(кастомные кнопки), а также непонятно как сделать кастомные "Скрыть" и "Закрыть" кнопки(если без рамки Windows). [Скриншот 1]
  • Не могу убрать данный белый фон или просто изменить его размер. [Скриншот 2]
  • Правильно ли я вообще выполняю действия(что через редактор форм)?


P.S. Видно плохо искал ответы на вопросы, что не нашёл.

habib2302 08-07-2018 20:50 2821063

Цитата:

Цитата TheLeon
Не могу вместо кнопок инсталлятора вставить свои изображения(кастомные кнопки) »

Текстурирование кнопок через botva2.dll
Код:

[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirName={pf}\MyApp

[Files]
Source: botva2.dll; DestDir: {tmp}; Flags: dontcopy
Source: compiler:innocallback.dll; DestDir: {tmp}; Flags: dontcopy
Source: Button.png; DestDir: {tmp}; Flags: dontcopy

[Code]
type
TButtonInfo = record ButtonName: array of TButton; Handle: array of HWND; Count: Integer; end;
TBtnEventProc = procedure(h:HWND);

const
BtnClickEventID = 1;
BtnMouseEnterEventID = 2;
BtnMouseLeaveEventID = 3;
BtnMouseMoveEventID = 4;

balLeft = 0;
balCenter = 1;

var
ButtonsBuff: TButtonInfo;
HCancelButton, HNextButton, HBackButton, HDirBrowseButton, HGroupBrowseButton: HWND;

function WrapBtnCallback(Callback: TBtnEventProc; ParamCount: Integer): Longword; external 'wrapcallback@files:innocallback.dll stdcall';
function BtnCreate(hParent:HWND; Left,Top,Width,Height:integer; FileName:PAnsiChar; ShadowWidth:integer; IsCheckBtn:boolean):HWND; external 'BtnCreate@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetPosition(h:HWND; NewLeft, NewTop, NewWidth, NewHeight: integer); external 'BtnSetPosition@files:botva2.dll stdcall';
procedure BtnRefresh(h:HWND); external 'BtnRefresh@files:botva2.dll stdcall';
function BtnGetChecked(h:HWND):boolean; external 'BtnGetChecked@files:botva2.dll stdcall';
procedure BtnSetChecked(h:HWND; Value:boolean); external 'BtnSetChecked@files:botva2.dll stdcall';
procedure BtnSetText(h:HWND; Text:PAnsiChar); external 'BtnSetText@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetTextAlignment(h:HWND; HorIndent, VertIndent:integer; Alignment:DWORD); external 'BtnSetTextAlignment@files:botva2.dll stdcall';
procedure BtnSetVisibility(h:HWND; Value:boolean); external 'BtnSetVisibility@files:botva2.dll stdcall';
function BtnGetEnabled(h:HWND):boolean; external 'BtnGetEnabled@files:botva2.dll stdcall';
procedure BtnSetEnabled(h:HWND; Value:boolean); external 'BtnSetEnabled@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetFont(h:HWND; Font:Cardinal); external 'BtnSetFont@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetFontColor(h:HWND; NormalFontColor, FocusedFontColor, PressedFontColor, DisabledFontColor: Cardinal); external 'BtnSetFontColor@{tmp}\botva2.dll stdcall delayload';
procedure BtnSetEvent(h:HWND; EventID:integer; Event:Longword); external 'BtnSetEvent@files:botva2.dll stdcall';
procedure BtnSetCursor(h:HWND; hCur:Cardinal); external 'BtnSetCursor@files:botva2.dll stdcall';
function GetSysCursorHandle(id:integer):Cardinal; external 'GetSysCursorHandle@files:botva2.dll stdcall';
procedure gdipShutdown; external 'gdipShutdown@files:botva2.dll stdcall';

procedure UpdateButtons();
var I: integer;
begin
for
I:=0 to (ButtonsBuff.Count-1) do begin
BtnSetEnabled(ButtonsBuff.Handle[I], ButtonsBuff.ButtonName[I].Enabled)
BtnSetVisibility(ButtonsBuff.Handle[I], ButtonsBuff.ButtonName[I].Visible)
BtnSetText(ButtonsBuff.Handle[I], ButtonsBuff.ButtonName[I].Caption)
BtnRefresh(ButtonsBuff.Handle[I])
end;
end;

procedure ButtonOnClick(hBtn: HWND);
var Btn: TButton; I: Integer;
begin
for
I:=0 to (ButtonsBuff.Count-1) do begin
if
hBtn = ButtonsBuff.Handle[I] then Btn:= ButtonsBuff.ButtonName[I];
end;
Btn.OnClick(Btn)
UpdateButtons;
end;

function EffectTextureButton(Handle: HWND; Button: TButton; ImageName: PAnsiChar; ShadowWidth: Integer; EnterEvent, MoveEvent, LeaveEvent: TbtnEventProc): HWND;
begin
Result:=BtnCreate(Handle, Button.Left-8, Button.Top-8, Button.Width+16, Button.Height+16, ImageName, ShadowWidth, False) ///Размеры подобраны для текущей текстуры
BtnSetEvent(Result, BtnClickEventID, WrapBtnCallback(@ButtonOnClick, 1))
if EnterEvent <> nil then BtnSetEvent(Result, BtnMouseEnterEventID, WrapBtnCallback(EnterEvent, 1));
if MoveEvent <> nil then BtnSetEvent(Result, BtnMouseMoveEventID, WrapBtnCallback(MoveEvent, 1));
if LeaveEvent <> nil then BtnSetEvent(Result, BtnMouseLeaveEventID, WrapBtnCallback(LeaveEvent, 1));
BtnSetFont(Result, Button.Font.Handle)
BtnSetText(Result, Button.Caption);
BtnSetVisibility(Result, Button.Visible);
BtnSetFontColor(Result,clBlack,clBlack,clBlack,clGray);
BtnSetCursor(Result,GetSysCursorHandle(32649));
Button.Width:=0; Button.Height:= 0;
SetArrayLength(ButtonsBuff.Handle, ButtonsBuff.Count+1);SetArrayLength(ButtonsBuff.ButtonName, ButtonsBuff.Count+1);
ButtonsBuff.ButtonName[ButtonsBuff.Count]:= Button; ButtonsBuff.Handle[ButtonsBuff.Count]:= Result;
ButtonsBuff.Count:= ButtonsBuff.Count+1;
end;

procedure ButtonChangeFont(ButtonHandle: HWND; Font: TFont; NormalColor, FocusedColor, PressedColor, DisabledColor: Cardinal);
begin
if
Font <> nil then BtnSetFont(ButtonHandle, Font.Handle);
BtnSetFontColor(ButtonHandle, NormalColor, FocusedColor, PressedColor, DisabledColor)
end;

procedure InitializeWizard();
begin
ExtractTemporaryFile('Button.png')
HNextButton:= EffectTextureButton(WizardForm.Handle, WizardForm.NextButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HCancelButton:= EffectTextureButton(WizardForm.Handle, WizardForm.CancelButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HBackButton:= EffectTextureButton(WizardForm.Handle, WizardForm.BackButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HDirBrowseButton:= EffectTextureButton(WizardForm.Handle, WizardForm.DirBrowseButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
HGroupBrowseButton:= EffectTextureButton(WizardForm.Handle, WizardForm.GroupBrowseButton, ExpandConstant('{tmp}\Button.png'), 18, nil, nil, nil)
end;

procedure CurPageChanged(CurPageId: Integer);
begin
UpdateButtons
end;

procedure DeinitializeSetup();
begin
gdipShutdown
end;



Цитата:

Цитата TheLeon
а также непонятно как сделать кастомные "Скрыть" и "Закрыть" кнопки(если без рамки Windows) »

если не ошибаюсь эти кнопки меняются только скинами для инсталляторов

TheLeon 09-07-2018 12:45 2821129

habib2302,
Цитата:

Цитата habib2302
Текстурирование кнопок через botva2.dll »

Использовал код, настраивал размеры текстурирования, но пропал текст кнопок, кнопки огромного размера, а также неактивны. [Скриншот 1]

Sotonisto 11-07-2018 02:59 2821422

Цитата:

Цитата TheLeon
Не могу вместо кнопок инсталлятора вставить свои изображения(кастомные кнопки), а также непонятно как сделать кастомные "Скрыть" и "Закрыть" кнопки(если без рамки Windows).
Не могу убрать данный белый фон или просто изменить его размер.»

Как-то так?

TheLeon 11-07-2018 12:28 2821484

Sotonisto, спасибо огромное! Вы сделали всё как в моём шаблоне, не видя других страниц инсталлятора, спасибо!

Sotonisto 11-07-2018 18:07 2821551

TheLeon, не за что. Надеюсь, со скриптом вы разобрались без проблем.

pollipen 16-07-2018 11:56 2821993

парни как избавиться от запроса вот этого
что бы перезаписала сразу
Скрытый текст

boss911 16-07-2018 14:59 2822020

Цитата:

Цитата pollipen
как избавиться от запроса... »

Код:

[Files]
Source: ACDSee Video\videorecorder.ini; DestDir: {app}\ACDSee Video; Flags: overwritereadonly


ErikPshat 21-07-2018 17:46 2822974

Ребята, помогите пожалуйста...
Я тут делаю распаковщик для многотомных архивов одной игры. Но пока это дело реализовал через голый 7-Zip.
Скачать проект можно здесь: http://rgho.st/7Qx8Zvc7C (в архиве лежат 5 маленьких томов для теста распаковки - 001, 002, 003, 004, 005).

Я же хочу сделать распаковку через ISDone по фэншую, чтобы распаковка шла с двумя полосками прогресс-бара, с процентами, временем и всем остальным, но не пойму, какими командами и в каком месте её прикрутить. Я умею её прикручивать, но она у меня работает только в стандартных приложениях после нажатия кнопки "Готово". А здесь у меня кастомный интерфейс и есть кнопка "Распаковать".

Помогите пожалуйста...

R.i.m.s.k.y. 23-07-2018 12:20 2823157

Подскажите, пожалуйста, почему установщик инно не может под UAC внести изменения в реестр HLKM
Версия инно 5,5,1 ее2 (а)
куски скрипта в части касающейся
Код:

[Setup]
PrivilegesRequired=admin

[Code]
procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssDone then begin
    if IsComponentSelected('TW1') then begin
      RegWriteDWordValue (HKEY_LOCAL_MACHINE, 'SOFTWARE\CD Projekt Red\The Witcher','IsDjinniInstalled', 1);
      RegWriteStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\CD Projekt Red\The Witcher','RegionVersion', 'WE');
      RegWriteStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\CD Projekt Red\The Witcher','InstallFolder', ExpandConstant('app}\'));
    end;//  if IsComponentSelected('TW1') then begin
  end;

[Registry]
Root: HKLM; Subkey: "SOFTWARE\CD Projekt Red\The Witcher"; ValueName: "IsDjinniInstalled"; ValueType: Dword; ValueData: "$1"; Components: TW1; Flags: uninsdeletekey
Root: HKLM; Subkey: "SOFTWARE\CD Projekt Red\The Witcher"; ValueName: "RegionVersion"; ValueType: String; ValueData: "WE"; Components: TW1; Flags: uninsdeletekey
Root: HKLM; Subkey: "SOFTWARE\CD Projekt Red\The Witcher"; ValueName: "InstallFolder"; ValueType: String; ValueData: "{app}\"; Components: TW1; Flags: uninsdeletekey

Установщик может выдать ошибку RegCreatekeyEx: сбой, код 89
или не выдать и втихаря все поставить но ключи в реестре HKLM не создать

Причем примерно до НГ установщик работал нормально, виню последние обновки безопасности майкрософта

Заранее благодарен

usermode 23-07-2018 19:53 2823188

если игра x64 и нужен доступ установщика к 64 бит разделам, то попробуй в секцию [Setup] прописать:
ArchitecturesInstallIn64BitMode=x64 ia64

Цитата:

Цитата R.i.m.s.k.y.
Причем примерно до НГ установщик работал нормально, виню последние обновки безопасности майкрософта »

тогда уж инсталлятор тоже надо обновить, далеко на необновляемых ResTools сборках не уехать.

R.i.m.s.k.y. 23-07-2018 20:43 2823198

usermode, нет игра х86

R.i.m.s.k.y. 23-07-2018 21:42 2823204

еще подскажите, пожалуйста, как сделать через bass так чтобы первый мр3 файл проигрался и перешел ко второму, а второй мр3 уже играл в цикле
сейчас в фоне играет только один мр3 в цикле
Код:

procedure InitializeWizard();
  ...
  ExtractTemporaryFile('BASS.dll');
  ExtractTemporaryFile('InnoCallback.dll');
  ExtractTemporaryFile('CallbackCtrl.dll');
  ExtractTemporaryFile('botva2.dll');
  ExtractTemporaryFile('volmax.png');
  ExtractTemporaryFile('volmin.png');
  ExtractTemporaryFile('volpb.png');
  ExtractTemporaryFile('voldote.png');
  ExtractTemporaryFile('MusicButton.png');
  ExtractTemporaryFile('mp3.mp3');
  BASS_Init(ExpandConstant('{tmp}\mp3.mp3'))
  BASS_CreateMediaPlayer(WizardForm, '{tmp}\volmax.png', '{tmp}\volmin.png', '{tmp}\volpb.png', '{tmp}\voldote.png', 110, 490);


usermode 24-07-2018 12:00 2823259

R.i.m.s.k.y.
тогда для записи в реестр использовать windows api.

R.i.m.s.k.y. 24-07-2018 12:04 2823262

Цитата:

Цитата usermode
тогда для записи в реестр использовать windows api »

можно пример для инно?

ErikPshat 31-07-2018 10:02 2824163

Не могу выудить переменную из кода GetOpenFileName. Вот пример:
Код:

procedure UnpackButtonClick(Sender: TObject);
var
  FileName: String;
begin
  // Set the initial filename
  FileName := '';
  if GetOpenFileName('', FileName, '', 'Archives Files (*.zip)|*.zip|All Files|*.*', 'zip') then
  begin
    // Successful; user clicked OK
    // FileName contains the selected filename
    MsgBox('Выбран архив {FileName}', mbInformation, MB_OK);
  end;
  if not ShellExec('open', ExpandConstant('{tmp}\7z.exe'), 'x -y {FileName}', ExpandConstant('{src}'), SW_SHOWNORMAL, ewnowait, ResultCode) then
  MsgBox(ExpandConstant('{code:NotFileOnDiskMsg}'), mbCriticalError,MB_OK);
end;

Делаю распаковку архивов и переменная {FileName} ничего не возвращает, ни в MsgBox, ни подхватывает выбранный файл при распаковке.

nik1967 31-07-2018 12:03 2824191

ErikPshat,
Скрытый текст

Код:

[Setup]
AppName = MyApp
AppVerName = MyApp
DefaultDirname = {pf}\MyApp
OutputDir=.

[Files]
Source: 7z.exe; Flags: dontcopy;

[code]
var
 
UnpackButton: TButton;
  PathTmp: String;

procedure UnpackButtonClick(Sender: TObject);
var
 
FileName: String;
  ResultCode: Integer;
begin
  if not
FileExists(PathTmp+'7z.exe') then ExtractTemporaryFile('7z.exe');
  // Set the initial filename
 
FileName := '';
  if GetOpenFileName('', FileName, '', 'Archives Files (*.zip)|*.zip|All Files|*.*', 'zip') then
  begin
   
// Successful; user clicked OK
    // FileName contains the selected filename
   
MsgBox('Выбран архив: '+FileName, mbInformation, MB_OK);
  end;
  if not ShellExec('open', ExpandConstant('{tmp}\7z.exe'), 'x -y '+FileName, ExpandConstant('{src}'), 0, ewnowait, ResultCode) then
 
MsgBox(ExpandConstant('{code:NotFileOnDiskMsg}'), mbCriticalError,MB_OK);
end;

procedure InitializeWizard();
begin
 
PathTmp:= ExpandConstant('{tmp}\');
  UnpackButton:= TButton.Create(WizardForm);
  with UnpackButton do begin
   
Parent:= WizardForm;
    SetBounds(ScaleX(10), ScaleY(327), ScaleX(75), ScaleY(25));
    Caption:= 'Распаковать';
    OnClick:= @UnpackButtonClick;
  end;
end;


ErikPshat 31-07-2018 12:48 2824195

nik1967, Классно, спасибо, отлично работает!!! Понятно, где я допустил ошибку в фигурных скобках.

Можно ещё развить тему?...
А теперь я пытаюсь распаковать архивы с мультивыбором GetOpenFileNameMulti.
Всё то же самое, в справке Inno Setup есть пример кода.
Но почему-то компилятор выдаёт ошибку "Unknown Identifier 'GetOpenFileNameMulti'".
Может есть рабочий пример аналогичного кода?

nik1967 31-07-2018 13:03 2824198

ErikPshat, скорее всего пользуешься расширенным компилятором. А GetOpenFileNameMulti прикрутили в поздних версиях инно. У меня в 5.5.9 уже не ругается.
Цитата:

Цитата ErikPshat
в справке Inno Setup »

Эта справка для 5.6.1, на сколько я помню.

zbz 31-07-2018 14:06 2824207

Ребята помогите пожалуйста, разобратся в скрите. Еле откопал в интернете вот этот скрипт:
скрипт
[Setup]
AppName=My Program
AppVersion=1.5
DefaultGroupName=My Program
DefaultDirName={pf}\My Program
DisableDirPage=yes

[Files]

Source: "D:\!ZBFlash\!АБУБоекомплект\InnoSetup\Projects\ABU\Core\Myprog1.exe"; DestDir: "C:\ABUTemp"
Source: "D:\!ZBFlash\!АБУБоекомплект\InnoSetup\Projects\ABU\Core\Myprog2.exe"; DestDir: "C:\ABUTemp"



[code]
var
MyOptionsPage: TInputOptionWizardPage;

procedure InitializeWizard;
begin
MyOptionsPage := CreateInputOptionPage(wpWelcome, 'Caption', 'Description',
'SubCaption', True, False);
MyOptionsPage.Add('install Myprog1');
MyOptionsPage.Add('install Myprog1');
MyOptionsPage.Values[0] := True;
end;

function ShouldInstallIcon: Boolean;
begin


Result := MyOptionsPage.Values[0];
end;


procedure CurPageChanged(CurPageID: Integer);
begin
If CurPageID=wpWelcome then
begin
SendMessage(WizardForm.NEXTBUTTON.Handle, 513, 0, 0)
SendMessage(WizardForm.NEXTBUTTON.Handle, 514, 0, 0)
end;
end;

и не могу понят куда и как написать, чтоб при соотвествуюшем выборе радио кнопки запускалась соотвествующий ехешник (Myprog1.exe или Myprog2.exe).

R.i.m.s.k.y. 31-07-2018 14:21 2824212

zbz, читать в справке про секцию components
Код:

[Components]
Name: Myprog; Description: Myprog;
Name: Myprog\Myprog1; Description: Myprog1; Flags: exclusive
Name: Myprog\Myprog2; Description: Myprog2; Flags: exclusive


[Files]
Components: Myprog\Myprog1; Source: "D:\!ZBFlash\!АБУБоекомплект\InnoSetup\Projects\ABU\Core\Myprog1.exe"; DestDir: "C:\ABUTemp"
Components: Myprog\Myprog2; Source: "D:\!ZBFlash\!АБУБоекомплект\InnoSetup\Projects\ABU\Core\Myprog2.exe"; DestDir: "C:\ABUTemp"


zbz 31-07-2018 14:45 2824217

Цитата:

Цитата R.i.m.s.k.y.
Components: Myprog\Myprog1; Source: "D:\!ZBFlash\!АБУБоекомплект\InnoSetup\Projects\ABU\Core\Myprog1.exe"; DestDir: "C:\ABUTemp" Components: Myprog\Myprog2; Source: "D:\!ZBFlash\!АБУБоекомплект\InnoSetup\Projects\ABU\Core\Myprog2.exe"; DestDir: "C:\ABUTemp" »

она же только копирует ехешники, а мне надо чтоб ехешник запускалось (или я что то не понял?!)

ErikPshat 31-07-2018 14:48 2824218

Да, ошибку выбивает китайский 5.5.1 ee2. Переключился на компилятор 5.6.1, проходит нормально. Но при условии, если я делаю через ExpandConstsnt:
Код:

MsgBox('Выбраны PKG: '+ExpandConstant('FileNameList'), mbInformation, MB_OK);
Позволяет выбрать множество файлов и парсит все выбранные файлы в одну строку, каждый в кавычках, как и должно быть. Но при попытке распаковать, MsgBox выводит необработанную строку:
Код:

Выбраны PKG: FileNameList
При нормальных условиях, без ExpandConstant, при компиляции выдаёт ошибку: Type mismatch.
Что-то не так снова в этой конструкции.

R.i.m.s.k.y. 31-07-2018 14:59 2824220

zbz, а) в твоем скрипте я не увидел запуска
б) лучше не использовать модификации инно если можно использовать стандартные средства инно
убрать кусок
Код:

MyOptionsPage: TInputOptionWizardPage;

procedure InitializeWizard;
begin
MyOptionsPage := CreateInputOptionPage(wpWelcome, 'Caption', 'Description',
'SubCaption', True, False);
MyOptionsPage.Add('install Myprog1');
MyOptionsPage.Add('install Myprog1');
MyOptionsPage.Values[0] := True;
end;

function ShouldInstallIcon: Boolean;
begin


Result := MyOptionsPage.Values[0];
end;

в) про запуск читать про секцию Run
Код:

[Run]

Components: Myprog\Myprog1; Filename: "C:\ABUTemp\Myprog1.exe"; Description: "Myprog1.exe"; Flags: skipifsilent runhidden
Components: Myprog\Myprog2; Filename: "C:\ABUTemp\Myprog2.exe"; Description: "Myprog2.exe"; Flags: nowait skipifsilent


mubbii 12-08-2018 00:42 2826007

Это мой первый пост, я использовал или просматривал OSZONE в течение нескольких месяцев (помог мне много ... :) новичок здесь).
У меня вопрос о наложении Thumbail для панели задач ... в частности, показывается ход установки. Я добавил скриншот, чтобы уточнить.

https://imgur.com/a/duLH1r7

Im в настоящее время использует (wintb) .dll для наложения эскизов и работает нормально, но я хочу, чтобы он отображал дополнительную информацию, например. ход установки и оставшееся время.

Если это возможно? отправляем. любая помощь оценена. Спасибо!

im с использованием inno 5.6.1 (u) и последней улучшенной.

nik1967 18-08-2018 08:52 2827210

mubbii, почитай здесь.

ChopMan 27-08-2018 02:39 2828722

Относительно недавно начал изучать конструкция написания скрипта для Inno Setup. И тут возникла проблема: На странице, где необходимо выбрать путь, куда будет устанавливаться программа, по умолчанию стоит путь, который прописан в DefaultDirName, к примеру это DefaultDirName={pf}. В том проблема, что если требуется изменить путь в ручную, то все к выставленному пути приписывается значение DefaultDirName, то есть я хочу установить путь на E:\Games, но выставляется в итоге E:\Games\Program Files , мне требуется, чтобы значение DefaultDirName не выставлялось при изменении пути.
В интернете искал как и на этом форуме, особо толку такого не нашёл. Помогите пожалуйста разобраться в данной проблеме.

nik1967 27-08-2018 07:17 2828727

ChopMan,
Справочку внимательно изучаем

[Setup]: AppendDefaultDirName
Возможные значения:
yes или no
Значение по умолчанию:
yes

Описание:
По умолчанию при указании пути на странице Выбор папки назначения с помощью кнопки Обзор... (Browse...) инсталлятор автоматически добавляет в конце имя папки, указанной в директиве DefaultDirName, в которую будет установлена программа. Например, если DefaultDirName={pf}\My Program и пользователь выбрал в обзоре диск "Z:\", то программа установится в "Z:\My Program".

Если значение директивы no, то папка с указанным DefaultDirName именем в конечном каталоге создаваться не будет. На странице выбора появится кнопка "Создать папку" (Make New Folder).


El Sanchez 05-10-2018 09:26 2834519

Цитата:

Цитата из ЛС
Можете обновить примеры для inno setup закрепления ярлыка на панели задач и в меню пуск? Те что есть не закрепляют на win10 pro.

PinToTaskbar

Код:

function PinToTaskbar(const FileName: string; IsPin: Boolean): Boolean;
// FileName : full path to executable file
// IsPin    : False - unpin from TaskBar, True - pin to TaskBar
var
 
ShellApp: Variant;
  Verb: string;
begin
 
Result := False;
  if not FileExists(FileName) then Exit;
  try
    if
IsPin then
     
Verb := 'taskbarpin' else
     
Verb := 'taskbarunpin';
    ShellApp := CreateOleObject('Shell.Application');
    ShellApp.Windows.Item.Document.Application.NameSpace(ExtractFileDir(FileName)).ParseName(ExtractFileName(FileName)).InvokeVerb(Verb);
    Result := True;
  except
   
ShowExceptionMessage;
  end;
end;


PinToStartMenu

Код:

function PinToStartMenu(const FileName: string; const IsPin: Boolean): Boolean;
// FileName : full path to exe- or lnk-file
// IsPin    : False - unpin from StartMenu, True - pin to StartMenu
var
 
ShellApp, FolderItem: Variant;
  Verb, LnkName: string;
begin
 
Result := False;
  if not FileExists(FileName) then Exit;
  try
   
ShellApp := CreateOleObject('Shell.Application');
    FolderItem := ShellApp.Windows.Item.Document.Application.NameSpace(ExtractFileDir(FileName)).ParseName(ExtractFileName(FileName));
    if GetWindowsVersion < $06020000 then // below Windows 8
   
begin
      if
IsPin then
       
Verb := 'startpin' else
       
Verb := 'startunpin';
      FolderItem.InvokeVerb(Verb);
      Result := True;
    end
    else 
// Windows 8 and above
   
begin
      if not
FolderItem.IsLink then
      begin
       
LnkName := FolderItem.ExtendedProperty('FileDescription');
        if LnkName = '' then
         
LnkName := ExtractFileName(FileName);
        LnkName := ExpandConstant('{commonprograms}\') + ChangeFileExt(LnkName, '.lnk');
        if IsPin then
         
Result := not FileExists(LnkName) and
           
FileExists(CreateShellLink(LnkName, '', FileName, '', '', '', 0, SW_SHOWNORMAL))
        else
         
Result := DeleteFile(LnkName);
      end
      else
      begin
       
LnkName := ExpandConstant('{commonprograms}\') + ExtractFileName(FolderItem.Path);
        if IsPin then
         
Result := not FileExists(LnkName) and
           
FileCopy(FolderItem.Path, LnkName, False)
        else
         
Result := DeleteFile(LnkName);
      end;
    end;
  except
   
ShowExceptionMessage;
  end;
end;


ROMKA-1977 08-10-2018 14:31 2834946

Здраствуйте. Помогите пож. разобратся с ярлыком деинсталятора в меню пуск.

Всегда указывал так:
[Icons]
Name: {group}\{cm:UninstallProgram,{#MyName}}; Filename: {uninstallexe}; Check: CheckError

Ярлык деинсталятора в меню пуск Win 7 отображался. Установив прогу в Win 10 ярлык деинсталятора не отображается. Заметил что такая же проблема и в инсталяторах других разработчиков.
Запустив установку в Win 10 в режиме совместимости с Win 7 всё нормально, рабочий ярлык на своём месте.

Прописал следующее:
[Icons]
Name: {group}\Деинсталлировать {#MyName}; Filename: {uninstallexe}; Check: CheckError

После этого всё норм, рабочий ярлык на своём месте.
В чем же проблема в первом случае ?

ErikPshat 08-10-2018 19:32 2834982

Цитата:

Цитата ROMKA-1977
{cm:UninstallProgram,{#MyName}}; »

Наверное лучше писать так:
Код:

{cm:UninstallProgram} {#MyName};

ErikPshat 09-10-2018 15:12 2835093

Ребята, нубский вопрос...
Как средствами Inno Setup создать новый пустой текстовой файл?

Я знаю только один хак создания через лист:
Код:

var
  List: TStringList; txt: string; res: Integer;
begin
  txt:= ExpandConstant('{tmp}\file.txt');
  List:= TStringList.Create;
  List.Add('Добавляем первую строку в файл');
  List.SaveToFile(txt);
  List.Free;
end;

Может быть можно просто написать эту строку отдельно, как самостоятельную:
Код:

SaveToFile(file.txt);
Но по-моему к этому должна предшествовать какая-та трансляция.

El Sanchez 09-10-2018 15:50 2835102

Цитата:

Цитата ROMKA-1977
Всегда указывал так:
[Icons]
Name: {group}\{cm:UninstallProgram,{#MyName}}; Filename: {uninstallexe}; Check: CheckError »

ROMKA-1977, если UninstallProgram вынесен во внешний файл, то проверьте его кодировку, должна быть UTF-8. Либо CheckError возвращает False на Win 10.
Цитата:

Цитата ErikPshat
Наверное лучше писать так: »

ErikPshat, там все правильно написано, читайте справку.
Цитата:

Цитата ErikPshat
Как средствами Inno Setup создать новый пустой текстовой файл? »

ErikPshat,
Код:

SaveStringToFile(ExpandConstant('{tmp}\file.txt'), '', False);


ErikPshat 09-10-2018 16:09 2835106

El Sanchez, о да, спасибо, проверил работает.
Если указано False, тогда перезаписывает файл, а если указать True, тогда записывает строку в конец файла.

А я перелопатил в документации весь хэлп и почему-то пропустил эту команду. Оказывается она там есть )))
Спасибо ещё раз!

ErikPshat 09-10-2018 18:47 2835134

Подскажите пожалуйста, как проверить наличие записи в INI-файле?

У меня в секцию [CONFIG] записывается ключ "InstallDirectory" с путём в параметре. И я делаю отдельную функцию на его считывание:
Код:

function InsDir(Default:String):String;
  Begin
    Result:= GetIniString('CONFIG','InstallDirectory','',ExpandConstant('{tmp}\config.ini'));
  end;

А теперь мне нужно проверить, присутствует ли ключ с параметром. Если да, то я его считываю. Если нет, то я беру данные из другого ключа. Ну типа как-то так:
Код:

if (ExpandConstant('{code:InsDir}') > 0) then begin DIR:= ExpandConstant('{code:InsDir}') end else
if (ExpandConstant('{code:NewDir}') > 0) then begin DIR:= ExpandConstant('{code:NewDir}') end;

То есть, я не знаю с чем сравнивать. Правильно ли будет узнавать наличие ключа, потому что он больше нуля?
Мне нужно на переменную DIR назначить существующий ключ.

ROMKA-1977 09-10-2018 20:47 2835150

Цитата:

Цитата ErikPshat
{cm:UninstallProgram} {#MyName}; »

В данном вами примере инсталятор берёт полное название ярлыка из файла Russian.isl и получается в итоге - Деинсталлировать %1MyName
Может есть какойто метод оптимизации секции [Icons] не прибегая к подробному тексту - Name: {group}\Деинсталлировать {#MyName}; Filename: {uninstallexe}; Check: CheckError
Уточняю проблему - это только но win 10 и подобное не только у моих инсталяшек

ErikPshat 09-10-2018 21:08 2835154

ROMKA-1977, вам выше совет дал El Sanchez, вы читали?
То есть, вы вписали ключ MyName в файл Russian.isl и теперь хотите вывести его в секции [Icons]?
А почему бы в шапке не написать через
Код:

#define  MyName  "Моё Название"
а потом выводить куда захочешь?
Или в секцию CustomMessage через en. и ru.

Кстати, нужно бы параметры в кавычки брать, а у вас без кавычек. Просто в Inno Setup иногда запятая всё решает.
Из меня правда плохой советчик, кто бы мне самому подсказал, но у меня в секции [Icons] всегда так:
Код:

[Icons]
Name: "{group}\{cm:UninstallProgram,{#MyName}}"; Filename: "{uninstallexe}"; Check: "CheckError";


AnastasiyaM 20-10-2018 16:45 2836730

Ребята, помогите, пожалуйста.
Есть задача, при установке программы создавать нового пользователя windows и добавлять программу в автозагрузку только ему (во время установки программы но не является текущим пользователем.) Пробовала получать SID пользователя после создания, но видимо из-за нехватки опыта получается какая-то ерунда. Выкладываю свои попытки, может подскажете как можно поправить?

Код:

[Registry]
Root: HKU; Subkey: {code:GetUserSid}\Software\Microsoft\Windows\CurrentVersion\Run; ValueName: {#MyAppExeName}; ValueType: string; ValueData: {app}\{#MyAppExeName};

[Run]
;  здесь я создаю пользователя и пыталась сделать его загружаемым по умлочания после перезагрузки, но пока точно работает только первая строчка :)
Filename: net.exe; parameters: "user Visitor /add /fullname:""Visitor"" /comment:""TEST"" /expires:never /passwordchg:no"
Filename: reg.exe; parameters: "ADD HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon /v AutoAdminLogon /t REG_SZ /d 1";
Filename: reg.exe; parameters: "ADD HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon /v DefaultUserName /t REG_SZ /d 'Visitor'"; 
[Code]
function GetUserSid(ExecStdout: string):string;
var
  TmpFileName: string;
  ResultCode: integer;
  Params: string;

  begin
TmpFileName := ExpandConstant('{tmp}') + '\sid_results.txt';
    Exec(ExpandConstant('{cmd}'), ' /C wmic useraccount where name=''Visitor'' get sid > "' + TmpFileName + '"', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
      if LoadStringFromFile(TmpFileName, ExecStdout) then
        begin   
        MsgBox(ExecStdout, mbInformation, MB_OK);
        end
      else
        begin
        MsgBox('Installing Error', mbError, MB_OK);
        end;
    DeleteFile(TmpFileName);
    end;


Chudmin 21-10-2018 22:26 2836907

Здравствуйте!
Подскажите пожалуйста, как реализовать, чтобы при запуске инсталятора, например, "Моя_прога", если запущена уже ранее установленная программа "Моя_прога.exe", то сразу же, без вопросов, "Моя_прога.exe" закрывалась?

Iska 21-10-2018 23:00 2836909

Chudmin, вообще-то, в этом случае инсталлятор не должен «сразу же, без вопросов» закрываться.

Chudmin 22-10-2018 05:44 2836925

Цитата:

Цитата Iska
в этом случае инсталлятор не должен «сразу же, без вопросов» закрываться. »

Вы не правильно меня поняли. Есть программа "Моя_прога" и есть инсталятор к ней "Моя_прога_Setup", так вот, если у пользователя уже установлена "Моя_прога" и запущена, а в это время он запускает (при работающей "Моя_прога") инсталятор "Моя_прога_Setup", то инсталятор сразу же, "молчком", закрывает программу "Моя_прога".

Iska 22-10-2018 05:46 2836926

Chudmin, и этого быть не должно (разве что «Моя_прога» — это сервис).

Chudmin 22-10-2018 06:01 2836927

Цитата:

Цитата Iska
и этого быть не должно »

Ну, должно или не должно, это другой вопрос, главное что такое работает, например в репаках уважаемого Elchupacabra.

ErikPshat 22-10-2018 06:39 2836928

Chudmin,
Код:

[UninstallRun]
Filename: "{sys}\taskkill.exe"; Parameters: "/f /im Моя_прога.exe"; Flags: skipifdoesntexist runhidden

или использовать сразу в секции Files параметр BeforeInstall для уничтожения процесса перед установкой:
Код:

[Files]
Source: "Моя_прога.exe"; DestDir: "{app}"; Flags: ignoreversion; BeforeInstall: TaskKill('Моя_прога.exe')

[ Code ]
procedure TaskKill(FileName: String);
var
  ResultCode: Integer;
begin
    Exec(ExpandConstant('taskkill.exe'), '/f /im ' + '"' + FileName + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;


Chudmin 22-10-2018 07:17 2836931

Цитата:

Цитата ErikPshat
или использовать сразу в секции Files параметр BeforeInstall для уничтожения процесса перед установкой: »

Спасибо большое, этот метод как раз близок к моему желанию (в отличии от [UninstallRun]). Я только недавно стал вникать в тонкости Inno Setup, так-что чайник в полном смысле этого слова, а в секции [code], так вообще на уровне скопировал, посмотрел результат, так-что Ваш пример в мою копилку, на которых (в том числе) я буду постигать азы [code].

И всё-таки, у Elchupacabra этот процесс происходит сразу же после запуска инсталятора, КАК? Конечно и Ваш способ работает и выполняет свою функцию, но хотелось бы знать как сделать в самом начале, чисто академический интерес.

boss911 22-10-2018 16:00 2836987

Цитата:

Цитата Chudmin
Есть программа "Моя_прога" и есть инсталятор к ней "Моя_прога_Setup", так вот, если у пользователя уже установлена "Моя_прога" и запущена, а в это время он запускает (при работающей "Моя_прога") инсталятор "Моя_прога_Setup", то инсталятор сразу же, "молчком", закрывает программу "Моя_прога". »

Предложу использовать библиотеку KillProc.dll для Inno Setup.
Код:

[Files]
Source: C:\MyProg\MyProg.exe; DestDir: {app}; Flags: ignoreversion; BeforeInstall: KillProc
Source: compiler:Libraries\KillProc.dll; DestDir: {tmp}; Flags: dontcopy

[Code]
function KillProcByExeName(ProcessName: PAnsiChar; ExcludeID: Cardinal): Integer; external 'KillProcByExeName@files:KillProc.dll stdcall';

procedure KillProc;
begin
  KillProcByExeName('MyProg.exe', 0);
end;

Если в момент установки будет запущен процесс с именем MyProg.exe, то перед копированием файла MyProg.exe, данный процесс будет принудительно завершен. Метод старый, возможно уже есть другие решения, с проверкой ID процесса.

Правильно или не правильно, но если MyProg.exe не служба и нет ключа командной строки для завершения работы, а процесс без вопросов необходимо завершить и по другому ни как, то это единственный вариант, и уже закрываешь глаза на то, что это не правильно. ИМХО.

ErikPshat 22-10-2018 21:21 2837055

Цитата:

Цитата boss911
Предложу использовать библиотеку KillProc.dll для Inno Setup. »

Не понимаю зачем, если это делается стандартными средствами. Ну может быть для кого-то это может оказаться единственно рабочим решением.

Цитата:

Цитата Chudmin
И всё-таки, у Elchupacabra этот процесс происходит сразу же после запуска инсталятора, КАК? »

Ну так всё зависит от того, когда выполняется ваш код. Сколько у вас файлов в секции [Files] и когда они запускаются?
Скорее всего ваши файлы смирно сидят в инсталляторе и терпеливо ждут, пока юзер не пройдёт все этапы, проставит галочки, там создавать ярдыки на рабочем столе, выбирает дополнения, путь установки, а тоько в заключении жмёт кнопку "Установить". Вот тогда и активируется ваша "Моя_прога.exe", а перед её запуском и начинается поиск процесса и его уничтожение.

Чтобы процесс уничтожался сразу при запуске инсталлятора, нужно чтобы у вас в [Files] был бы назначен на BeforeInstall какой-нибудь файлик, который бы извлекался в %TEMP% именно при запуске инсталлятора, а не по нажатию кнопки "Установить".

Для примера, вы можете прикрепить к инсталлятору Сплэш-заставку и заодно на неё повесить убийцу процесса:
Код:

[Files]
; Файлы Splash-заставки, загружаются первыми
Source: Include\isgsg.dll; DestDir: {tmp}; Flags: dontcopy nocompression; BeforeInstall: TaskKill('Моя_прога.exe')
Source: Include\Splash.png; DestDir: {tmp}; Flags: dontcopy nocompression

В секции [ Code ] объявляете процедуру заставки и процедуру убийцы процесса в самом начале:
Код:

[ Code ]
{ Splash заставка }
procedure ShowSplashScreen(p1:HWND;p2:AnsiString;p3,p4,p5,p6,p7:integer;p8:boolean;p9:Cardinal;p10:integer);
    external 'ShowSplashScreen@files:isgsg.dll stdcall delayload';
procedure TaskKill(FileName: String);var ResultCode: Integer;begin
    Exec(ExpandConstant('taskkill.exe'),'/f /im '+'"'+FileName+'"','',SW_HIDE,ewWaitUntilTerminated,ResultCode);end;

Этот код извлечения и запуска заставки вставляете в нужном вам месте. Я её разместил после всей массы программного кода в конец, но перед отрисовкой формы окна:
Код:

{ Splash заставка }
procedure Splash();
begin
  ExtractTemporaryFile('Splash.png');
  ShowSplashScreen(WizardForm.Handle,ExpandConstant('{tmp}\Splash.png'),500,800,500,0,255,True,$FFFFFF,10);
end;

И в конце кода инициализируете её:
Код:

procedure InitializeWizard();
begin
  Splash();
end;

Таким образом, при запуске программы сразу извлекаются файлы заставки в %TEMP% и запускается заставка перед стартом инсталлятора, но ещё перед этим, запускается убийца процесса, потому что на файл заставки выставлен флаг BeforeInstall.

AnastasiyaM 22-10-2018 22:54 2837096

Цитата:

Цитата AnastasiyaM
Есть задача, при установке программы создавать нового пользователя windows и добавлять программу в автозагрузку только ему (во время установки программы но не является текущим пользователем.) Пробовала получать SID пользователя после создания, но видимо из-за нехватки опыта получается какая-то ерунда. Выкладываю свои попытки, может подскажете как можно поправить? »

В общем, не смогла победить задачу средствами инсталлятора, сделала bat файл, который находит SID и прописывает в автозапуск программу. Теперь новая проблема. Если запускаю свой bat в новом пользователе, то он успешно отрабатывает. А если в том пользователе, под которым создаю нового, то пишет "неверный параметр". В связи с этим ломаю теперь голову над задачей:
1. установить программу
2. создать попутно нового пользователя
3. перезагрузить систему и зайти под новым пользователем
4. запустить bat файл.
И это все должен делать инсталлятор.
Видела примеры как делают продолжение установки после перезагрузки, но очень слабо понимаю, что куда там нужно вписать (
Буду очень благодарна за советы, примеры, объяснения

Iska 22-10-2018 23:47 2837108

AnastasiyaM, в Вашем случае пользователя мало создать: у новосозданного пользователя отсутствует профиль. Просто запустите программно какое-либо приложение от имени новосозданного пользователя, дождитесь его завершения, и только затем пытайтесь что-либо делать с его разделами реестра или путями в его профиле.

AnastasiyaM 22-10-2018 23:56 2837112

Цитата:

Цитата Iska
AnastasiyaM, в Вашем случае пользователя мало создать: у новосозданного пользователя отсутствует профиль. Просто запустите программно какое-либо приложение от имени новосозданного пользователя, дождитесь его завершения, и только затем пытайтесь что-либо делать с его разделами реестра или путями в его профиле. »

Большое спасибо за совет, буду копать в этом направлении!

ErikPshat 23-10-2018 03:29 2837125

Цитата:

Цитата AnastasiyaM
В общем, не смогла победить задачу средствами инсталлятора, сделала bat файл, который находит SID и прописывает в автозапуск программу. Теперь новая проблема. Если запускаю свой bat в новом пользователе, то он успешно отрабатывает. А если в том пользователе, под которым создаю нового, то пишет "неверный параметр". В связи с этим ломаю теперь голову над задачей: »

Это уже называется вирусописание, а не инсталлятор )))

Chudmin 23-10-2018 08:06 2837135

Цитата:

Цитата ErikPshat
Таким образом, при запуске программы сразу извлекаются файлы заставки в %TEMP% и запускается заставка перед стартом инсталлятора, но ещё перед этим, запускается убийца процесса, потому что на файл заставки выставлен флаг BeforeInstall. »

При компиляции выдаёт ошибку на строке " Splash();" - Unknown identifier 'Splash'.

ErikPshat 23-10-2018 08:38 2837138

Вложений: 1
Цитата:

Цитата Chudmin
При компиляции выдаёт ошибку на строке " Splash();" - Unknown identifier 'Splash'. »

Ой, забыл добавить код извлечния ))) мы же 2 файла только добавилив в [Files], чтобы программа паковала их и таскала с собой. А кто извлекать файлы будет, чтобы они заработали? Они в нужный момент в нужной части кода должны извлекаться командой ExtractTemporaryFile и следом запускать отображение заставки.

Вот, нужно ещё код извлечения и активации нужно добавить в подходящее вам место:
Код:

{ Splash заставка }
procedure Splash();
begin
  ExtractTemporaryFile('Splash.png');
  ShowSplashScreen(WizardForm.Handle,ExpandConstant('{tmp}\Splash.png'),500,800,500,0,255,True,$FFFFFF,10);
end;

Если что, DLL-ку isgsg.dll Splash-заставки залил во вложение. Картинку с прозрачностью Splash.png свою добавите.

Chudmin 23-10-2018 09:07 2837142

Цитата:

Цитата ErikPshat
Вот, нужно ещё код извлечения и активации нужно добавить в подходящее вам место: »

Спасибо за отзывчивость! Но похоже сначала мне нужно в секции "Коде" изучить азы, что за что отвечает, и как правильно это пишется, а то выходит ошибка (как и сейчас), а я вообще ничего не понимаю, от слова совсем. Не буду же по каждому пустяку просить людей, чтобы мне разжевали и в рот положили.

Дайте совет, что, где почитать в этом направлении, чтобы хоть что-то понимать?

ErikPshat 23-10-2018 09:57 2837148

Chudmin, ну так в Inno Script Studio нажмите в меню Помощь -> Документация Inno Setup и изучайте.
Используется Pascal, простейший язык для изучения.

Я именно со справки и начинал. Когда делал свою первую программу, сутки посидел, поискал решения своих задач, так там всё и нашёл, там много примеров практически по всем направлениям, собранных по вопросам и ответам на форумах. Ну и за сутки я практически освоил все приёмы по кодингу в этой программе.
Скачайте последнюю версию русской справки: http://krinkels.org/threads/russkaja...no-setup.2083/
Замените CHM в папке с программой C:\Program Files (x86)\Inno Setup 5\
Посмотрите сборник скриптов и примеров: http://krinkels.org/threads/faq-po-inno-setup.7/
Покомпилируйте готовые рабочие скрипты: http://krinkels.org/forums/skripty-dlja-inno-setup.256/
Ну и на их примере попытайтесь сделать что-нибудь своё.

Chudmin 23-10-2018 14:01 2837187

Цитата:

Цитата ErikPshat
Используется Pascal, простейший язык для изучения. »

Нашёл я свою ошибку, Splash-заставка отработала, а вот taskkill нет.

AnastasiyaM 23-10-2018 17:18 2837222

Цитата:

Цитата Iska
AnastasiyaM, в Вашем случае пользователя мало создать: у новосозданного пользователя отсутствует профиль. Просто запустите программно какое-либо приложение от имени новосозданного пользователя, дождитесь его завершения, и только затем пытайтесь что-либо делать с его разделами реестра или путями в его профиле. »

Еще раз спасибо, почти получилось сотворить чудо.
Только bat файл запрашивает пароль нового пользователя, когда запускает что-то от его имени (без пароля отказывается работать). Есть ли способ, как ему его передать в инсталятор? что то вроде Filename: cmd.exe; parameters: "{app}\my.bat %pas"; ?

Цитата:

Цитата ErikPshat
Это уже называется вирусописание, а не инсталлятор ))) »

не :) специфические требования :)

ErikPshat 23-10-2018 20:10 2837253

Цитата:

Цитата Chudmin
Нашёл я свою ошибку, Splash-заставка отработала, а вот taskkill нет. »

Ну попробуйте повесить taskkill на иконку заставки или на другие файлы, которые загружаются первыми.
Вполне возможно, что команда извлечения ExtractTemporaryFile действует принудительно, в обход стандартного функционала инсталлятора и поэтому флаги из секции [Files] не отрабатывают. По-моему так и есть, флаги там работают только при стандартных действиях инсталлятора, т.е. при нажатии кнопки Install на конечном этапе. А у вас до этого не доходит и вы вызываете Taskkill до запуска инсталлятора из секции [ Code ] программы.

Поэтому нужно искать другое решение, т.е. как-то вызывать taskkill из кода программы, либо подключать библиотеку taskkill.dll или KillProc.dll и вызывать его через [external 'KillProcByExeName@files:KillProc.dll stdcall], как недавно выкладывал код boss911
здесь: http://forum.oszone.net/thread-33414...essage_2836987
здесь: http://forum.oszone.net/thread-33414...ml#edit2836987
здесь: http://forum.oszone.net/thread-33414...ml#post2836987

Chudmin 23-10-2018 20:14 2837254

Цитата:

Цитата ErikPshat
Поэтому нужно искать другое решение, т.е. как-то вызывать taskkill из кода программы, либо подключать библиотеку taskkill.dll или KillProc.dll и вызывать его через [external 'KillProcByExeName@files:KillProc.dll stdcall], как недавно выкладывал код boss911 здесь: http://forum.oszone.net/thread-33414...essage_2836987 »

Да, буду думать-экспериментировать.

Iska 23-10-2018 21:23 2837269

Цитата:

Цитата AnastasiyaM
Только bat файл запрашивает пароль нового пользователя, когда запускает что-то от его имени (без пароля отказывается работать). Есть ли способ, как ему его передать в инсталятор? »

Это Вам надо «местных» коллег, специалистов по InnoSetup Pascal Scripting, озадачить данным вопросом, дабы подсказали.

ErikPshat 23-10-2018 22:09 2837274

Цитата:

Цитата AnastasiyaM
Только bat файл запрашивает пароль нового пользователя, когда запускает что-то от его имени (без пароля отказывается работать). Есть ли способ, как ему его передать в инсталятор? что то вроде Filename: cmd.exe; parameters: "{app}\my.bat %pas"; ? »

Скорее всего созданный пользователь не является Администратором и не имеет прав. Вам нужно нового пользователя назначить Администратором компьютера. Может быть как-то так получится:
Код:

@echo Добавление нового пользователя
@echo off
 set user_name=Vasia_Pupkin
 set user_passw=12345678
echo.
echo 1. Добавление нового пользователя
 net user %user_name% %user_passw% /add /expires:never /fullname:%user_name%
echo.
echo 2. Обновление свойств пользователя
echo.
 wmic path UserAccount where "Name='%user_name%'" set PasswordExpires=false /nointeractive
echo.
echo 3. Добавление в группу "Администраторы" и удаление из "Пользователя"
 net localgroup "Администраторы" %user_name% /add
 net localgroup "Пользователи" %user_name% /delete
@pause


Iska 23-10-2018 22:29 2837278

ErikPshat, чего, кого?

Цитата:

Цитата ErikPshat
Скорее всего созданный пользователь не является Администратором и не имеет прав. »

И не должен являться. Этого не требуется ни по условию техзадания, ни для реализации.

Цитата:

Цитата ErikPshat
Вам нужно нового пользователя назначить Администратором компьютера. »

Не нужно. Совсем. И этого не требуется ни по условию техзадания, ни для реализации.

Нужно: реализация на InnoSetup Pascal Scripting функции CreateProcessAsUser/CreateProcessWithLogon.

ErikPshat 23-10-2018 22:41 2837280

Iska, ну я написал код батника, можно всё перенести в код Inno Setup.
А почему тогда, при создании нового пользователя, после запуска батника, требует ввод пароля?
Потому что созданный пользователь является просто Гостем и для него всегда будет запршиваться пароль.

AnastasiyaM 23-10-2018 23:16 2837286

Цитата:

Цитата ErikPshat
Iska, ну я написал код батника, можно всё перенести в код Inno Setup.
А почему тогда, при создании нового пользователя, после запуска батника, требует ввод пароля?
Потому что созданный пользователь является просто Гостем и для него всегда будет запршиваться пароль. »

Iska прав, задача создать пользователя и прописать ему ключи в реестр. Но так как у нового пользователь нет профиля, пока в него никто не логинился, я пытаюсь запустить от его имени какой-то процесс. Пароль просит именно нового пользователя. Если создавать пользователя без пароля, то ranas команда вообще отказывается работать :(

ErikPshat 24-10-2018 00:28 2837290

AnastasiyaM, ну так я что-то недогоняю. Я же вам и предложил код, который:

1. Создаёт нового пользователя с Именем и Паролем.
2. Настраивает пользователя, т.е. ставит галочку, что Пароль не временный, а "Срок действия пароля не ограничен".
3. Делает пользователя Админом и даёт права на выполнение действий без ввода пароля.

Теперь вы можете от его имени запускать необходимые процессы, без запроса пароля.
И команду ranas можете выполнять.

AnastasiyaM 24-10-2018 01:17 2837291

ErikPshat, нужен обязательно бесправный пользователь.
Цитата:

Цитата ErikPshat
3. Делает пользователя Админом и даёт права на выполнение действий без ввода пароля. »

Даже если он еще никогда не логинился? Я попробовала вставить Ваш код, он все равно пароль запросил и я пошла искать другие способы. Может что-то не так сделала..

Я пока сделала такой костыль в секции
Код:

[Code]
Exec(ExpandConstant('runas'), ' /user:MyUser cmd.exe', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ErrorCode);

теперь во время установки сообщение командной строки с запросом пароля появляется на экране. Не идеально, но работает :)

El Sanchez 24-10-2018 12:36 2837348

AnastasiyaM, вам нужно создавать пользователя уже с паролем, иначе на первом же логоне система скажет ни-ни, потом создать профиль и получить SID. Вот пример без автологона и с требованием пароля при первом входе. Пароль и прочие настройки вам все равно придется в учетке пользователя делать.
Скрытый текст

Код:

[Registry]
#define UserName "Visitor"
Root: HKU; Subkey: {code:GetUserSid|{#UserName}}\Software\Microsoft\Windows\CurrentVersion\Run; ValueName: {#MyAppExeName}; ValueType: string; ValueData: {app}\{#MyAppExeName}; Check: CheckCreateUser('{#UserName}')

[Code]
#define A = (Defined UNICODE) ? "W" : "A"
const
  ERROR_SUCCESS = 0;
  ERROR_INSUFFICIENT_BUFFER = 122;
  LOGON32_LOGON_INTERACTIVE = 2;
  LOGON32_PROVIDER_DEFAULT = 0;

type
  TProfileInfo = record
    dwSize: DWORD;
    dwFlags: DWORD;
    lpUserName: string;
    lpProfilePath: string;
    lpDefaultPath: string;
    lpServerName: string;
    lpPolicyPath: string;
    hProfile: THandle;
  end;

function LookupAccountName(lpSystemName, lpAccountName: string;
  var Sid: Byte; var cbSid: DWORD; ReferencedDomainName: string;
  var cbReferencedDomainName: DWORD; var peUse: LongWord): BOOL; external 'LookupAccountName{#A}@advapi32.dll stdcall';
function ConvertSidToStringSid(var Sid: Byte; var StringSid: LongWord): BOOL; external 'ConvertSidToStringSid{#A}@advapi32.dll stdcall';
function LogonUser(lpszUsername, lpszDomain, lpszPassword: string;
  dwLogonType, dwLogonProvider: DWORD; var phToken: THandle): BOOL; external 'LogonUser{#A}@advapi32.dll stdcall';
function LoadUserProfile(hToken: THandle; var lpProfileInfo: TProfileInfo): BOOL; external 'LoadUserProfile{#A}@userenv.dll stdcall';
function UnloadUserProfile(hToken, hProfile: THandle): BOOL; external 'UnloadUserProfile@userenv.dll stdcall';
function CloseHandle(hObject: THandle): BOOL; external 'CloseHandle@kernel32.dll stdcall';

function CheckCreateUser(const UserName: string): Boolean;
var
  TempPassword: string;
  UserToken: THandle;
  ProfileInfo: TProfileInfo;
  ResultCode: Integer;
begin
  Result := False;
  try
    { Create user account. }
    TempPassword := 'PqYDLMAD';
    if not Exec(ExpandConstant('{cmd}'), Format('/c net user "%s" "%s" /add /expires:never', [UserName, TempPassword]), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) or
      (ResultCode <> ERROR_SUCCESS) then Exit;

    { Create user profile. }
    if not LogonUser(UserName, '.', TempPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, UserToken) then
      RaiseException(SysErrorMessage(DLLGetLastError));
    ProfileInfo.dwSize := SizeOf(ProfileInfo);
    ProfileInfo.lpUserName := UserName;
    if not LoadUserProfile(UserToken, ProfileInfo) and
      not UnloadUserProfile(UserToken, ProfileInfo.hProfile) then
      RaiseException(SysErrorMessage(DLLGetLastError));

    { Change user account. }
    if not Exec(ExpandConstant('{cmd}'), Format('/c net user "%s" "" /logonpasswordchg:yes', [UserName]), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) or
      (ResultCode <> ERROR_SUCCESS) then Exit;

    Result := True;
  except
    ShowExceptionMessage;
  finally
    if UserToken <> 0 then
      CloseHandle(UserToken);
  end;
end;

function GetUserSid(const UserName: string): string;
var
  Sid: array of Byte;
  DomainName: string;
  SidSize, DomainNameSize: DWORD;
  Buffer: LongWord;
begin
  Result := '';
  try
    SetArrayLength(Sid, 1);
    if not LookupAccountName('', UserName, Sid[0], SidSize, '', DomainNameSize, Buffer) and
      BOOL(DLLGetLastError <> ERROR_INSUFFICIENT_BUFFER) then Exit;
    SetArrayLength(Sid, SidSize);
    DomainName := StringOfChar(#0, DomainNameSize - 1);
    if not LookupAccountName('', UserName, Sid[0], SidSize, DomainName, DomainNameSize, Buffer) and
      BOOL(DLLGetLastError <> ERROR_SUCCESS) then
      RaiseException(SysErrorMessage(DLLGetLastError));
    if not ConvertSidToStringSid(Sid[0], Buffer) then
      RaiseException(SysErrorMessage(DLLGetLastError));
    Result := CastIntegerToString(Buffer);
  except
    ShowExceptionMessage;
  finally
  end;
end;


Chudmin 24-10-2018 14:34 2837362

Цитата:

Цитата ErikPshat
флаги там работают только при стандартных действиях инсталлятора, т.е. при нажатии кнопки Install на конечном этапе. А у вас до этого не доходит и вы вызываете Taskkill до запуска инсталлятора из секции [ Code ] программы. »

Похоже так и есть - я прикрутил скин, файлы скина делал через Темп, без копирования и с копированием в {app}, с флагом BeforeInstall - TaskKill не отрабатывал, а вот при установке отрабатывает.

AnastasiyaM 24-10-2018 14:36 2837364

Цитата:

Цитата El Sanchez
Вот пример без автологона и с требованием пароля при первом входе. Пароль и прочие настройки вам все равно придется в учетке пользователя делать. »

Это очень круто! Спасибо вам большое за помощь! Я бы такую красоту в жизни не написала :yahoo:

pollipen 28-10-2018 20:37 2838162

Парни скажите как сделать средствами Inno Setup
короче при распаковки инстал. запускается другой с папки tmp, но он запаролен скажем 12345
так вот как мне сделать что бы он автоматом запускался без вода в ручную пароля

Iska 28-10-2018 21:09 2838166

Цитата:

Цитата pollipen
так вот как мне сделать что бы он автоматом запускался без вода в ручную пароля »

Inno Setup command line - Поиск в GoogleSetup Command Line Parameters:
Цитата:

/PASSWORD=password

Specifies the password to use. If the [Setup] section directive Password was not set, this command line parameter is ignored.

When an invalid password is specified, this command line parameter is also ignored.

pollipen 29-10-2018 11:40 2838234

что то ни как ни пойму
wwwww.exe он запаролен
Скрытый текст
#define MyAppName "My Program"
#define MyAppVersion "1.5"
#define MyAppPublisher "My Company, Inc."
#define MyAppURL "http://www.example.com/"
#define MyAppExeName "MyProg.exe"

[Setup]
AppId={{4F1F4C94-0955-42AB-9AEF-23D33908F46C}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
OutputBaseFilename=setup
Compression=lzma
SolidCompression=yes


[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "C:\Program Files (x86)\Inno Setup 5\Examples\MyProg.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Users\ww\Desktop\wwwww.exe"; DestDir: "{tmp}"; Flags: ignoreversion

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Run]
Filename: "{tmp}\wwwww.exe"; Parameters: "/PASSWORD=12345"

ErikPshat 29-10-2018 17:41 2838282

pollipen, чёт мне показалось, что речь шла про секцию [Setup], а не про [RUN].
Хотя и в секции [ Code ] любые параметры запуска приложения имеют возможность выставить параметры запуска.

pollipen 30-10-2018 11:44 2838393

ErikPshat
хорошо тогда как через [ Code ]

ErikPshat 30-10-2018 13:52 2838415

pollipen, ну как мы запускаем любые экзешники через "ShellExec" или "Exec". Там на втором месте указываются параметры к экзешнику.
Вот пример извлечения запароленных архивов 7-Zip:
Код:

; Дефайним переменные
#define  Name      "My_Program_Name"
#define  UserName  "by pollipen"
#define  Version    "1.0.0.0"
#define  Publisher  "pollipen © OsZone Team"
#define  ExeName    "My_Program_Name"
;
; Точка с запятой - это комментарий
;
; Выставляем стандартные параметры программы в секции Setup:
[Setup]
;VersionInfoCompany=Название компании
VersionInfoCompany={#Publisher}

;VersionInfoCopyright=Авторские права
VersionInfoCopyright=(c) 2006-2018 {#Publisher}

;VersionInfoDescription=Описание файла
VersionInfoDescription={#Name} {#UserName}

;VersionInfoProductName=Название продукта
VersionInfoProductName={#Name}

;VersionInfoProductVersion=1.0.0.0 (Версия продукта цифровая)
VersionInfoProductVersion={#Version}

;VersionInfoProductTextVersion=Производитель
VersionInfoProductTextVersion={#Publisher}

;VersionInfoTextVersion=Версия файла текстовая
VersionInfoTextVersion={#Version} Final

;VersionInfoVersion=1.0.0.0 (Версия файла цифровая)
VersionInfoVersion={#Version}
;
; Таскаем (пакуем) с собой экзешник и INI (для примера) в программе:
[Files]
Source: Include\7z.exe; DestDir: {tmp}; Flags: dontcopy
Source: Include\7z.dll; DestDir: {tmp}; Flags: dontcopy
Source: Include\RUS\Config_en.ini; DestDir: {tmp}; Flags: dontcopy
Source: Include\ENG\Config_en.ini; DestDir: {tmp}; Flags: dontcopy
;
; Выставляем поддерживаемые языки в программе:
[Languages]
Name: en; MessagesFile: compiler:Default.isl
Name: ru; MessagesFile: compiler:Languages\Russian.isl
;
; Заменяем стандартные диалоги на свои любимые:
[Messages]
SetupAppTitle={#Name}
SelectLanguageTitle={#Name}
ru.SelectLanguageLabel=Выберите язык, который будет использован в программе распаковки:
en.SelectLanguageLabel=Select the language to use in the unpacking program:
;
; Добавляем свои кастомные диалоги:
[CustomMessages]
ru.SelectArch=Выберите файл архива для распаковки
ru.SelectedArch=Выбран архивный файл :
en.SelectArch=Select archive file to unpack
en.SelectedArch=Selected archive file :
;
; //////////////////////////////////////
; А тут пошла секция кода Code (пробелы у Code убираем, т.к. форум их воспринимает как ББ-код):
[ Code ]
// Допустим, берём любой текст из INI-файла, в данном случае название экзешника 7z.exe. Пишем для этого функцию:
// В INI секция [Support], а под ней ключ UNPACK_ARCH=7z.exe.
// Захватываем через переменную тот языковой INI, который язык юзер выбрал при запуске программы:
function UnpackArch(Default:String):String;
  Begin
    Result:=GetIniString('Support', 'UNPACK_ARCH', '', ExpandConstant('{tmp}\Config_{language}.ini'));
  end;

{ Команда кнопки "Распаковать архив". Код самой кнопки приводить не буду, у вас своя кнопка }
procedure UnpackArchButtonClick(Sender: TObject);
// Объявляем новую переменную названия выбранного архива через проводник Windows:
var
  ArchName: String;
begin
// Извлекаем из инсталлятора в {tmp} файлы архиватора:
  ExtractTemporaryFile('7z.exe');
  ExtractTemporaryFile('7z.dll');
// Присваиваем в объявленную выше переменную имя выбранного архива:
  ArchName := '';
// Открываем архив в проводнике Windows:
  if GetOpenFileName(ExpandConstant('{cm:SelectArch}'),ArchName,ExpandConstant('{src}'),ExpandConstant('{cm:ArchFiles}')+' (001,ZIP,RAR,7z)|*.001;*.zip;*.rar;*.7z|'+ExpandConstant('{cm:TOMFile}')+' (*.001)|*.001|'+ExpandConstant('{cm:ZIPFile}')+' (*.zip)|*.zip|'+ExpandConstant('{cm:RARFile}')+' (*.rar)|*.rar|'+ExpandConstant('{cm:RARMFile}')+' (*.part1.rar)|*.part1.rar|'+ExpandConstant('{cm:SevenFile}')+' (*.7z)|*.7z|'+ExpandConstant('{cm:AllFiles}')+'|*.*','001') then
// Затем отображаем в окошке имя выбранного архива и спрашиваем подтверждение или отказ на извлечение:
    if MsgBox(ExpandConstant('{cm:SelectedArch}')+#10#10+ArchName+#10#10+ExpandConstant('{cm:ExtractArch}'), mbInformation, MB_YESNO) = IDYES then
// В случае согласия, травим архив на экзешник 7z.exe, а на втором месте указываются параметры, про которые вы спрашивали, один из параметров (толькодлясвоих) - это пароль:
  if not ShellExec('open',ExpandConstant('{tmp}\{code:UnpackArch}'),'x -y -oExtractedArchive -pтолькодлясвоих '+'"'+ArchName+'"',ExpandConstant('{src}'),SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode) then
  MsgBox(ExpandConstant('{code:NotFileOnDiskMsg}'),mbCriticalError,MB_OK);
  begin ShellExec('open',ExpandConstant('{src}\ExtractedArchive'),'','',SW_SHOWNORMAL,ewWaitUntilIdle,ResultCode) end;
end;


Maratina 05-11-2018 08:57 2839396

как установить punkbuster в тихую? без принятия соглашения и тд?
параметры я нашел в логах...
Код:

--install --install-dlls="D:\Games\Battlefield 2" --i-accept-the-pb-eula --no-prompts --no-display
но {src} не передается как папка где лежит инсталл
пример-
Код:

Exec(ExpandConstant ('{src}\punkbuster\redist\pbsvc.exe'), '--install --install-dlls="{src}" --i-accept-the-pb-eula --no-prompts --no-display', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
и установка punkbuster с ошибкой "не удается найти указанный путь {src}
в логе после этого...

El Sanchez 05-11-2018 11:34 2839411

Цитата:

Цитата Maratina
и установка punkbuster с ошибкой "не удается найти указанный путь {src} »

Maratina, раскрывать нужно константы.
Скрытый текст

Код:

[Run]
Filename: {src}\punkbuster\redist\pbsvc.exe; Parameters: "--install --install-dlls=""{src}"" --i-accept-the-pb-eula --no-prompts --no-display"; Flags: nowait
; или в [Code]
Exec(ExpandConstant('{src}\punkbuster\redist\pbsvc.exe'), '--install --install-dlls=' + ExpandConstant('"{src}"') + ' --i-accept-the-pb-eula --no-prompts --no-display', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);


Chudmin 07-11-2018 20:44 2839750

Здравствуйте! Воспользовался скинами (ISSkinU.dll и *.cjstyle), и заметил, что на странице Лицензионного соглашения, полоса прокрутки не отображается в Win 10 (виртуалка), в Win 7 отображается - как я понял это не лечится?

Chudmin 18-11-2018 20:51 2841373

Здравствуйте! Потихоньку (очень потихоньку) пытаюсь вникнуть в Inno Setup, больше методом научного тыка на примерах, из одного примера взял КОД, в меру своих сил подредактировал его.

Скрытый текст
Код:

[Files]
Source: "{app}\Win_7.txt"; DestDir: "{app}"; Check:
Source: "{app}\Win_10.txt"; DestDir: "{app}"; Check:
Source: "{app}\Win_10_2.txt"; DestDir: "{app}"; Check:
Source: "{app}\Dop_Win_7.txt"; DestDir: "{app}"; Check:


[Code_]
var
Check: array [0..3] of TCheckBox;

procedure Check0(Sender: TObject);
begin
if Check[0].Checked then
begin
Check[1].Checked := False;
Check[2].Checked := False;
end;

if (Check[0].Checked = False) and (Check[1].Checked = False)
and (Check[2].Checked = False) then Check[0].Checked := True;
end;

procedure Check1(Sender: TObject);
begin
if Check[1].Checked then
begin
Check[0].Checked := False;
Check[2].Checked := False;
end;

if (Check[0].Checked = False) and (Check[1].Checked = False)
and (Check[2].Checked = False) then Check[1].Checked := True;
end;

procedure Check2(Sender: TObject);
begin
if Check[2].Checked then
begin
Check[0].Checked := False;
Check[1].Checked := False;
end;

if (Check[0].Checked = False) and (Check[1].Checked = False)
and (Check[2].Checked = False) then Check[2].Checked := True;
end;



procedure Check3(Sender: TObject);
begin
if Check[3].Checked then
end;


procedure InitializeWizard();
begin
Check[0] := TCheckBox.Create(WizardForm);
with Check[0] do
begin
Parent := WizardForm.SelectTasksPage;
Checked := True;
Left:=ScaleX(4);
Top := ScaleY(90);
Width:=ScaleX(280);
OnClick := @Check0;
// Будет Win_7.txt
Caption := ' Стандартные иконки в стиле Win 7';
end;

Check[1] := TCheckBox.Create(WizardForm);
with Check[1] do
begin
Parent := WizardForm.SelectTasksPage;
Left:=ScaleX(4);
Top := ScaleY(115);
Width:=ScaleX(280);
OnClick := @Check1;
// Будет Win_10.txt
Caption := ' Стандартные иконки в стиле Win 10';
end;

Check[2] := TCheckBox.Create(WizardForm);
with Check[2] do
begin
Parent := WizardForm.SelectTasksPage;
Left:=ScaleX(4);
Top := ScaleY(140);
Width:=ScaleX(350);
OnClick := @Check2;
// Будет Win_10_2.txt
Caption := ' Станадартные иконки в стиле Win 7 + Win 10';
end;

Check[3] := TCheckBox.Create(WizardForm);
with Check[3] do
begin
Parent := WizardForm.SelectTasksPage;
Left:=ScaleX(4);
Top := ScaleY(165);
Width:=ScaleX(280);
OnClick := @Check3;
// Будет Dop_Win_7.txt
Caption := ' Дополнительные иконки в стиле Win 7';
end;
end;


А вот как "привязать" чекбоксы к файлам, ума не приложу, что-то мне подсказывает, что через "function" нужно, но вот как, тяму не хватает, картина как разобранная мозаика, там что-то понимаю, здесь о чём-то догадываюсь. Господа, направьте на путь истинный.

nik1967 19-11-2018 21:25 2841569

Chudmin,
Три варианта

Первый: самый простой, но через секцию Components

Код:

[Setup]
AppName = MyApp
AppVerName = MyApp
DefaultDirname = {pf}\MyApp
OutputDir=.

[Types]
Name: full; Description: Full installation; Flags: iscustom;

[Components]
Name: Check0; Description: "Стандартные иконки в стиле Win 7"; Flags: exclusiveTypes: full;
Name: Check1; Description: "Стандартные иконки в стиле Win 10"; Flags: exclusive;
Name: Check2; Description: "Станадартные иконки в стиле Win 7 + Win 10"; Flags: exclusive;
Name: Check3; Description: "Дополнительные иконки в стиле Win 7"; Flags: exclusive;

[Files]
Source: "Win_7.txt"; DestDir: "{app}"; Components: Check0;
Source: "Win_10.txt"; DestDir: "{app}"; Components: Check1;
Source: "Win_10_2.txt"; DestDir: "{app}"; Components: Check2;
Source: "Dop_Win_7.txt"; DestDir: "{app}"; Components: Check3;


Второй: если все же нужны чекбосы, а не радиобаттоны

Код:

[Setup]
AppName = MyApp
AppVerName = MyApp
DefaultDirname = {pf}\MyApp
OutputDir=.

[Tasks]
Name: desktopicon; Description: "Create a &desktop icon";

[Files]
Source: "Win_7.txt"; DestDir: "{app}"; Check: Check_0;
Source: "Win_10.txt"; DestDir: "{app}"; Check: Check_1;
Source: "Win_10_2.txt"; DestDir: "{app}"; Check: Check_2;
Source: "Dop_Win_7.txt"; DestDir: "{app}"; Check:Check_3;

[Code]
var
 
Check: array [0..3] of TCheckBox;

function Check_0(): Boolean;
begin
 
Result:= Check[0].Checked;
end;

function Check_1(): Boolean;
begin
 
Result:= Check[1].Checked;
end;

function Check_2(): Boolean;
begin
 
Result:= Check[2].Checked;
end;

function Check_3(): Boolean;
begin
 
Result:= Check[3].Checked;
end;

procedure Check0(Sender: TObject);
begin
  if
Check[0].Checked then begin
   
Check[1].Checked:= False;
    Check[2].Checked:= False;
    Check[3].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[0].Checked:= True;
end;

procedure Check1(Sender: TObject);
begin
  if
Check[1].Checked then begin
   
Check[0].Checked:= False;
    Check[2].Checked:= False;
    Check[3].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[1].Checked := True;
end;

procedure Check2(Sender: TObject);
begin
  if
Check[2].Checked then begin
   
Check[0].Checked:= False;
    Check[1].Checked:= False;
    Check[3].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[2].Checked:= True;
end;

procedure Check3(Sender: TObject);
begin
  if
Check[3].Checked then begin
   
Check[0].Checked:= False;
    Check[1].Checked:= False;
    Check[2].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[3].Checked:= True;
end;

procedure InitializeWizard();
begin
 
Check[0]:= TCheckBox.Create(WizardForm);
  with Check[0] do begin
   
Parent:= WizardForm.SelectTasksPage;
    Checked:= True;
    Left:=ScaleX(4);
    Top:= ScaleY(90);
    Width:=ScaleX(280);
    OnClick:= @Check0;
    // Будет Win_7.txt
   
Caption:= ' Стандартные иконки в стиле Win 7';
  end;

  Check[1]:= TCheckBox.Create(WizardForm);
  with Check[1] do begin
   
Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(115);
    Width:=ScaleX(280);
    OnClick:= @Check1;
    // Будет Win_10.txt
   
Caption:= ' Стандартные иконки в стиле Win 10';
  end;

  Check[2]:= TCheckBox.Create(WizardForm);
  with Check[2] do begin
   
Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(140);
    Width:=ScaleX(350);
    OnClick:= @Check2;
    // Будет Win_10_2.txt
   
Caption:= ' Станадартные иконки в стиле Win 7 + Win 10';
  end;

  Check[3]:= TCheckBox.Create(WizardForm);
  with Check[3] do begin
   
Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(165);
    Width:=ScaleX(280);
    OnClick:= @Check3;
    // Будет Dop_Win_7.txt
   
Caption:= ' Дополнительные иконки в стиле Win 7';
  end;
end;


Третий: если все же нужны чекбосы, а не радиобаттоны, другая реализация

Код:

[Setup]
AppName = MyApp
AppVerName = MyApp
DefaultDirname = {pf}\MyApp
OutputDir=.

[Tasks]
Name: desktopicon; Description: "Create a &desktop icon";

[Code]
var
 
Check: array [0..3] of TCheckBox;

procedure Check0(Sender: TObject);
begin
  if
Check[0].Checked then begin
   
Check[1].Checked:= False;
    Check[2].Checked:= False;
    Check[3].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[0].Checked:= True;
end;

procedure Check1(Sender: TObject);
begin
  if
Check[1].Checked then begin
   
Check[0].Checked:= False;
    Check[2].Checked:= False;
    Check[3].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[1].Checked := True;
end;

procedure Check2(Sender: TObject);
begin
  if
Check[2].Checked then begin
   
Check[0].Checked:= False;
    Check[1].Checked:= False;
    Check[3].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[2].Checked:= True;
end;

procedure Check3(Sender: TObject);
begin
  if
Check[3].Checked then begin
   
Check[0].Checked:= False;
    Check[1].Checked:= False;
    Check[2].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[3].Checked:= True;
end;

procedure InitializeWizard();
begin
 
Check[0]:= TCheckBox.Create(WizardForm);
  with Check[0] do begin
   
Parent:= WizardForm.SelectTasksPage;
    Checked:= True;
    Left:=ScaleX(4);
    Top:= ScaleY(90);
    Width:=ScaleX(280);
    OnClick:= @Check0;
    // Будет Win_7.txt
   
Caption:= ' Стандартные иконки в стиле Win 7';
  end;

  Check[1]:= TCheckBox.Create(WizardForm);
  with Check[1] do begin
   
Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(115);
    Width:=ScaleX(280);
    OnClick:= @Check1;
    // Будет Win_10.txt
   
Caption:= ' Стандартные иконки в стиле Win 10';
  end;

  Check[2]:= TCheckBox.Create(WizardForm);
  with Check[2] do begin
   
Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(140);
    Width:=ScaleX(350);
    OnClick:= @Check2;
    // Будет Win_10_2.txt
   
Caption:= ' Станадартные иконки в стиле Win 7 + Win 10';
  end;

  Check[3]:= TCheckBox.Create(WizardForm);
  with Check[3] do begin
   
Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(165);
    Width:=ScaleX(280);
    OnClick:= @Check3;
    // Будет Dop_Win_7.txt
   
Caption:= ' Дополнительные иконки в стиле Win 7';
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  case
CurPageID of
   
wpFinished: begin
      if
Check[0].Checked then FileCopy(ExpandConstant('{src}\Win_7.txt'), ExpandConstant('{app}\Win_7.txt'), false);
      if Check[1].Checked then FileCopy(ExpandConstant('{src}\Win_10.txt'), ExpandConstant('{app}\Win_10.txt'), false);
      if Check[2].Checked then FileCopy(ExpandConstant('{src}\Win_10_2.txt'), ExpandConstant('{app}\Win_10_2.txt'), false);
      if Check[3].Checked then FileCopy(ExpandConstant('{src}\Dop_Win_7.txt'), ExpandConstant('{app}\Dop_Win_7.txt'), false);
    end;
  end;
end;



Chudmin 19-11-2018 22:45 2841594

nik1967, большое Вам спасибо! Теперь более менее понятно как оно организовано.

Через секцию Components я это уже организовал по Справке, но мне захотелось понять, как это организовать через чекбоксы. Правда я забыл сказать, что из первых трёх чекбоксов должен быть выбран обязательно только какой-то один, а четвёртый по желанию, без привязки к первым трём. Надеюсь я правильно сделал?

Скрытый текст
Код:

[Code_]
var
  Check: array [0..3] of TCheckBox;

function Check_0(): Boolean;
begin
  Result:= Check[0].Checked;
end;

function Check_1(): Boolean;
begin
  Result:= Check[1].Checked;
end;

function Check_2(): Boolean;
begin
  Result:= Check[2].Checked;
end;

function Check_3(): Boolean;
begin
  Result:= Check[3].Checked;
end;

procedure Check0(Sender: TObject);
begin
  if Check[0].Checked then begin
    Check[1].Checked:= False;
    Check[2].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) then Check[0].Checked:= True;
end;

procedure Check1(Sender: TObject);
begin
  if Check[1].Checked then begin
    Check[0].Checked:= False;
    Check[2].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) then Check[1].Checked := True;
end;

procedure Check2(Sender: TObject);
begin
  if Check[2].Checked then begin
    Check[0].Checked:= False;
    Check[1].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) then Check[2].Checked:= True;
end;

procedure Check3(Sender: TObject);
begin
  if Check[3].Checked then
end;

procedure InitializeWizard();
begin
  Check[0]:= TCheckBox.Create(WizardForm);
  with Check[0] do begin
    Parent:= WizardForm.SelectTasksPage;
    Checked:= True;
    Left:=ScaleX(4);
    Top:= ScaleY(90);
    Width:=ScaleX(280);
    OnClick:= @Check0;
    // Будет Win_7.txt
    Caption:= ' Стандартные иконки в стиле Win 7';
  end;

  Check[1]:= TCheckBox.Create(WizardForm);
  with Check[1] do begin
    Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(115);
    Width:=ScaleX(280);
    OnClick:= @Check1;
    // Будет Win_10.txt
    Caption:= ' Стандартные иконки в стиле Win 10';
  end;

  Check[2]:= TCheckBox.Create(WizardForm);
  with Check[2] do begin
    Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(140);
    Width:=ScaleX(350);
    OnClick:= @Check2;
    // Будет Win_10_2.txt
    Caption:= ' Станадартные иконки в стиле Win 7 + Win 10';
  end;

  Check[3]:= TCheckBox.Create(WizardForm);
  with Check[3] do begin
    Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(165);
    Width:=ScaleX(280);
    OnClick:= @Check3;
    // Будет Dop_Win_7.txt
    Caption:= ' Дополнительные иконки в стиле Win 7';
  end;
end;


ErikPshat 19-11-2018 23:12 2841603

nik1967, и у меня в нагрузку подобный вопрос.

Как вывести эти же чекбоксы, то только не в главное окно, а в MsgBox?
Могу ли я использовать вместо этого:
Код:

Check[3]:= TCheckBox.Create(WizardForm);
аот это?
Код:

Check[3]:= TCheckBox.Create(MsgBox);

Dodakaedr 19-11-2018 23:29 2841611

Вставлю свои пять копеек:)
Цитата:

Цитата Chudmin
А вот как "привязать" чекбоксы к файлам »

Цитата:

Цитата Chudmin
из первых трёх чекбоксов должен быть выбран обязательно только какой-то один, а четвёртый по желанию »

Example

Код:

[Setup]
AppName=app
AppVersion=app 1.0
DefaultDirName={pf}\app

[Files]
Source: "{app}\Win_7.txt"; DestDir: "{app}"; Check: Check0();
Source: "{app}\Win_10.txt"; DestDir: "{app}"; Check: Check1();
Source: "{app}\Win_10_2.txt"; DestDir: "{app}"; Check: Check2();
Source: "{app}\Dop_Win_7.txt"; DestDir: "{app}"; Check: Check3();

[Code]
var
Check: array [0..3] of TCheckBox;

function Check0(): boolean;
begin
 
Result := Check[0].Checked;
end;

function Check1(): boolean;
begin
 
Result := Check[1].Checked;
end;

function Check2(): boolean;
begin
 
Result := Check[2].Checked;
end;

function Check3(): boolean;
begin
 
Result := Check[3].Checked;
end;

procedure GetCheck(Sender: TObject);
begin
  case
sender of
   
Check[0]: begin if Check[0].Checked then begin Check[1].Checked := False; Check[2].Checked := False; end; end;
    Check[1]: begin if Check[1].Checked then begin Check[2].Checked := False; Check[0].Checked := False; end; end;
    Check[2]: begin if Check[2].Checked then begin Check[1].Checked := False; Check[0].Checked := False; end; end;
  end;
end;

procedure InitializeWizard();
begin
Check[0] := TCheckBox.Create(WizardForm);
with Check[0] do
begin
Parent := WizardForm.SelectDirPage;
Checked := True;
Left:=ScaleX(4);
Top := ScaleY(100);
Width:=ScaleX(280);
OnClick := @GetCheck;
// Будет Win_7.txt
Caption := ' Стандартные иконки в стиле Win 7';
end;

Check[1] := TCheckBox.Create(WizardForm);
with Check[1] do
begin
Parent := WizardForm.SelectDirPage;
Left:=ScaleX(4);
Top := ScaleY(125);
Width:=ScaleX(280);
OnClick := @GetCheck;
// Будет Win_10.txt
Caption := ' Стандартные иконки в стиле Win 10';
end;

Check[2] := TCheckBox.Create(WizardForm);
with Check[2] do
begin
Parent := WizardForm.SelectDirPage;
Left:=ScaleX(4);
Top := ScaleY(150);
Width:=ScaleX(350);
OnClick := @GetCheck;
// Будет Win_10_2.txt
Caption := ' Станадартные иконки в стиле Win 7 + Win 10';
end;

Check[3] := TCheckBox.Create(WizardForm);
with Check[3] do
begin
Parent := WizardForm.SelectDirPage;
Left:=ScaleX(4);
Top := ScaleY(175);
Width:=ScaleX(280);
// Будет Dop_Win_7.txt
Caption := ' Дополнительные иконки в стиле Win 7';
end;
end;


Цитата:

Цитата ErikPshat
Как вывести эти же чекбоксы, то только не в главное окно, а в MsgBox? »

На сколько мне известно, то никак.

nik1967 20-11-2018 11:04 2841657

Dodakaedr,
ну если уж сокращать, то

Код:

procedure GetCheck(Sender: TObject);
begin
  case
sender of
   
Check[0]: if Check[0].Checked then begin Check[1].Checked := False; Check[2].Checked := False; end;
    Check[1]: if Check[1].Checked then begin Check[2].Checked := False; Check[0].Checked := False; end;
    Check[2]: if Check[2].Checked then begin Check[1].Checked := False; Check[0].Checked := False; end;
  end;
end;

Зачем нам лишние begin, end :)


Цитата:

Цитата ErikPshat
Как вывести эти же чекбоксы, то только не в главное окно, а в MsgBox? »

Цитата:

Цитата Dodakaedr
На сколько мне известно, то никак. »

Но, можно сделать собственную форму сообщения при нажатии на нужную кнопку, и на ней уже разместить всё, что нужно.

ErikPshat 20-11-2018 13:40 2841690

Цитата:

Цитата nik1967
ну если уж сокращать, то »

Согласен, там лишние begin и end;
А ещё лучше и нагляднее сократить без правок начало кода:
Код:

[ Code ]
var
Check: array [0..3] of TCheckBox;

function Check0(): boolean; begin Result := Check[0].Checked; end;
function Check1(): boolean; begin Result := Check[1].Checked; end;
function Check2(): boolean; begin Result := Check[2].Checked; end;
function Check3(): boolean; begin Result := Check[3].Checked; end;


Цитата:

Цитата nik1967
Но, можно сделать собственную форму сообщения при нажатии на нужную кнопку, и на ней уже разместить всё, что нужно.

Да, погуглил это дело и везде предлагают только через создание новой формы. Мне как раз сейчас нужно вставить чекбоксы этого красивого кода, подготовленного выше. И у меня стандартный MessageBox отображает окно выбранной папки, которую я собираюсь разделить на части по 4 ГБ для флешек FAT32 с последующей упаковкой. И как раз здесь мне нужны 3 чекбокса, чтобы дать возможность выбора разделения не только по "4 ГБ", но и по "2 ГБ" и "Без ограничений".
Код:

if MsgBox(ExpandConstant('Выбрана следующая папка :')+#10#10+FolderName+#10#10+ExpandConstant('Вы хотите упаковать папку в PKG менее 4 ГБ?'), mbInformation, MB_YESNO) = IDYES then
Скрин, где вместо 4 ГБ хочу поставить 3 чекбокса:

Есть какой-то готовый вариант для подобного MessageBox? А то у меня уже голова не шарит.

nik1967 20-11-2018 15:10 2841711

Цитата:

Цитата ErikPshat
Есть какой-то готовый вариант для подобного MessageBox? А то у меня уже голова не шарит. »

Набросал на скорую руку пример

Код:

[Setup]
AppName = MyApp
AppVerName = MyApp
DefaultDirname = {pf}\MyApp
OutputDir=.

[Code]
var
 
NewButton1: TNewButton;
  NewForm: TSetupForm;
  YesButton: TNewButton;
  NoButton: TNewButton;
  Check: array [0..3] of TCheckBox;

procedure NewFormButtonClick(Sender: TObject);
begin
  case
TNewButton(Sender) of
   
YesButton: MsgBox('Запустилась упаковка.', mbInformation, MB_OK); //  Сюда вешаешь выполнение, если да
   
NoButton: MsgBox('Ничего не произошло.', mbInformation, MB_OK);  //  Сюда, если нет
 
end;
  NewForm.Close;
end;

procedure GetCheck(Sender: TObject);
begin
  case
sender of
   
Check[0]: if Check[0].Checked then begin Check[1].Checked:= False; Check[2].Checked:= False; end;
    Check[1]: if Check[1].Checked then begin Check[2].Checked:= False; Check[0].Checked:= False; end;
    Check[2]: if Check[2].Checked then begin Check[1].Checked:= False; Check[0].Checked:= False; end;
  end;
end;

procedure TestOnClick(Sender: TObject);
begin
 
NewForm:= CreateCustomForm();
  with NewForm do begin
   
ClientWidth:= ScaleX(473);
    ClientHeight:= ScaleY(233);
    BorderIcons:= [];
    Caption:= 'Тест';
    Color:= clWindow;
    CenterInsideControl(WizardForm, False);
  end;

  with TLabel.Create(NewForm) do begin
   
Parent:= NewForm;
    SetBounds(ScaleX(-1), ScaleY(187), ScaleX(475), ScaleY(47));
    Transparent:= false;
    Color:= clBtnFace;
  end;

  with TLabel.Create(NewForm) do begin
   
Parent:= NewForm;
    SetBounds(ScaleX(60), ScaleY(10), ScaleX(400), ScaleY(80));
    AutoSize:= False;
    Caption:= 'Вы хотите упаковать папку в PKG?';
  end;

  Check[0]:= TCheckBox.Create(NewForm);
  with Check[0] do begin
   
Parent:= NewForm;
    Checked:= True;
    Left:=ScaleX(60);
    Top:= ScaleY(90);
    Width:=ScaleX(280);
    OnClick:= @GetCheck;
    Caption:= ' Тест 1';
  end;

  Check[1]:= TCheckBox.Create(NewForm);
  with Check[1] do begin
   
Parent:= NewForm;
    Left:=ScaleX(60);
    Top:= ScaleY(115);
    Width:=ScaleX(280);
    OnClick:= @GetCheck;
    Caption:= ' Тест 2';
  end;

  Check[2]:= TCheckBox.Create(NewForm);
  with Check[2] do begin
   
Parent:= NewForm;
    Left:=ScaleX(60);
    Top:= ScaleY(140);
    Width:=ScaleX(280);
    OnClick:= @GetCheck;
    Caption:= ' Тест 3';
  end;

  YesButton:= TNewButton.Create(NewForm);
  with YesButton do begin
   
Parent:= NewForm;
    SetBounds(ScaleX(304), ScaleY(200), ScaleX(75), ScaleY(23));
    OnClick:= @NewFormButtonClick;
    Caption:= SetupMessage(msgButtonYes);
  end;

  NoButton := TNewButton.Create(NewForm);
  with NoButton do begin
   
Parent:= NewForm;
    SetBounds(ScaleX(389), ScaleY(200), ScaleX(75), ScaleY(23));
    OnClick:= @NewFormButtonClick;
    Caption:= SetupMessage(msgButtonNo);
  end;

  NewForm.ShowModal;
  NewForm.Free;
end;

procedure InitializeWizard();
begin
 
NewButton1:= TNewButton.Create(WizardForm);
  with NewButton1 do
  begin
   
Parent:= WizardForm;
    SetBounds(ScaleX(10),ScaleY(327),ScaleX(75),ScaleY(23));
    Caption:= 'Тест';
    OnClick:= @TestOnClick;
  end;
end;


И да, зачем ты в MsgBox пихаешь ExpandConstant? Совершенно лишнее.
Код:


if MsgBox('Выбрана следующая папка :'+#10#10+FolderName+#10#10+'Вы хотите упаковать папку в PKG менее 4 ГБ?', mbInformation, MB_YESNO) = IDYES then


ErikPshat 20-11-2018 16:23 2841722

Цитата:

Цитата nik1967
Набросал на скорую руку пример »

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

Правда я хотел, чтобы это было именно так, как я указал на скриншоте. Я думал, если не получается вставить чекбоксы напрямую в MsgBox, тогда создать новую форму именно такого же MsgBox под замену с чекбоксами и подменить стандартный. Либо наверное лучше было бы вместо чекбоксов сделать там раскрывающийся список.

У вас же выходит кнопкой, опять же на том окне выбора папки. И мне кажется, тогда открывающееся окно по кнопке будет лишним.
Я решил тогда уж сразу использовать ранее предложенное решение на окне выбора папки с чекбоксами, так будет более разумнее с меньшим количеством телодвижений. То есть, в своей проге я откачусь назад на один шаг, где идёт выбор папки и там сразу буду отмечать размеры делений по ГБ. А в MsgBox, как на скрине, буду автоматом отображать выбранный ранее размер.

Только мне нужно заменить, в окне выбора папки, кнопки "Далее >" и "Отмена" на кнопки "Да" и "Нет", потому что у меня не инсталлятор, а как бы авторан.
Может вы мне подскажете, как это нужно организовать? Я просто сам только пару месяцев, как заинтересовался Inno Setup.

nik1967 20-11-2018 16:33 2841724

Цитата:

Цитата ErikPshat
создать новую форму именно такого же MsgBox под замену с чекбоксами и подменить стандартный. »

Я немного переделал скрипт - как раз сделал похожим на стандартный MsgBox.
Цитата:

Цитата ErikPshat
Только мне нужно заменить, в окне выбора папки, кнопки "Далее >" и "Отмена" на кнопки "Да" и "Нет", потому что у меня не инсталлятор, а как бы авторан. »

Я не знаю, как реализовано окно выбора папки.

ErikPshat 20-11-2018 19:52 2841756

nik1967, в ообщем я сделал вот такую реализацию своей идеи, можете заценить и указать на ошибки:

Готовый примар реализации чекбоксов на странице выбора папки:
Код:

#define  Name      "MyAppName"
#define  Version    "1.0 Build 1234"

[Setup]
AppName={#Name}
AppVersion={#Version}
DefaultDirName={src}

;[Files]
;Source: "{app}\4GB.txt"; DestDir: "{app}"; Check: Check0();
;Source: "{app}\2GB.txt"; DestDir: "{app}"; Check: Check1();
;Source: "{app}\NoLimit.txt"; DestDir: "{app}"; Check: Check2();
;Source: "{app}\Signed.txt"; DestDir: "{app}"; Check: Check3();

[Languages]
Name: ru; MessagesFile: compiler:Languages\Russian.isl

[Messages]
ru.WizardSelectDir=Выбор папки для разделения
ru.SelectDirDesc=Какую папку вы хотите разделить на части и упаковать их в PKG?
ru.SelectDirLabel3=Программа разделит выбранную папку на части по размерам,%nв зависимости от сделанного вами выбора в чекбоксах.
ru.SelectDirBrowseLabel=Для выбора папки, которую вам необходимо разделить, нажмите «Обзор».
ru.DiskSpaceMBLabel=Требуется как минимум 2 или 4 ГБ свободного дискового пространства.

[CustomMessages]
ru.Check4GB=Разделить папку на части по 4 Гигабайта
ru.Check2GB=Разделить папку на части по 2 Гигабайта
ru.CheckNot=Не разделять папку, упаковать целиком
ru.CheckSig=Подписать PKG (создать "retail_signed.pkg")

[ Code ]
var
Check: array [0..3] of TCheckBox;

function Check0(): boolean; begin Result := Check[0].Checked; end;
function Check1(): boolean; begin Result := Check[1].Checked; end;
function Check2(): boolean; begin Result := Check[2].Checked; end;
function Check3(): boolean; begin Result := Check[3].Checked; end;

procedure GetCheck(Sender: TObject);
begin
  case sender of
    Check[0]: if Check[0].Checked then begin Check[1].Checked := False; Check[2].Checked := False; end;
    Check[1]: if Check[1].Checked then begin Check[2].Checked := False; Check[0].Checked := False; end;
    Check[2]: if Check[2].Checked then begin Check[1].Checked := False; Check[0].Checked := False; end;
  end;
end;

procedure InitializeWizard();
begin
  Check[0] := TCheckBox.Create(WizardForm);
  with Check[0] do
  begin
    Parent := WizardForm.SelectDirPage;
    Checked := True;
    Left:= ScaleX(4);
    Top := ScaleY(115);
    Width:=ScaleX(280);
    OnClick := @GetCheck;
    // Будет 4GB.txt, если имеется в них необходимость, нужно раскомментировать их в секции [Files]
    Caption := ExpandConstant(' {cm:Check4GB}');
  end;

  Check[1] := TCheckBox.Create(WizardForm);
  with Check[1] do
  begin
    Parent := WizardForm.SelectDirPage;
    Left:= ScaleX(4);
    Top := ScaleY(135);
    Width:=ScaleX(280);
    OnClick := @GetCheck;
    // Будет 2GB.txt, если имеется в них необходимость, нужно раскомментировать их в секции [Files]
    Caption := ExpandConstant(' {cm:Check2GB}');
  end;

  Check[2] := TCheckBox.Create(WizardForm);
  with Check[2] do
  begin
    Parent := WizardForm.SelectDirPage;
    Left:= ScaleX(4);
    Top := ScaleY(155);
    Width:=ScaleX(350);
    OnClick := @GetCheck;
    // Будет NoLimit.txt, если имеется в них необходимость, нужно раскомментировать их в секции [Files]
    Caption := ExpandConstant(' {cm:CheckNot}');
  end;

  Check[3] := TCheckBox.Create(WizardForm);
  with Check[3] do
  begin
    Parent := WizardForm.SelectDirPage;
    Left:= ScaleX(4);
    Top := ScaleY(185);
    Width:=ScaleX(280);
    // Будет Signed.txt, если имеется в них необходимость, нужно раскомментировать их в секции [Files]
    Caption := ExpandConstant(' {cm:CheckSig}');
  end;
end;


Только какие потом отлавливать переменные я пока не придумал )))
  • Выбранная папка вроде: {#AppName}
  • Выбранный чекбокс как-то так: Check()

Iska 20-11-2018 19:56 2841758

Цитата:

Цитата ErikPshat
потому что у меня не инсталлятор, а как бы авторан. Может вы мне подскажете, как это нужно организовать?»

Если у Вас не инсталляция, а «как бы авторан» — то используйте в качестве рабочего средства не Inno Setup, а другие, более подходящие для того инструменты, например, AutoPlay Media Studio и т.п.

Chudmin 21-11-2018 11:06 2841834

Здравствуйте всем! Господа-товарищи, я так понимаю, в таком виде

Скрытый текст
Код:

[Code]
var
  Check: array [0..3] of TCheckBox;

function Check_0(): Boolean;
begin
  Result:= Check[0].Checked;
end;

function Check_1(): Boolean;
begin
  Result:= Check[1].Checked;
end;

function Check_2(): Boolean;
begin
  Result:= Check[2].Checked;
end;

function Check_3(): Boolean;
begin
  Result:= Check[3].Checked;
end;

procedure Check0(Sender: TObject);
begin
  if Check[0].Checked then begin
    Check[1].Checked:= False;
    Check[2].Checked:= False;
    Check[3].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[0].Checked:= True;
end;

procedure Check1(Sender: TObject);
begin
  if Check[1].Checked then begin
    Check[0].Checked:= False;
    Check[2].Checked:= False;
    Check[3].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[1].Checked := True;
end;

procedure Check2(Sender: TObject);
begin
  if Check[2].Checked then begin
    Check[0].Checked:= False;
    Check[1].Checked:= False;
    Check[3].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[2].Checked:= True;
end;

procedure Check3(Sender: TObject);
begin
  if Check[3].Checked then begin
    Check[0].Checked:= False;
    Check[1].Checked:= False;
    Check[2].Checked:= False;
  end;

  if (Check[0].Checked = False) and (Check[1].Checked = False) and (Check[2].Checked = False) and (Check[3].Checked = False) then Check[3].Checked:= True;
end;

procedure InitializeWizard();
begin
  Check[0]:= TCheckBox.Create(WizardForm);
  with Check[0] do begin
    Parent:= WizardForm.SelectTasksPage;
    Checked:= True;
    Left:=ScaleX(4);
    Top:= ScaleY(90);
    Width:=ScaleX(280);
    OnClick:= @Check0;
    // Будет Win_7.txt
    Caption:= ' Стандартные иконки в стиле Win 7';
  end;

  Check[1]:= TCheckBox.Create(WizardForm);
  with Check[1] do begin
    Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(115);
    Width:=ScaleX(280);
    OnClick:= @Check1;
    // Будет Win_10.txt
    Caption:= ' Стандартные иконки в стиле Win 10';
  end;

  Check[2]:= TCheckBox.Create(WizardForm);
  with Check[2] do begin
    Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(140);
    Width:=ScaleX(350);
    OnClick:= @Check2;
    // Будет Win_10_2.txt
    Caption:= ' Станадартные иконки в стиле Win 7 + Win 10';
  end;

  Check[3]:= TCheckBox.Create(WizardForm);
  with Check[3] do begin
    Parent:= WizardForm.SelectTasksPage;
    Left:=ScaleX(4);
    Top:= ScaleY(165);
    Width:=ScaleX(280);
    OnClick:= @Check3;
    // Будет Dop_Win_7.txt
    Caption:= ' Дополнительные иконки в стиле Win 7';
  end;
end;


чекбоксы прикрутить нельзя к самостоятельно созданной странице, только к стандартным?

Dodakaedr 21-11-2018 15:13 2841902

Chudmin,
Типа такого
Код:

Check[0].Parent := CustomPage.Surface
CustomPage это созданная страница.

Chudmin 21-11-2018 20:57 2841961

Цитата:

Цитата Dodakaedr
Типа такого »

Благодарствую, - ведь видел и в Справке и примерах, но вылетело из головы.

RbwKz 22-11-2018 11:38 2842066

Дорогие форумчане, интересует следующий вопрос.
Возможно ли как-нибудь уловить ошибки которые возникают при установке программы? Например: если ставить с пацарапанного или грязного диска получим ошибку "The Source file is corrupted",
которая успешно отобразится на экране. Мне же нужно название этой ошибки отправить на сервер (Или возможно есть другой способ).
У кого какие мысли возникают?

Chudmin 22-11-2018 12:33 2842087

Здравствуйте всем! Подскажите пожалуйста, функция UpdateReadyMemo действует только для стандартных страниц, или можно включать сюда и созданные пользователем тоже.

boss911 22-11-2018 17:10 2842132

Цитата:

Цитата RbwKz
Мне же нужно название этой ошибки отправить на сервер »

Разве что отправить лог установки, где, возможно, будет отображена та или иная ошибка установки. Запускать инсталлятор нужно с параметром/ключом командной строки.

Код:

/LOG
Указывает инсталлятору создать log-файл в папке TEMP для подробного отчета о действиях и событиях при установке, обработке записей секции [Run], предпринятых в ходе установки. Применяется при отслеживании ошибок. Например, если вы подозреваете, что файл не был заменен, хотя должен был, log-файл сообщит, что файл был действительно пропущен и почему это произошло.
Log-файлу присваивается уникальное имя на базе текущей даты. (Существующие файлы не перезаписываются и не дополняются.)
Информация, содержащаяся в log-файле, техническая и поэтому не может быть понята пользователем. Формат файла может измениться без уведомления.

/LOG="filename"
Параметр похож на /LOG, но в отличие от него позволяет указать фиксированный путь/имя файла для log-файла. Если файл с указанным именем уже существует, он будет заменен. Если файл не может быть создан, установка прервется и выдаст сообщение об ошибке.


magsood 02-12-2018 11:30 2843681

I want create custom setup with inno setup like this:
https://drive.google.com/open?id=1L2...MJ7viq2KvhR6sA
Please help for iss code!

ToBeLife 06-12-2018 17:18 2844537

Вложений: 1
Всем привет.
Подскажите пожалуйста, как реализуется рабочий вариант бэкапа и возможность отключать деинсталлятор через task.
Прошу готовый пример. Как в этом русификаторе (примеры из справки не очень подходят).
Спасибо.

ADRebus 21-12-2018 11:56 2847329

Доброго,
подскажите, есть ли возможность установить разные значения для VersionInfoDescription (в разделе [Setup]) в зависимости от локализации
данное поле отображается в описании установщика, если выбрать "Свойства", по клику ПКМ

TROY Diamond 22-12-2018 14:05 2847577

Inno Setup - упаковка папок в архивы, в процессе установки
 
Здравствуйте!

Прошу прощения если создал тему НЕ в том разделе, просьба перенести её в соответствующий!

Подскажите, пожалуйста, аналог кода ниже, с использованием консольных библиотек от 7-Zip, WinRAR? библиотек Inno Setup и т.п. , для упаковки, БОЛЬШОГО количества имеющихся папок, в отдельные архивы ZIP, с заданием ОПРЕДЕЛЁННОГО расширения и обычной степенью сжатия, в процессе установки, с последовательным удалением каждой папки СРАЗУ ЖЕ ПОСЛЕ СОЗДАНИЯ АРХИВА, из секции CODE, в Inno Setup, а НЕ с использованием батника и т.п. из секции RUN!

Либо посоветуйте, как модифицировать и доработать данный код, желательно помочь и прислать ПОЛНЫЙ код для секции CODE и Files в Inno Setup:

Скрытый текст

Код:


Секция Files
Source: "Data\Папка_pak\*"; DestDir: "{app}\DATA\ПАПКА_pak"; BeforeInstall: ChangeCaption('Распаковка файлов...'); AfterInstall: ExtLog(); Flags: ignoreversion overwritereadonly recursesubdirs createallsubdirs sortfilesbyextension
Source: "{app}\Файл-пустышка"; DestDir: "{tmp}\"; BeforeInstall: ChangeCaption('Создание ФАЙЛА(архива).pk5...'); AfterInstall: Pack('ПАПКА_pak'); Flags: ignoreversion overwritereadonly
Source: "{app}\Файл-пусиышка"; DestDir: "{tmp}\"; BeforeInstall: ChangeCaption('Удаление временных файлов...'); AfterInstall: RF(ExpandConstant('{app}\Main\pkzip.exe')); Flags: ignoreversion overwritereadonly

Секция Code
procedure Pack(str: string);
var
res : Integer;
begin
Exec(ExpandConstant('{app}\Main\pkzip.exe'), ' -add -dir=relative -NoZipExtension '+str+'.pk3' + ' ' + str + '\*.*', ExpandConstant('{app}\Main\'), SW_HIDE, ewWaitUntilTerminated, Res);
RD(ExpandConstant('{app}\Main\')+str);
end;

procedure RD(Dir:string);
var
res : integer;
begin
Exec('cmd.exe', ' /c rd /S /Q ' + AddQuotes(Dir),ExpandConstant('{sys}'), SW_Hide,ewWaitUntilTerminated,res);
Exec('cmd.exe', ' /c rd /S /Q ' + '"'+Dir+'"',ExpandConstant('{sys}'), SW_Hide,ewWaitUntilTerminated,res);
end;

procedure RF(file:string);
var
res : Integer;
begin
Exec('cmd.exe', ' /c del /F /Q ' + AddQuotes(file),ExpandConstant('{sys}'), SW_Hide,ewWaitUntilTerminated,res);
Exec('cmd.exe', ' /c del /F /Q ' + '"'+file+'"',ExpandConstant('{sys}'), SW_Hide,ewWaitUntilTerminated,res);
end;



Всё это нужно для создания "игровых" архивов. Все "игровые" - это Архивы ZIP, с переименованным расширением. Сжатие ZIP-архивов - НЕ благодарное дело и НЕ приносит большого выигрыша в весе!
Поэтому я распаковал все, в отдельные, одноимённые папки - всё сжал, теперь нужно чтобы в процессе извлечения (копирования) установщиком Inno Setup, этих папок по окончанию копирования каждой папки создавался архив, а эта папка удалялась, потом копировалась следующая - создавался архив и папка после сразу же удалялась! А НЕ в конце всей установки!

Iska 22-12-2018 14:41 2847586

Цитата:

Цитата TROY Diamond
для упаковки, БОЛЬШОГО количества имеющихся папок, в отдельные архивы ZIP, с заданием ОПРЕДЕЛЁННОГО расширения и обычной степенью сжатия, в процессе установки, с последовательным удалением каждой папки СРАЗУ ЖЕ ПОСЛЕ СОЗДАНИЯ АРХИВА, »

Вы что — решили очередного вымогателя «запилить», коллега ;)?

TROY Diamond 22-12-2018 15:06 2847589

Iska, давайте по существу, я же написал для чего!

Iska 22-12-2018 18:52 2847625

TROY Diamond, эта шутка была.

По существу — я хотел бы уяснить смысл сих действий, которые по существу приводят лишь к увеличению времени установки. В чём глубинный смысл? Чем Вам так не нравятся архивы внутри инсталляции?

P.S. На выбор смотрите раз, два.

TROY Diamond 22-12-2018 19:19 2847629

Iska, что-то вообще не то! Написал вам в Личку - ваш ящик переполнен, посмотрите, пожалуйста!

El Sanchez 23-12-2018 12:05 2847715

Цитата:

Цитата ADRebus
подскажите, есть ли возможность установить разные значения для VersionInfoDescription (в разделе [Setup]) в зависимости от локализации
данное поле отображается в описании установщика, если выбрать "Свойства", по клику ПКМ »

ADRebus, локализации чего?
Цитата:

Цитата TROY Diamond
Подскажите, пожалуйста, аналог кода ниже, с использованием консольных библиотек от 7-Zip, WinRAR? библиотек Inno Setup и т.п. , для упаковки, БОЛЬШОГО количества имеющихся папок, в отдельные архивы ZIP, с заданием ОПРЕДЕЛЁННОГО расширения и обычной степенью сжатия, в процессе установки, с последовательным удалением каждой папки СРАЗУ ЖЕ ПОСЛЕ СОЗДАНИЯ АРХИВА, из секции CODE, в Inno Setup, а НЕ с использованием батника и т.п. из секции RUN! »

TROY Diamond,
Скрытый текст

Код:

[Files]
Source: 7za.exe; Flags: dontcopy
; {app}\data\test01
Source: {app}\test01\*; DestDir: {app}\data\test01; Flags: ignoreversion overwritereadonly recursesubdirs createallsubdirs sortfilesbyextension
Source: dummy; DestDir: {app}\data; AfterInstall: Pack(ExpandConstant('{app}\data\test01')); Flags: deleteafterinstall
; {app}\data\test02
Source: {app}\test02\*; DestDir: {app}\data\test02; Flags: ignoreversion overwritereadonly recursesubdirs createallsubdirs sortfilesbyextension
Source: dummy; DestDir: {app}\data; AfterInstall: Pack(ExpandConstant('{app}\data\test02')); Flags: deleteafterinstall

[Code]
procedure Pack(const APath: string);
var
  ResultCode: Integer;
begin
  if not FileExists(ExpandConstant('{tmp}\7za.exe')) then
    ExtractTemporaryFile('7za.exe');
  if not Exec(ExpandConstant('{tmp}\7za.exe'), Format('a -tzip -sdel -y "%0:s.pk3" .\%0:s\*', [ExtractFileName(APath)]), ExtractFileDir(APath), SW_HIDE, ewWaitUntilTerminated, ResultCode) then
    RaiseException(Format('Add new data from ''%s'' to archive ''%s.pk3'' failed with error 0x%.8x (%s)', [APath, ExtractFileName(APath), ResultCode, SysErrorMessage(ResultCode)]));
  if not RemoveDir(APath) then
  begin
    ResultCode := DLLGetLastError;
    RaiseException(Format('Unable to delete empty folder ''%s''. Error code: 0x%.8x (%s)', [APath, ResultCode, SysErrorMessage(ResultCode)]));
  end;
end;


Цитата:

Цитата Iska
По существу — я хотел бы уяснить смысл сих действий, которые по существу приводят лишь к увеличению времени установки. В чём глубинный смысл? Чем Вам так не нравятся архивы внутри инсталляции? »

Iska, размер инсталлятора по схеме zip + LZMA больше, чем просто LZMA. Хочет сэкономить на размере в ущерб времени установки.

Iska 23-12-2018 13:01 2847730

Цитата:

Цитата El Sanchez
Iska, размер инсталлятора по схеме zip + LZMA больше, чем просто LZMA. »

El Sanchez, сильно больше?

Кстати, почему не рекомендуете коллеге TROY Diamond Вашу собственную разработку, на которую я ссылался выше?!

Цитата:

Цитата TROY Diamond
Написал вам в Личку - ваш ящик переполнен, посмотрите, пожалуйста! »

Пишите прямо здесь.

TROY Diamond 23-12-2018 13:13 2847735

Iska!

Цитата:

Цитата El Sanchez
Iska, размер инсталлятора по схеме zip + LZMA больше, чем просто LZMA. Хочет сэкономить на размере в ущерб времени установки.

Да так и есть! Если пытаться сжать уже сжатое в ZIP, с помощью стандартных средств Inno Setup в LZMA, то почти вообще НЕ сжимается, а если распаковать все ZIP-архивы в отдельные папки, то сжимается существенно в LZMA.

Я привёл вам пример рабочего скрипта! НО там используется старый консольный pkzip, который давным-давно НЕ поддерживается и НЕ развивается разработчиками! ((( На некоторых компах он почему-то НЕ "отрабатывает", (видимо из-за старости или какой-то неправильности скрипта), а также некоторые антивирусы на него "ругаются"! ((

Я просил усовершенствовать-доработать данный скрипт или предложить аналог вместо pkzip, использовать иные библиотеки от RAR, 7-Zip или ещё откуда-то. Сжать в Zip не так сложно ведь? Просто папок 100-ни!

Пример, есть папки Pack01, Pack02, Pack03 - это распакованные одноимённые архивы ZIP (Pack01.pack, Pack02.pack., Pack03.pack) - условно для примера.

Нужно чтобы из установщика Inno Setup папка Pack01 - извлеклась скопировалась в папку установки, после чего заархивировалась в необходимый архив ZIP с обычной степенью сжатия - и именем и расширением, какое нужно, например, Pack01.pack, после чего папка Pack01, была сразу же удалена, и только после этого началось копирование Pack02... - создание из неё архива Pack02.pack, удаление папки Pack02 и т.д...

Iska 23-12-2018 13:35 2847741

TROY Diamond, Вам тот же вопрос: «существенно» — это сколько?

El Sanchez 23-12-2018 15:59 2847770

Цитата:

Цитата Iska
El Sanchez, сильно больше? »

Iska, будет зависеть от степени сжимаемости исходных файлов. Я пока пример писал потестировал на кошках:
1. Берем пару папок с файлами, каждую из них пакуем в zip-архив. Полученные архивы пакуем в test01.7z (LZMA2, Ultra). Тут эмулируем инсталлятор с максимальным сжатием с zip-архивами внутри. Размер архива test01.7z - 241141 байт.
2. Эту же пару папок пакуем в test02.7z (LZMA2, Ultra). Тут эмулируем инсталлятор с максимальным сжатием с файлами внутри. Размер архива test02.7z - 193102 байт.
Цитата:

Цитата Iska
Кстати, почему не рекомендуете коллеге TROY Diamond Вашу собственную разработку, на которую я ссылался выше?! »

Iska, старьё и много букв для TROY Diamond :)

TROY Diamond 23-12-2018 19:24 2847848

El Sanchez, Iska, так как сделать-то?

По поводу размера - игра в установленном конечном виде с игровыми ZIP-архивами занимает 15 ГБ, примерно, если ничего НЕ менять и прям так с этими архивами создать установщик в Inno Setup, с максимальным сжатием (LZMA - LZMA2), то получается около 14 -14,5 ГБ. И то там кроме архивов есть ещё и не запакованные файлы, вот они и сжимаются, - от этого и размер уменьшается!

Кроме того, если НЕ использовать сжатие LZMA - LZMA2, а выбрать сжатие ZIP, то разница НЕ большая, 14,7 ГБ, зато время на сборку (компиляцию) установщика экономится!

А если распаковать все архивы в папки и собрать установщик в Inno Setup, сжав даже просто (LZMA), то получится около 11 ГБ!
А если ещё поставить флаги: сортировать по имени, по расширению все файлы, - то получается около 10,5 ГБ!

vint56 27-12-2018 14:18 2848575

TROY Diamond,
Скачай ISDone 0.6 final там есть возможность распаковать архивы 7zip и FreeArc и поддержка упаковки файлов в архивы zip. многое другое
ну так распакуй zip архивы и запакуй файлы в архив 7zip или FreeArc
после установки укажи за запаковать
if not ISPackZIP ( 0, 0, ExpandConstant('{app}\Pack01\*'), ExpandConstant('{app}\Pack01.pack'), 2, false ) then break;
if not ISPackZIP ( 0, 0, ExpandConstant('{app}\Pack02\*'), ExpandConstant('{app}\Pack02.pack'), 2, false ) then break;
if not ISPackZIP ( 0, 0, ExpandConstant('{app}\Pack03\*'), ExpandConstant('{app}\Pack03.pack'), 2, false ) then break;

TROY Diamond 29-12-2018 02:25 2848893

vint56, мне всё это нужно стандартным установщиком Inno Setup, а не чтобы рядом с setup.exe лежали архивы в 7-zip или FreeArc, переименованные в *.bin! И уж НЕ в коем случае (как многие сборщики делают) - сжать всё что нужно внешним архиваторами 7-zip или FreeArc, и другими, потом всё это "загнать" в Inno Setup, потмо в процессе установки игры, всё это начнёт копироваться на ЖД, потом распаковываться, потом перепаковываться в "игровые архивы" и только потом удаляться! ВОТ ЭТОГО НЕ НАДО!
Это во-первых требует на ЖД раза в 2-3 больше свободного места на ЖД и требует намного больше времени на установку!

Мне нужно по другому! Пример:
В папке Game у меня лежат все файлы игры и все распакованные игровые архивы (по папкам) и я всё это содержимое просто скомпилирую Inno Setup, - стандартного метода сжатия LZMA - вполне хватит!
Начнётся ОБЫЧНЫЙ процесс установки игры (копирование файлов), вот всё что мне нужно, чтобы в процессе установки копирования всех файлов игры, каждая скопированная ОПРЕДЕЛЁННАЯ папка, сразу же после копирования - архивировалась в zip, с конкретным названием, после чего сразу же удалялась, потом копировалась следующая папка...

Iska 29-12-2018 05:29 2848903

Цитата:

Цитата TROY Diamond
El Sanchez, Iska, так как сделать-то? »

TROY Diamond, пинайте про «много букв» коллегу El Sanchez, если сами не разобрались.

El Sanchez 29-12-2018 13:00 2848952

Цитата:

Цитата TROY Diamond
Мне нужно по другому! Пример:
В папке Game у меня лежат все файлы игры и все распакованные игровые архивы (по папкам) и я всё это содержимое просто скомпилирую Inno Setup, - стандартного метода сжатия LZMA - вполне хватит!
Начнётся ОБЫЧНЫЙ процесс установки игры (копирование файлов), вот всё что мне нужно, чтобы в процессе установки копирования всех файлов игры, каждая скопированная ОПРЕДЕЛЁННАЯ папка, сразу же после копирования - архивировалась в zip, с конкретным названием, после чего сразу же удалялась, потом копировалась следующая папка... »

TROY Diamond, рабочий пример я привел в предыдущем своем сообщении, осталось увидеть.

Iska 29-12-2018 16:44 2848983

Неправильно ты, Дядя Фёдор, бутерброд ешь Вы, коллега, ссылку приводите ;), вот так:
Цитата:

Цитата El Sanchez
TROY Diamond, рабочий пример я привел в предыдущем своем сообщении, осталось увидеть. »

надо.

TROY Diamond 30-12-2018 00:44 2849031

El Sanchez, вот теперь увидел, благодаря - Iska! Спасибо!

7za.exe - какой брать и ещё вопрос Inno Setup ANSI или Unicode - имеет значение, какой брать?

Iska 30-12-2018 03:00 2849039

Цитата:

Цитата TROY Diamond
7za.exe - какой брать »

Последний.

Цитата:

Цитата TROY Diamond
Inno Setup ANSI или Unicode - имеет значение, какой брать? »

Разумеется, будет иметь значение. Берите Unicode, не прогадаете.

TROY Diamond 30-12-2018 18:54 2849173

Iska, с DLL-кой такое прокатит или принципиально 7za.exe?

Iska 30-12-2018 19:17 2849178

Цитата:

Цитата TROY Diamond
Iska, с DLL-кой такое прокатит… »

Чтобы прокатило — пинайте коллегу El Sanchez на предмет данной темы, я Вам тут слабый помощник. Сегодня, кстати, 7-Zip обновился.

TROY Diamond 30-12-2018 19:56 2849186

Iska, в 7-Zip, нет 7za.exe, есть DLL-ки и 7z.exe...

mwz 30-12-2018 20:00 2849188

Цитата:

Цитата TROY Diamond
в 7-Zip, нет 7za.exe »

Есть.
Находится в 7z1806-extra, который также лежит на странице загрузок.

Iska 30-12-2018 20:32 2849190

Цитата:

Цитата TROY Diamond
Iska, в 7-Zip, нет 7za.exe, »

Как уже сказал коллега mwz — есть. И Вам нужен именно 7za.exe, standalone-версия, уже статически слинкованная с потребными библиотеками (не 7z.exe).

TROY Diamond 31-12-2018 02:54 2849227

Iska и mwz, я просто уточнил - спасибо за пояснения! Чтобы просто упаковать в обычный zip, нужны такие "заморочки" и "спец-файл"?

Iska 31-12-2018 12:03 2849265

TROY Diamond, что подразумевается под «заморочками» и под «спец-файлом»?

TROY Diamond 31-12-2018 18:42 2849307

Iska , смайлик забыл поставить - всё в порядке, спасибо!

Iska, mwz и El Sanchez, подскажите, пожалуйста:
1. Как во время архивирования файлов "заставить индикатор процесса двигаться" или хотя бы чтобы было написано создание файла и т.п. Идеально бы ещё с процентами соединить! НОВЫЙ липовый (НЕ настоящий) индикатор процесса НЕ нужен!
А то во время упаковки всё замирает, кнопка Отмена НЕ активна, конечный пользователь может решить что всё зависло, а создание некоторых больших архивов может занимает до 5-7 минут!

2. Как внести в список для деинсталляции, эти созданные архивы, установщик ведь о них НЕ знает, при удалении игры все архивы останутся в папки установки? Просто указать все архивы в [UninstallDelete]?

2.1. А если процесс установки, по какой-то причине, будет прерван, тут как сделать? Чтобы ВСЯ папка установки была удалена, если установка завершилась некорректно или вообще была переврана?

3. Есть ещё одна проблема - это те игры, которые хранят свои сейвы, файлы конфигурации и т.п. прям в папке установки, поэтому просто тупо удалить всю папку нельзя, нужно спросить пользователя "Оставить сохранения и т.п.?"

mwz 31-12-2018 20:03 2849320

Цитата:

Цитата TROY Diamond
Чтобы ВСЯ папка установки была удалена, если установка завершилась некорректно или вообще была переврана? »

Как-то у одного знакомого пропало абсолютно всё на диске E:

Разборка с анализом протоколов и дальнейшим "опросом свидетелей" показала, что сын установил пиратскую игру, а затем деинсталлировал её. И всё бы ничего, но установил он её в корень диска Е, а деинсталятор запустил команду, которая в переводе на человеческий язык означала: "Удалить нахрен всю папку установки, и при удалении ни о чём не спрашивать".

С Наступающим!

Iska 01-01-2019 09:48 2849368

TROY Diamond, вооот… Теперь Вы видите, что не всё так просто :)?

Цитата:

Цитата TROY Diamond
1. Как во время архивирования файлов "заставить индикатор процесса двигаться" или хотя бы чтобы было написано создание файла и т.п. Идеально бы ещё с процентами соединить! »

По-хорошему — никак. Это сторонние задачи, никоим образом не привязанные ни к объёму инсталляции, ни к индикатору процесса инсталляции (который определяется как раз её объёмом).

Цитата:

Цитата TROY Diamond
НОВЫЙ липовый (НЕ настоящий) индикатор процесса НЕ нужен! »

Вообще-то — как раз нужен новый индикатор, в отдельном окне. А совсем правильно — новое окно для всех пакуемых архивов, плюс по ещё одному окну с индикатором упаковки каждого отдельного архива. Я так думаю.

Цитата:

Цитата TROY Diamond
А то во время упаковки всё замирает, кнопка Отмена НЕ активна, конечный пользователь может решить что всё зависло, а создание некоторых больших архивов может занимает до 5-7 минут! »

Функция exec() с параметром ewWaitUntilTerminated — она такая ;). Вы что-то запустили из кода и ждёте результата. И пока такая функция полностью не отработает — обновлять форму и обрабатывать приходящие для неё сообщения некому.

Цитата:

Цитата TROY Diamond
2. Как внести в список для деинсталляции, эти созданные архивы, установщик ведь о них НЕ знает, при удалении игры все архивы останутся в папки установки? Просто указать все архивы в [UninstallDelete]? »

Да. Имейте в виду, что они будут удалены на последнем шаге деинсталляции

Цитата:

Цитата TROY Diamond
2.1. А если процесс установки, по какой-то причине, будет прерван, тут как сделать? Чтобы ВСЯ папка установки была удалена, если установка завершилась некорректно или вообще была переврана? »

В общем и целом — сложно. Вы должны внутри процедуры Pack() анализировать код возврата 7za.exe, и при ненулевом коде возврата удалить все ранее созданные архивы.

Цитата:

Цитата TROY Diamond
3. Есть ещё одна проблема - это те игры, которые хранят свои сейвы, файлы конфигурации и т.п. прям в папке установки, поэтому просто тупо удалить всю папку нельзя, нужно спросить пользователя "Оставить сохранения и т.п.?" »

Ну, дык, спрашивайте. Pascal ждёт Вас. Вообще-то, нормальные игры давно уже не хранят пользовательские данные в каталоге установки, а только либо в пользовательском разделе реестре, либо в профиле пользователя.

mwz, пираты — они такие :). Любимое дело — попытаться забросить «свои» библиотеки в системный каталог, забросить «свои» шрифты в каталог со шрифтами, нимало не заботясь о том, что не токмо функционал каких-то сторонних приложений, но и сама операционная система от таких вывертов может накрыться медным тазом.

TROY Diamond 01-01-2019 20:38 2849401

Iska, ну а липовый индикатор установки во время создания архивов как тогда сделать, или просто в момент создания архива, стандартную надпись "Копирование файлов", заменить на "Создание файла и т.п."?

Iska 02-01-2019 00:04 2849421

Не надо липовый. Нужны отдельные и реальные. Как — надеюсь, коллеги Вам помогут.

El Sanchez 04-01-2019 14:39 2849719

Вложений: 1
Цитата:

Цитата TROY Diamond
во время упаковки всё замирает, кнопка Отмена НЕ активна, конечный пользователь может решить что всё зависло, а создание некоторых больших архивов может занимает до 5-7 минут! »

TROY Diamond, ясно, так и знал, что по-простому не выйдет.
Скрытый текст

Код:

[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl

[CustomMessages]
ru.SevenZipStatusPackFiles=Упаковка файлов из %1:
ru.SevenZipProgressCaptions=Прогресс:%nСкорость:%nПрошло:%nОсталось:
ru.SevenZipProgressInfo=%1%% (%2 из %3)%n%4%n%5%n%6
ru.SevenZipPackFailed=При создании архива %1 произошла ошибка. Код ошибки: %2
ru.UnableDeleteEmptyFolder=Не удалось удалить пустую папку %1. Код ошибки: %2 (%3)

[Files]
Source: 7-zip32.dll; Flags: dontcopy
#ifndef IS_ENHANCED
; http://restools.hanzify.org/inno/callbackctrl/InnoCallbackCtrl_V1.1.zip
Source: CallbackCtrl.dll; Flags: dontcopy
#endif
; {app}\data\test01
Source: {app}\test01\*; DestDir: {app}\data\test01; Flags: ignoreversion overwritereadonly recursesubdirs createallsubdirs sortfilesbyextension
Source: dummy; DestDir: {app}\data; AfterInstall: Pack(ExpandConstant('{app}\data\test01')); Flags: deleteafterinstall
; {app}\data\test02
Source: {app}\test02\*; DestDir: {app}\data\test02; Flags: ignoreversion overwritereadonly recursesubdirs createallsubdirs sortfilesbyextension
Source: dummy; DestDir: {app}\data; AfterInstall: Pack(ExpandConstant('{app}\data\test02')); Flags: deleteafterinstall

[Code]
#define A = (Defined UNICODE) ? "W" : "A"
const
  WM_GETFONT = $0031;
  WM_SETTEXT = $000C;
  WM_USER    = $0400;

  PBM_SETPOS    = WM_USER + 2;
  PBM_SETRANGE32 = WM_USER + 6;

  GWL_STYLE = -16;

  WS_CLIPSIBLINGS = $04000000;
  WS_VISIBLE      = $10000000;
  WS_CHILDWINDOW  = $40000000;
  SS_RIGHT = $2;

  CP_ACP  = 0;
  CP_UTF8 = 65001;

  FNAME_MAX32 = 512;
  MAX_PATH = 260;

  ARCEXTRACT_BEGIN    = 0;
  ARCEXTRACT_INPROCESS = 1;

type
  { 7-zip.dll. }
  TExtractingInfo = record
    szSourceFileName: PAnsiChar;
    szDestFileName: PAnsiChar;
    dwFileSize: DWORD;
    szFileSize: PAnsiChar;
    dwWriteSize: DWORD;
    szWriteSize: PAnsiChar;
    dwProgress: DWORD;
    szSpeed: PAnsiChar;
    szElapsed: PAnsiChar;
    szRemain: PAnsiChar;
  end;

  { User-defined data passed to callback. }
  TArcParam = array of HWND;

#ifndef IS_ENHANCED
 
TPackCallbackProc = function (nState: UINT; var ExtInfo: TExtractingInfo; var ArcParam: TArcParam): BOOL;
#endif

// Unicode and Character Set Functions
function WideCharToMultiByte(CodePage: UINT; dwFlags: DWORD; lpWideCharStr: string; cchWideChar: Integer; lpMultiByteStr: AnsiString; cbMultiByte, lpDefaultChar: Integer; lpUsedDefaultChar: Longint): Integer; external 'WideCharToMultiByte@kernel32.dll stdcall';
function MultiByteToWideChar(CodePage: UINT; dwFlags: DWORD; lpMultiByteStr: AnsiString; cbMultiByte: Integer; lpWideCharStr: string; cchWideChar: Integer): Integer; external 'MultiByteToWideChar@kernel32.dll stdcall';
// Shell Lightweight Utility Functions
function PathCompactPath(hDC: THandle; lpszPath: string; dx: UINT): BOOL; external 'PathCompactPath{#A}@shlwapi.dll stdcall';
// Painting and Drawing Functions
function GetDC(hWnd: HWND): THandle; external 'GetDC@user32.dll stdcall';
// Device Context Functions
function ReleaseDC(hWnd: HWND; hDC: THandle): Integer; external 'ReleaseDC@user32.dll stdcall';
function SelectObject(hdc, hgdiobj: THandle): THandle; external 'SelectObject@gdi32.dll stdcall';
// Window Functions
function GetClientRect(hWnd: HWND; var lpRect: TRect): BOOL; external 'GetClientRect@user32.dll stdcall';
// Message Functions
function SendMessageString(hWnd: HWND; Msg: UINT; wParam: Longint; lParam: string): Longint; external 'SendMessage{#A}@user32.dll stdcall';
// Window Class Functions
function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: Longint): Longint; external 'SetWindowLong{#A}@user32.dll stdcall';
// 7-zip.dll Functions
function SevenZip(const CmdLine: AnsiString; ArcProc: Longint; var LParam: TArcParam): Integer; external 'SevenZip@files:7-zip32.dll stdcall';
#ifndef IS_ENHANCED
// CallbackCtrl.dll Functions
function WrapPackProc(Callback: TPackCallbackProc; ParamCount: Integer): LongWord; external 'wrapcallbackaddr@files:callbackctrl.dll stdcall';
#endif

var
  ProgressInfoContainer, ProgressInfo: TNewStaticText;
  ArcProc: LongWord;

function UTF8Encode(const Value: string): AnsiString;
var
  Len: Integer;
  UTF16Buffer: string;
begin
  if Value = '' then Exit;
#ifndef UNICODE
 
// на ANSI-версии компилятора сначала переводим строку в UTF-16LE (Unicode)
  Len := MultiByteToWideChar(CP_ACP, 0, Value, -1, '', 0);
  if Len = 0 then Exit;
  UTF16Buffer := StringOfChar(#0, Len shl 1);
  if MultiByteToWideChar(CP_ACP, 0, Value, -1, UTF16Buffer, Len) = 0 then Exit;
#else
 
UTF16Buffer := Value;
#endif
 
// перевод строки UTF-16LE (Unicode) в UTF-8
  Len := WideCharToMultiByte(CP_UTF8, 0, UTF16Buffer, -1, '', 0, 0, 0);
  if Len = 0 then Exit;
  Result := StringOfChar(#0, Len - 1);
  if WideCharToMultiByte(CP_UTF8, 0, UTF16Buffer, -1, Result, Len, 0, 0) = 0 then Exit;
end;

function UTF8Decode(const Value: AnsiString): string;
var
  Len: Integer;
#ifndef UNICODE
 
UTF16Buffer: string;
#endif
begin
  if Value = '' then Exit;
#ifndef UNICODE
 
// на ANSI-версии компилятора сначала переводим строку в UTF-16LE (Unicode)
  Len := MultiByteToWideChar(CP_UTF8, 0, Value, -1, '', 0);
  if Len = 0 then Exit;
  UTF16Buffer := StringOfChar(#0, Len shl 1);
  if MultiByteToWideChar(CP_UTF8, 0, Value, -1, UTF16Buffer, Len) = 0 then Exit;

  // перевод строки UTF-16 в ANSI
  Len := WideCharToMultiByte(CP_ACP, 0, UTF16Buffer, -1, '', 0, 0, 0);
  if Len = 0 then Exit;
  Result := StringOfChar(#0, Len - 1);
  if WideCharToMultiByte(CP_ACP, 0, UTF16Buffer, -1, Result, Len, 0, 0) = 0 then Exit;
#else
 
// на Unicode-версии компилятора перевод строки UTF-8 в UTF-16LE (Unicode)
  Len := MultiByteToWideChar(CP_UTF8, 0, Value, -1, '', 0);
  if Len = 0 then Exit;
  Result := StringOfChar(#0, Len - 1);
  if MultiByteToWideChar(CP_UTF8, 0, Value, -1, Result, Len) = 0 then Exit;
#endif
end;

function PackCallbackProc(nState: UINT; var ExtInfo: TExtractingInfo; var ArcParam: TArcParam): BOOL;
var
  S: string;
  DC, SaveFont: THandle;
  H: HWND;
  R: TRect;
begin
  { Avoid call VCL methods or get/set properties. }
  Result := True;
  case nState of
    ARCEXTRACT_BEGIN:
      begin
        H := ArcParam[0];
        DC := GetDC(H);
        try
          SaveFont := SelectObject(DC, SendMessage(H, WM_GETFONT, 0, 0));
          GetClientRect(H, R);
          S := UTF8Decode(ExtInfo.szDestFileName);
          PathCompactPath(DC, S, R.Right - R.Left);
          SendMessageString(H, WM_SETTEXT, 0, S);
        finally
          if SaveFont <> 0 then
            SelectObject(DC, SaveFont);
          ReleaseDC(H, DC);
        end;
      end;
    ARCEXTRACT_INPROCESS:
      begin
        H := ArcParam[1];
        PostMessage(H, PBM_SETRANGE32, 0, 100);
        PostMessage(H, PBM_SETPOS, ExtInfo.dwProgress, 0);
        H := ArcParam[2];
        S := FmtMessage(CustomMessage('SevenZipProgressInfo'), [IntToStr(ExtInfo.dwProgress), ExtInfo.szWriteSize, ExtInfo.szFileSize, ExtInfo.szSpeed, ExtInfo.szElapsed, ExtInfo.szRemain]);
        SendMessageString(H, WM_SETTEXT, 0, S);
      end;
  end;
end;

procedure Pack(const APath: string);
var
  CmdLine: AnsiString;
  ArcParam: TArcParam;
  ResultCode: Integer;
begin
  { Pack files. }
  try
    WizardForm.StatusLabel.Caption := FmtMessage(CustomMessage('SevenZipStatusPackFiles'), [ExtractFileName(APath)]);
    ProgressInfoContainer.Show;
    CmdLine := UTF8Encode(Format('a -tzip -sdel -y "%0:s.pk3" "%0:s\*"', [APath]));
    SetLength(ArcParam, 3);
    ArcParam[0] := WizardForm.FilenameLabel.Handle;
    ArcParam[1] := WizardForm.ProgressGauge.Handle;
    ArcParam[2] := ProgressInfo.Handle;
    ResultCode := SevenZip(CmdLine, ArcProc, ArcParam);
    if ResultCode <> 0 then
      RaiseException(FmtMessage(CustomMessage('SevenZipPackFailed'), [ExtractFileName(APath), Format('0x%.8x', [ResultCode])]));
    if not RemoveDir(APath) then
    begin
      ResultCode := DLLGetLastError;
      RaiseException(FmtMessage(CustomMessage('UnableDeleteEmptyFolder'), [APath, ResultCode, SysErrorMessage(ResultCode)]));
    end;
  except
    ShowExceptionMessage;
    DelTree(ExtractFileDir(APath) + '\*.pk3', False, True, False);  // Rollback if error occured.
  finally
    ProgressInfoContainer.Hide;
    WizardForm.StatusLabel.Caption := SetupMessage(msgStatusExtractFiles);
    WizardForm.FilenameLabel.Caption := '';
  end;
end;

procedure CreateInstallingPage;
begin
  { ProgressInfoContainer. }
  ProgressInfoContainer := TNewStaticText.Create(WizardForm);
  with ProgressInfoContainer do
  begin
    Parent := WizardForm.InstallingPage;
    Align := alBottom;
    AutoSize := False;
    Caption := CustomMessage('SevenZipProgressCaptions');
    Height := Parent.ClientHeight - WizardForm.ProgressGauge.Top - WizardForm.ProgressGauge.Height - ScaleY(5);
  end;

  { ProgressInfo. }
  ProgressInfo := TNewStaticText.Create(WizardForm);
  with ProgressInfo do
  begin
    Parent := ProgressInfoContainer;
    Align := alRight;
    AutoSize := False;
    Width := Parent.ClientWidth div 2;
    SetWindowLong(Handle, GWL_STYLE, WS_CHILDWINDOW or WS_VISIBLE or WS_CLIPSIBLINGS or SS_RIGHT);
  end;
#ifdef IS_ENHANCED
 
ArcProc := CallbackAddr('PackCallbackProc');
#else
 
ArcProc := WrapPackProc(@PackCallbackProc, 3);
#endif
end;

procedure InitializeWizard;
begin
  CreateInstallingPage;
end;


rashidzhan 06-01-2019 06:44 2850101

Кто платно поможет мне создать инсталлятор?


1) Выбор языка установщика;
2) Проверка на новую версию установщика;
3) Установки некоторых файлов;
4) Тихая установка дополнительных программ и утилит;
5) Установка ярлыков;
6) Показывать описание в отдельной окошке;
7) Интерфейс как на скриншоте.

Скрин я сильно фотошопил.

TROY Diamond 10-01-2019 15:20 2851187

Цитата El Sanchez:
El Sanchez »
Цитата:

ясно, так и знал, что по-простому не выйдет.
1. El Sanchez, пожалуйста, будьте любезны, можно ПОЛНЫЙ скрипт, а также указать какую версию (и где взять) CallbackCtrl.dll и Inno Setip - вы использовали, что-то не получается! ((( То не пакует нормально, то архивы получаются битые, то папка не удаляется сразу после создания архива и перед распаковкой новой... Несколько раз компилировал, каждый раз по новому получалось...

2. Также подскажите, пожалуйста, как в этот скрипт добавить проверку ранее установленного приложения, например, по секции Uninstall, по названию и т.п., НО только с предупреждением, что приложение уже было установлено, БЕЗ запрета устанавливать "поверх"!
ПРОБЛЕМА В ТОМ, ЧТО ПРИЛОЖЕНИЕ МОЖЕТ НАЗЫВАТЬСЯ ПО РАЗНОМУ и в секции Uninstall, оно может быть в различных разделах! Я готов указать в скрипте ВСЕ ВОЗМОЖНЫЕ варианты, только скажите, куда и как это сделать?

El Sanchez 11-01-2019 11:12 2851384

Цитата:

Цитата TROY Diamond
можно ПОЛНЫЙ скрипт, а также указать какую версию (и где взять) CallbackCtrl.dll и Inno Setip - вы использовали, что-то не получается! »

TROY Diamond, пример и так полный, только без секции Setup и с тестовыми папками test01, test02 и файлом-пустышкой dummy в Files. Работает в обычной и в расширенной версиях. Ссылка на CallbackCtrl.dll приведена в Files.
Цитата:

Цитата TROY Diamond
Также подскажите, пожалуйста, как в этот скрипт добавить проверку ранее установленного приложения, например, по секции Uninstall, по названию и т.п., НО только с предупреждением, что приложение уже было установлено, БЕЗ запрета устанавливать "поверх"!
ПРОБЛЕМА В ТОМ, ЧТО ПРИЛОЖЕНИЕ МОЖЕТ НАЗЫВАТЬСЯ ПО РАЗНОМУ и в секции Uninstall, оно может быть в различных разделах! Я готов указать в скрипте ВСЕ ВОЗМОЖНЫЕ варианты, только скажите, куда и как это сделать? »

TROY Diamond,
Скрытый текст

Код:

function InitializeSetup: Boolean;
var
  UninstallSubKeyName: string;
begin
  UninstallSubKeyName := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\';
  if RegKeyExists(HKLM, UninstallSubKeyName + 'AIMP') or
    RegKeyExists(HKLM, UninstallSubKeyName + '{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}') or
    RegKeyExists(HKLM, UninstallSubKeyName + 'Axialis IconWorkshop_is1') then
    MsgBox('Я никому не нужное информационное сообщение.', mbInformation, MB_OK);
end;


TROY Diamond 11-01-2019 15:32 2851419

El Sanchez вместо "AIMP" и "{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}" - писать все возможные варианты?
А в MsgBox - написать что приложение уже было ранее установлено?

А как соединить с тем скриптом правильно?

El Sanchez 11-01-2019 17:34 2851436

Цитата:

Цитата TROY Diamond
вместо "AIMP" и "{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}" - писать все возможные варианты? »

TROY Diamond, да. Я ж не знаю ваших вариантов.
Цитата:

Цитата TROY Diamond
А в MsgBox - написать что приложение уже было ранее установлено? »

TROY Diamond, угу.
Цитата:

Цитата TROY Diamond
А как соединить с тем скриптом правильно? »

TROY Diamond, копировать-вставить. Только я забыл в теле InitializeSetup строку Result := True; добавить, а то форму не увидите.

TROY Diamond 11-01-2019 18:49 2851451

El Sanchez, так вот добавить?

Код:

function InitializeSetup(): Boolean;
begin
Result:= True;
var
  UninstallSubKeyName: string;
begin
  UninstallSubKeyName := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\';
  if RegKeyExists(HKLM, UninstallSubKeyName + 'AIMP') or
    RegKeyExists(HKLM, UninstallSubKeyName + '{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}') or
    RegKeyExists(HKLM, UninstallSubKeyName + 'Axialis IconWorkshop_is1') then
    MsgBox('Я никому не нужное информационное сообщение.', mbInformation, MB_OK);
end;

2. Соединить коды: 1-й со 2-м, сразу поле
Код:

procedure InitializeWizard;
begin
  CreateInstallingPage;
end;

в первом коде вставить второй код?

3. Вы знали, наверное что будет это вопрос? ))) Как теперь подкорректировать размер свободного места на ЖД, который требует установщик? В нём ведь скомпилированы распакованные архивы и он считает их вес, а папки ведь поочередно удаляются после создания архивов, места нужно раза в 2 меньше, чем он хочет!

Iska 12-01-2019 05:12 2851510

Цитата:

Цитата TROY Diamond
Как теперь подкорректировать размер свободного места на ЖД, который требует установщик? »

А куда он, простите, будет извлекать Ваши пока ещё не-архивы?!

El Sanchez 12-01-2019 10:13 2851524

Цитата:

Цитата TROY Diamond
так вот добавить? »

TROY Diamond, нет, после begin.
Цитата:

Цитата TROY Diamond
Соединить коды: 1-й со 2-м, сразу поле в первом коде вставить второй код? »

TROY Diamond, да. Вам бы справку почитать.
Цитата:

Цитата TROY Diamond
Как теперь подкорректировать размер свободного места на ЖД, который требует установщик? В нём ведь скомпилированы распакованные архивы и он считает их вес, а папки ведь поочередно удаляются после создания архивов, места нужно раза в 2 меньше, чем он хочет! »

TROY Diamond, забить на это.

TROY Diamond 19-01-2019 17:14 2853297

El Sanchez, а если НЕ "забивать"? ))

2. Как сделать чтобы по умолчанию полученный установщик требовал для запуска права Администратора? "PrivilegesRequired=admin", - НЕ даёт нужного эффекта, "значка щита" у полученного setup.exe - нет!
Приходится потом редактировать Манифест в полученном файле setup.exe, с помощью редактора ресурсов! Менять на "requireAdministrator".

1specific 20-01-2019 01:56 2853381

Всем привет.
Ищу человека который отлично ладит с inno setup.
Задача: сделать стучалку на сервер при установке программы, чтобы можно было подсчитать количество уникальных установок (подсчет уже на уровне сервера и к задаче не имеет отношения).
Разумеется "не за спасибо".
Скажите пожалуйста в какую тему мне обратиться с этой задачей? Если я по адресу - то пишите в ЛС. Договоримся!

Iska 20-01-2019 02:56 2853383

1specific, «стучалка на сервер» делается в самом приложении, а не в инсталляции. И отрабатывать она должна в момент первого исполнения Вашего приложения. Так что, не страдайте ерундой.

habib2302 20-01-2019 10:21 2853394

1specific, AutoIt в помощь

1specific 20-01-2019 10:42 2853397

Iska, это вы так решили для своих нужд?
У меня цель - отстучать об успешной установке приложения. Не о запуске, а об установке.
В inno это реализуемо. Так к чему вообще ваше замечание не понимаю?

habib2302, как autoit связан например с post запросом на сервер после установки приложения? Я не понимаю как он применим к моей задаче.

habib2302 20-01-2019 11:26 2853402

1specific, можно добавить проверку на удачную установку инсталлятора и задать запуск autoit скрипта после удачной установки

1specific 20-01-2019 11:49 2853409

habib2302, ну гуд. Спасибо за идею.
Но в целом вопрос способа реализации не поднимался. Ищется человек который сможет реализовать мою задумку, а как это делать - это ему уже виднее) хоть отдельный софт, хоть vbs, хоть как)) мне главное результат)

Iska 20-01-2019 12:17 2853415

Цитата:

Цитата 1specific
Iska, это вы так решили для своих нужд? »

Неа.

Цитата:

Цитата 1specific
У меня цель - отстучать об успешной установке приложения. Не о запуске, а об установке. »

А в чём смысл? Если Вас интересует накрутка («IE установлен на 100% компьютеров с ОС Microsoft Windows!») — делайте, как хотите Вы. Если Вас интересует реальное количество установок — делайте, как советую я. Единственное исключение — приложение не Ваше, доступа к его исходному коду у Вас нет, а Вы просто делаете какое-нибудь очередное поделие в стиле «репак bla-bla-bla». Тут уж выбора нет.

Цитата:

Цитата 1specific
В inno это реализуемо. »

Угу. Тут больше зависит от того, как Вы будете сие реализовывать на стороне сервера. От этого и надо танцевать. Но в общем и целом сие может выглядеть, например, так: проверяете, есть ли соединение с глобальной сетью, создаёте экземпляр объекта «MSXML2.XMLHTTP» («Microsoft.XMLHTTP» и т.п., см., например: XMLHttpRequest — Википедия), заполняете его свойства, указываете метод (POST или GET), отсылаете методом .Send(), анализируете ответ, повторяете пару-тройку раз, если были некритичные ошибки. Коллеги нарисуют готовый код, я думаю. Если Вы со своей стороны опишите серверную часть.

Цитата:

Цитата 1specific
Так к чему вообще ваше замечание не понимаю? »

Просто рекомендация. Разве я могу запретить Вам что-то делать?

Цитата:

Цитата 1specific
habib2302, как autoit связан например с post запросом на сервер после установки приложения? Я не понимаю как он применим к моей задаче. »

Никак.

1specific 20-01-2019 23:39 2853493

Iska, спасибо за ответ.

Цитата:

Цитата Iska
Если Вас интересует реальное количество установок — делайте, как советую я »

Да я бы с удовольствием сделал, если бы мои знания позволяли. Но мой пост о поиске исполнителя именно поэтому и появился - нужен человек который сможет реализовать.

Цитата:

Цитата Iska
Тут больше зависит от того, как Вы будете сие реализовывать на стороне сервера. От этого и надо танцевать »

На стороне сервера всё проще. Туда приходит post запрос с параметрами, мы эти параметры добавляем в БД. Вот у нас и собрана информация об установках в базе.

Цитата:

Цитата Iska
Но в общем и целом сие может выглядеть, например, так: проверяете, есть ли соединение с глобальной сетью, создаёте экземпляр объекта «MSXML2.XMLHTTP» («Microsoft.XMLHTTP» и т.п., см., например: XMLHttpRequest — Википедия), заполняете его свойства, указываете метод (POST или GET), отсылаете методом .Send(), анализируете ответ, повторяете пару-тройку раз, если были некритичные ошибки. »

Вообще для меня тёмный лес. Возможно это гениальная идея, но к сожалению я не в состоянии оценить)))

Цитата:

Цитата Iska
Коллеги нарисуют готовый код, я думаю. Если Вы со своей стороны опишите серверную часть. »

А вот тут легко:
  1. После успешной установки, отсылаем post запрос вида site_ru/success.php?md5=11111&hwid=22222&os=7&ip=1.1.1.1.1
    P.S. важно именно отослать post запрос незаметно для пользователя (т.е. не открыть страницу браузера после установки, а в фоне просто отослать). Причина - бональная защита от дураков которые путем изменения url могут накручивать установки.
  2. Сервер принимает этот запрос, добавляет параметры запроса в базу (каждый в свою колонку таблицы).

Пояснение к параметрам
  • md5 - это md5 установщика, который был успешно установлен (самого install.exe). Он будет всегда уникальный и генерируется на уровне сервера путем добавления байтов, перед тем как отдать его на скачивание.
  • hwd - это hwid железки на которой была произведена установка
  • os - это операционная система на которой была произведена установка
  • ip - это IP адрес устройства на котором была произведена установка (ну это возможно лишнее, т.к. ip мы можем определять при получении post запроса на сервере).

Iska 21-01-2019 00:34 2853495

Цитата:

Цитата 1specific
Вообще для меня тёмный лес. Возможно это гениальная идея, но к сожалению я не в состоянии оценить))) »

Ничего гениального в этом нет, обычная отсылка запроса, использующая готовую библиотеку посредством Automation. Примеры можно найти запросом по тем же ключевым словам, например:
Inno Setup "MSXML2.XMLHTTP"|"Microsoft.XMLHTTP" POST Send - Поиск в Google. Вот типичный образец использования класса (причём, даже с разбором ответа сервера). Если вместо «Inno Setup» укажете «VBScript», или «VB», или «VBA» — найдёте уйму примеров, которые только и останется, что перевести с VBScript на Pascal.

Цитата:

Цитата 1specific
Он будет всегда уникальный и генерируется на уровне сервера путем добавления байтов, перед тем как отдать его на скачивание. »

И этого бы я не советовал делать — на подобные вещи могут весьма нервно реагировать поведенческие анализаторы проактивной защиты антивирусов (вкупе с тем, что планируется, что инсталлятор будет «стучать» в сеть — чую, получится убойный эффект a-la красной тряпки для быка).

Я бы нацарапал, но думаю, у более опытных в Pascal коллег сие выйдет гораздо лучше.

ErikPshat 21-01-2019 21:36 2853649

Можете подсказать, почему у меня ошибка could not call proc?

Пытаюсь при запуске инсталлятора проверить установленную версию PowerShell и если она меньше 5.1, тогда скачивать и устанавливать её.
Вот такой сокращённый код:
Код скрипта
Код:

[Setup]
AppName=PowerShell
AppVersion=5.1

[Files]
Source: "embedded\ISSkin\ISSkinU.dll"; DestDir: {tmp}; Flags: dontcopy
Source: "embedded\ISSkin\Styles\{#Skin}.cjstyles"; DestDir: {tmp}; Flags: dontcopy
Source: "embedded\7z.dll"; DestDir: {tmp}; Flags: dontcopy
Source: "embedded\7z.exe"; DestDir: {tmp}; Flags: dontcopy
Source: "embedded\7z32.dll"; DestDir: {tmp}; Flags: dontcopy
Source: "embedded\7z32.exe"; DestDir: {tmp}; Flags: dontcopy

[Languages]
Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"

[CustomMessages]
ru.Caution7064=На компьютере обнаружена устаревшая версия PowerShell.%nПосле установки программы будет произведено скачивание и установка обновления PowerShell 5.1 для Windows 7 64bit.%n%nПожалуйста, дождитесь завершения обновления!

[_Code]
procedure LoadSkin(lpszPath: String; lpszIniFileName: String); external 'LoadSkin@files:ISSkinU.dll stdcall';
procedure UnloadSkin(); external 'UnloadSkin@files:ISSkinU.dll stdcall';
function ShowWindow(hWnd: Integer; uType: Integer): Integer; external 'ShowWindow@user32.dll stdcall';

function IsWindowsVersionOrNewer(Major, Minor: Integer): Boolean;
var
  Version: TWindowsVersion;
begin
  GetWindowsVersionEx(Version);
  Result := (Version.Major > Major) or ((Version.Major = Major) and (Version.Minor >= Minor));
end;

function IsWindows70OrNewer: Boolean; begin Result := IsWindowsVersionOrNewer(6, 1); end;
function IsWindows80OrNewer: Boolean; begin Result := IsWindowsVersionOrNewer(6, 2); end;
function IsWindows81OrNewer: Boolean; begin Result := IsWindowsVersionOrNewer(6, 3); end;
function IsWindows10OrNewer: Boolean; begin Result := IsWindowsVersionOrNewer(10,0); end;

function InitializeSetup(): Boolean;
begin
  ExtractTemporaryFile('{#Skin}.cjstyles');
  LoadSkin(ExpandConstant('{tmp}\{#Skin}.cjstyles'), 'normalmystyle.ini');
        Result := True;
end;

// Скачиваем PowerShell 5.1 под нашу версию Windows и битность...
procedure InitializeWizard;
var
  PSVersion: String;
begin
  RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine','PowerShellVersion', PSVersion);
  if ExpandConstant(Copy(PSVersion,1,3)) < ExpandConstant('5.1') then
  begin
    if IsWin64 then
    begin
        idpAddFileSize('https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win7AndW2K8R2-KB3191566-x64.zip',ExpandConstant('{tmp}\Win7AndW2K8R2-KB3191566-x64.zip'),68076477); end else
      if IsWindows80OrNewer and not IsWindows81OrNewer then begin MsgBox(ExpandConstant('{cm:Caution8064}'), mbInformation, MB_OK);
        idpAddFileSize('https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/W2K12-KB3191565-x64.msu',ExpandConstant('{tmp}\W2K12-KB3191565-x64.msu'),21585220); end else
      if IsWindows81OrNewer and not IsWindows10OrNewer then begin MsgBox(ExpandConstant('{cm:Caution8164}'), mbInformation, MB_OK);
        idpAddFileSize('https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win8.1AndW2K12R2-KB3191564-x64.msu',ExpandConstant('{tmp}\Win8.1AndW2K12R2-KB3191564-x64.msu'),19878906); end;
      idpDownloadAfter(wpReady);
    end
    else
    begin
      if IsWindows70OrNewer and not IsWindows80OrNewer then begin MsgBox(ExpandConstant('{cm:Caution7032}'), mbInformation, MB_OK);
        idpAddFileSize('https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win7-KB3191566-x86.zip',ExpandConstant('{tmp}\Win7-KB3191566-x86.zip'),44821734); end else
      if IsWindows81OrNewer and not IsWindows10OrNewer then begin MsgBox(ExpandConstant('{cm:Caution8132}'), mbInformation, MB_OK);
        idpAddFileSize('https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win8.1-KB3191564-x86.msu',ExpandConstant('{tmp}\Win8.1-KB3191564-x86.msu'),15231117); end;
      idpDownloadAfter(wpReady);
    end;
  end;
end;

// Во время показа страницы загрузки открываем по умолчанию скрытые детали загрузки...
procedure CurPageChanged(CurPageID: Integer);
begin
 if not IsWindows10OrNewer then
  begin
    if CurPageID = IDPForm.Page.ID then
    begin
    // Показать детали загрузки
    idpShowDetails(True);
    // Скрываем кнопку Подробно/Скрыть
    IDPForm.DetailsButton.Visible := False;
    end;
  end;
end;

// Распаковываем ранее скачанный ZIP/MSU и запускаем установку...
procedure CurStepChanged(CurStep: TSetupStep);
var
  ResultCode: Integer;
begin
  if CurStep = ssPostInstall then
  begin
    if IsWin64 then
    begin
      if FileExists(ExpandConstant('{tmp}\Win7AndW2K8R2-KB3191566-x64.zip')) then
      begin
        ExtractTemporaryFile('7z.exe');
        ExtractTemporaryFile('7z.dll');
        ShellExec('open',ExpandConstant('{tmp}\7z.exe'),ExpandConstant('x -y -oExtractedArchive ')+ExpandConstant('Win7AndW2K8R2-KB3191566-x64.zip'),'',SW_HIDE,ewWaitUntilTerminated,ResultCode);
        ShellExec('open',ExpandConstant('{sys}\wusa.exe'),ExpandConstant('{tmp}\ExtractedArchive\Win7AndW2K8R2-KB3191566-x64.msu'),'',SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode);
      end;
      if FileExists(ExpandConstant('{tmp}\W2K12-KB3191565-x64.msu')) then ShellExec('open',ExpandConstant('{sys}\wusa.exe'),ExpandConstant('{tmp}\W2K12-KB3191565-x64.msu'),'',SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode);
      if FileExists(ExpandConstant('{tmp}\Win8.1AndW2K12R2-KB3191564-x64.msu')) then ShellExec('open',ExpandConstant('{sys}\wusa.exe'),ExpandConstant('{tmp}\Win8.1AndW2K12R2-KB3191564-x64.msu'),'',SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode);
    end
    else
    begin
      if FileExists(ExpandConstant('{tmp}\Win7-KB3191566-x86.zip')) then
      begin
        ExtractTemporaryFile('7z32.exe');
        ExtractTemporaryFile('7z32.dll');
        ShellExec('open',ExpandConstant('{tmp}\7z32.exe'),ExpandConstant('x -y -oExtractedArchive ')+ExpandConstant('Win7-KB3191566-x86.zip'),'',SW_HIDE,ewWaitUntilTerminated,ResultCode);
        ShellExec('open',ExpandConstant('{sys}\wusa.exe'),ExpandConstant('{tmp}\ExtractedArchive\Win7-KB3191566-x86.msu'),'',SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode);
      end;
      if FileExists(ExpandConstant('{tmp}\Win8.1-KB3191564-x86.msu')) then ShellExec('open',ExpandConstant('{sys}\wusa.exe'),ExpandConstant('{tmp}\Win8.1-KB3191564-x86.msu'),'',SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode);
    end;
  end;
end;

procedure DeinitializeSetup();
begin
  ShowWindow(StrToInt(ExpandConstant('{wizardhwnd}')), 0);
  UnloadSkin();
end;


Поясняю, ошибка возникает, когда я после скачивания PowerShell вставляю код открытия детализации "Показать" и скрытия кнопки "Скрыть" на странице скачивания.
Без этого кода всё работает нормально.
А при вставке кода, сразу ошибка, причём только при условия меньше или больше, а при равенстве условия сравнения версий, всё отрабатывает правильно.
Вот этот короткий код в скрипте:
Код в скрипте, приводящий к ошибке: "could not call proc"
Код:

// Во время показа страницы загрузки открываем по умолчанию скрытые детали загрузки...
procedure CurPageChanged(CurPageID: Integer);
begin
 if not IsWindows10OrNewer then
  begin
    if CurPageID = IDPForm.Page.ID then
    begin
    // Показать детали загрузки
    idpShowDetails(True);
    // Скрываем кнопку Подробно/Скрыть
    IDPForm.DetailsButton.Visible := False;
    end;
  end;
end;


ErikPshat 22-01-2019 00:40 2853687

Эмм, попробую перефразировать по другому...
Я делаю установку программы, которая требует PowerShell последней версии 5.1 для Windows 7/8.0/8.1 (на 10-ке она стоит из коробки).
Так вот, я хочу в инсталляторе отобразить детализацию скачивания файла обновления и убрать там кнопку "Скрыть/Показать".
Но если я добавляю этот код, тогда программа вылетает с ошибкой "could not call proc".
Поэтому я прошу помощи - что я делаю не так?

Выше наверное никому не понятен мой сокращённый код.
Выкладываю готовый код, тоже сокращённый (выкинул все лишние файлы и строки программы), но код компилируемый и рабочий:В строке №76 выставлено условие сравнения < (меньше)
Код:

if ExpandConstant(Copy(PSVersion,1,3)) < ExpandConstant('5.1') then
Если у вас PowerShell устаревшая меньшей версии, тогда будет скачивание и установка.
А если у вас PowerShell уже обновлена, тогда вам нужно будет поменять на = (равно), иначе ничего происходить не будет.

Далее, нужно раскомментировать код отображения детализированных данных между строками 105 - 120:
Код:

procedure CurPageChanged(CurPageID: Integer);
begin
 if not IsWindows10OrNewer then
  begin
  if CurPageID = IDPForm.Page.ID then
    begin
    // Показать детали загрузки
    idpShowDetails(True);
    // Скрываем кнопку Подробно/Скрыть
    IDPForm.DetailsButton.Visible := False;
    end;
  end;
end;

И при условии < попробовать скомпилировать и найти ошибку, почему в этом случае выскакивает "could not call proc".
Что интересно, при условии = (равенства), никакой ошибки при компиляции не происходит.
Пожалуйста профи, не игнорируйте, помогите...

1specific 22-01-2019 10:53 2853723

Цитата:

Цитата Iska
И этого бы я не советовал делать — на подобные вещи могут весьма нервно реагировать поведенческие анализаторы проактивной защиты антивирусов »

Согласен. Риск есть и риск высок. Но мне что-то не приходят другие варианты в голову, как за что еще можно зацепиться, чтобы был некий уникальный параметр установщика без его пересборки.
Исключение - изменение названия инсталлятора перед тем как отдать юзеру. Но высока вероятность что юзер его поменяет.

Цитата:

Цитата Iska
Я бы нацарапал, но думаю, у более опытных в Pascal коллег сие выйдет гораздо лучше. »

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

El Sanchez 22-01-2019 11:27 2853729

Цитата:

Цитата TROY Diamond
а если НЕ "забивать"? )) »

TROY Diamond, вы не знаете размер будущих архивов, поэтому DiskSpaceLabel-у вам нечего предложить.
Цитата:

Цитата TROY Diamond
Как сделать чтобы по умолчанию полученный установщик требовал для запуска права Администратора? "PrivilegesRequired=admin", - НЕ даёт нужного эффекта »

TROY Diamond, разработчик руководствуется тупыми гайдами от Microsoft по разработке десктопных приложений, хотя, возможно, баг, но баг слишком уж долгоживущий в официальной версии, чтобы быть багом. Китайская версия данного поведения не имеет.
Цитата:

Цитата 1specific
за что еще можно зацепиться, чтобы был некий уникальный параметр установщика без его пересборки. »

1specific, например, GUID в конец инсталлятора. Но сначала четко определитесь с термином "успешная установка".
Цитата:

Цитата ErikPshat
if ExpandConstant(Copy(PSVersion,1,3)) < ExpandConstant('5.1') then »

ErikPshat, во-первых, нельзя так версионные строки сравнивать. Когда-нибудь PSVersion станет 10.0 и это условие станет истинным. Во-вторых, ExpandConstant лишние, нет там брекетированных констант. В-третьих, ошибка у вас тогда, когда это выражение не истинно -> не выполняются idp-функции -> не создается IDPForm. И уже в CurPageChanged идет обращение к несуществующей IDPForm.

ErikPshat 22-01-2019 15:39 2853778

El Sanchez, ну когда выйдет версия 10, тогда уже меня не будет ))) Да и даже когда она будет, то всё равно она менее сегодняшней 5.1 не станет по условию. Просто прога требует такую версию, но только в меньших версиях её код не срабатывает, поэтому для работы проги требуется не менее 5.1. Я рад, что хоть так работает )). Насчёт 2-го понял, приму к сведению.

Цитата:

Цитата El Sanchez
В-третьих, ошибка у вас тогда, когда это выражение не истинно -> не выполняются idp-функции -> не создается IDPForm. И уже в CurPageChanged идет обращение к несуществующей IDPForm. »

Вот это мне и непонятно, что нужно сделать, чтобы заставить эту функцию отрабатывать именно после инициализации IDP.Form?
Я пихал её и в начало, и в середину, и в конец момента скачивания. Но всё равно одно и то же, либо ошибка, либо никакого эффекта не происходит. Трудно мне до этого догнать, я всего-то пару месяцев как начал осваивать Inno Setup.

El Sanchez 22-01-2019 17:31 2853796

Цитата:

Цитата ErikPshat
Я пихал её и в начало, и в середину, и в конец момента скачивания. Но всё равно одно и то же, либо ошибка, либо никакого эффекта не происходит. »

ErikPshat,
Скрытый текст

Код:

function StrCmpLogicalW(psz1, psz2: string): Integer; external 'StrCmpLogicalW@shlwapi.dll stdcall';

procedure InitializeWizard;
var
  PSVersion: string;
begin
  if not RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine', 'PowerShellVersion', PSVersion) or
    (StrCmpLogicalW(PSVersion, '5.2') < 0) then
  begin
    { ... }
    { IDPForm.Page is create inside idpDownloadAfter. }
    idpDownloadAfter(wpReady);
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  if not IsWindows10OrNewer and
    Assigned(IDPForm.Page) then
  begin
    if CurPageID = IDPForm.Page.ID then
    begin
      { ... }
    end;
  end;
end;


Iska 22-01-2019 19:01 2853810

Цитата:

Цитата 1specific
А более опытные коллеги видимо даже не обратят внимание на мой пост)) »

Обратят.

Цитата:

Цитата 1specific
Таких как вы по пальцам одной руки пересчитать можно) »

Это далеко не так.


Цитата:

Цитата 1specific
чтобы был некий уникальный параметр установщика »

Но зачем? Я бы просто генерировал тот же GUID на завершающем этапе установки — вот Вам и уникальность. А файл инсталляции должен быть одинаков для всех.

1specific 22-01-2019 22:28 2853866

Цитата:

Цитата Iska
Но зачем? Я бы просто генерировал тот же GUID на завершающем этапе установки — вот Вам и уникальность. А файл инсталляции должен быть одинаков для всех. »

Потому что это делается для партнерской программы.
Чтобы считать количество уникальных скачиваний и знать от какого из партнеров был скачан и установлен файл делается связка md5+hwid
Где md5 привязывается к партнеру в БД и генерится на сервере путем добавления байтов, а hwid как показатель уникальности установки.
После чего данные проверяются, если установка уникальна (hwid,ip и т п), то партнеру засчитывается +1 установка (партнер определяется по md5).

Сгенерировать отдельный установщик под партнера (или как вы говорите GUID) возможно, если бы партнеров было 5-10 или 30. Но партнеров много, и неизвестно сколько. Под каждого генерить установщик это проблемно. Потом их все залить на хост - это уйма места. И далее если программа обновилась, это что каждому партнеру снова собирать и заливать установщик и закреплять руками md5 для каждого?
Поэтому было принято такое решение - исходный файл один, а далее под партнера при скачивании по его реф. ссылке генерится md5, который записывается в базу.

Надеюсь доступно описал весь процесс)

Цитата:

Цитата Iska
Обратят. »

Ну вот за неделю пока кроме вас даже никто и не ответил.

Цитата:

Цитата Iska
Это далеко не так. »

Наверняка много умных и опытных людей, но как я написал выше - судя по всему у них другие интересы.

ErikPshat 23-01-2019 02:29 2853902

El Sanchez, о, спасибо большое! Как просто решаются сложные вопросы )) и как же сложно решить простые задачи ))

Я так понял, эта функция function StrCmpLogicalW - сравнение строк в Unicode-формате встроенными средствами Win API (String Compare Logical Wide).
И вы мне подкинули решение сравнения версий. Немного не ясна для меня прозрачность логики работы (я так понял 5.2 была выставлена для теста?):
Код:

if not RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine', 'PowerShellVersion', PSVersion) or
    (StrCmpLogicalW(PSVersion, '5.1') < 0) then

Я пытаюсь прочитать это и как-то загадочно это. Предположим у пользователя (у меня) установлена последняя версия PowerShell 5.1, тогда читаю:
  • "Если не 5.1.14409.1005 (возвращает PSVersion из реестра) или 0.0.14409.1005 < 0 тогда... begin" и у меня пошла скачка и установка, даже если мне это не надо.
Первое условие из реестра получается никогда не выполняется, а служит только для доставания ключа из реестра в переменную PSVersion?
Вторым условием производится сравнение версии из реестра с требуемой нами. Но тогда и оно не отрабатывает, тем более, если оставить там 5.2.
Или я не правильно эту конструкцию читаю?

По-моему, моя прежняя конструкция вполне прозрачна (для меня) и отрабатывает правильно, даже если завтра выйдет версия 10.
Этот мой код с учётом вашей поправки насчёт лишнего ExpandConstant:
Код:

RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine','PowerShellVersion', PSVersion);
if Copy(PSVersion,1,3) < '5.1' then

Тут просто первой строкой захватываем из реестра версию в переменную PSVersion и второй строкой производим сравнение. Через Copy отсекаем ненужные нам минорные цифры билда и оставляем для сравнения только первые 2 цифры (3 символа с точкой) и сравниваем с требуемой нам цифрой 5.1. Даже если выйдет версия 7.0 или 10.0 (навряд ли), тогда условие же всё равно будет выполняться, т.к. нам нужно чтобы версия PowerShell была не ниже 5.1, а то что старше и больше уже не важно.
На самом деле моей программе достаточно и PowerShell v5.0. Это прога по разбивке и упаковке папок на части по 4 Гб/2 Гб/Целиком, а так же, по загрузке файлов из интернета из XML со ссылками, контрольными суммами, и пр. тех. данными, и средствами PowerSell это удачно реализовалось.
Для справки: на Win 7 из коробки установлена PS 2.0, на Win 8.0 стоит PS 3.0, на Win 8.1 - PS 4.0, на Win 10 - 5.0. Последняя стабильная 5.1. И больше на Windows 10 мало вероятно что предвидится.

Iska 23-01-2019 08:07 2853915

Цитата:

Цитата ErikPshat
И больше на Windows 10 мало вероятно что предвидится. »

4.7 PowerShell Core 6.0

ErikPshat 23-01-2019 09:00 2853918

Iska, ну допустим, пусть будет даже и так. Это ядро пока ещё не зарелизено на оффсайте, там давно уже лежит версия 5.1 и она давно не обновляется. Но разве это на что-то влияет? Предположим программе требуется для её стабильной работы версия 5.1, не меньше, но конечно же можно старше и если у юзера установлена меньшая версия, тогда ему предлагается обновиться как минимум на требуемую 5.1. И что это меняет, для работы моей программы, даже если завтра выйдет PS 6,0, потом 7.0 и так далее? Но они же будут не меньше 5.1, а если у юзера установлена более свежая версия, тогда логично ему и не будет предлагаться скачать и установить 5.1.

Ну я так понял, это просто опровержение моих слов типа "мало вероятно что предвидится" :)

El Sanchez 23-01-2019 10:44 2853938

Цитата:

Цитата ErikPshat
Я пытаюсь прочитать это и как-то загадочно это. Предположим у пользователя (у меня) установлена последняя версия PowerShell 5.1, тогда читаю:
"Если не 5.1.14409.1005 (возвращает PSVersion из реестра) или 0.0.14409.1005 < 0 тогда... begin" и у меня пошла скачка и установка, даже если мне это не надо. »

ErikPshat, немного я протупил, все-таки там 5.1 должно стоять. Главное, сначала правильно написал, потом переклинило и на 5.2 исправил :).
Цитата:

Цитата ErikPshat
Первое условие из реестра получается никогда не выполняется, а служит только для доставания ключа из реестра в переменную PSVersion?
Вторым условием производится сравнение версии из реестра с требуемой нами. Но тогда и оно не отрабатывает, тем более, если оставить там 5.2. »

ErikPshat, если не прочитали версию, то сравнивать нечего, нет у нас PowerShell, выполняем блок. Если прочитали, то сравниваем то, что прочитали, по результату проверки выполняем блок. Также в блоке пропишите сообщение, когда PowerShell не установлен (выпонилось первое условие).
Цитата:

Цитата ErikPshat
По-моему, моя прежняя конструкция вполне прозрачна (для меня) и отрабатывает правильно, даже если завтра выйдет версия 10. »

ErikPshat, отлично, выходит 10.0.0.1, вы с Copy режете до 3 символов, теперь сравните строки '10.' < '5.1'. Ой.

Iska 23-01-2019 17:19 2854071

ErikPshat, мы уже поимели версию ОС Windows за номером 10.0 сразу после версии 6.3. Так что не зарекайтесь.

ErikPshat 23-01-2019 19:39 2854123

El Sanchez, ещё раз благодарю за помощь и разъяснения! Потихоньку кое-что проясняется.

Есть ещё один один момент, который я оказывается упустил. Дело в том, что на Windows Vista идёт версия PS 1.0, на Windows 7 идёт из коробки версия PS 2.0 и что самое важное, они прописываются по другому пути в реестре, там разница в цифре 1 в пути:
Код:

SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine
А, начиная с Windows 8.0 PS 3.0 в пути вместо 1 идёт 3. Получается, что на 7-ке будет возвращаться пустая строка, как и в Vista (но ей пристального внимания уже не уделяем).
Тогда получается, нужно добавить условие проверки ключа реестра под 7-ку. Правильно ли будет, если я сделаю так:
Код:

if not RegQueryStringValue(HKLM,'SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine','PowerShellVersion',PSVersion) or
  not RegQueryStringValue(HKLM,'SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine','PowerShellVersion',PSVersion) or
  (StrCmpLogicalW(PSVersion, '5.1') < 0) then

Либо можно соорудить другую конструкцию через if и else, т.е. провести по отдельности верификацию через первый ключ, в противном случае через второй.

Цитата:

Цитата Iska
ErikPshat, мы уже поимели версию ОС Windows за номером 10.0 сразу после версии 6.3. »

Цитата:

Цитата El Sanchez
ErikPshat, отлично, выходит 10.0.0.1, вы с Copy режете до 3 символов, теперь сравните строки '10.' < '5.1'. Ой. »

Предположим, выйдет версия 10.0123.456, через Copy мы отсекаем первые 3 символа, получится 10. (десять с точкой).
Тогда при сравнении 10. < 5.1 разве система не поймёт, что нужно сравнивать цифры до точки, а потом после точки. Если стоит точка, тогда думаю система должна определять, что это дробная запятая и, если после точки ничего не стоит, то это означает 0, т.е. 10.0 < 5.1. Это конечно можно проверить на практике, но пока это так, размышления и аналитическая деятельность.

Iska 23-01-2019 20:09 2854126

Цитата:

Цитата ErikPshat
Это конечно можно проверить на практике, но пока это так, размышления и аналитическая деятельность. »

Проверяю:
AutoIt
Код:

AutoItSetOption("MustDeclareVars", 1)

ConsoleWrite( _
        "Returns  0 if the strings are identical." & @CRLF & _
        "Returns  1 if the string pointed to by psz1 has a greater value than that pointed to by psz2." & @CRLF & _
        "Returns -1 if the string pointed to by psz1 has a lesser value than that pointed to by psz2."  & @CRLF & @CRLF _
)


ConsoleWrite("1    w/s 5  ==> " & String(_StrCmpLogicalW("1",    "5"  )) & @CRLF)
ConsoleWrite("1    w/s 5.0 ==> " & String(_StrCmpLogicalW("1",    "5.0")) & @CRLF)
ConsoleWrite("1.0  w/s 5  ==> " & String(_StrCmpLogicalW("1.0",  "5"  )) & @CRLF)
ConsoleWrite("1.0  w/s 5.0 ==> " & String(_StrCmpLogicalW("1.0",  "5.0")) & @CRLF)

ConsoleWrite(@CRLF)

ConsoleWrite("10  w/s 5  ==> " & String(_StrCmpLogicalW("10",  "5"  )) & @CRLF)
ConsoleWrite("10  w/s 5.0 ==> " & String(_StrCmpLogicalW("10",  "5.0")) & @CRLF)
ConsoleWrite("10.0 w/s 5  ==> " & String(_StrCmpLogicalW("10.0", "5"  )) & @CRLF)
ConsoleWrite("10.0 w/s 5.0 ==> " & String(_StrCmpLogicalW("10.0", "5.0")) & @CRLF)

ConsoleWrite(@CRLF)

ConsoleWrite("10  w/s 10  ==> " & String(_StrCmpLogicalW("10",  "10"  )) & @CRLF)
ConsoleWrite("10  w/s 10.0 ==> " & String(_StrCmpLogicalW("10",  "10.0")) & @CRLF)
ConsoleWrite("10.0 w/s 10  ==> " & String(_StrCmpLogicalW("10.0", "10"  )) & @CRLF)
ConsoleWrite("10.0 w/s 10.0 ==> " & String(_StrCmpLogicalW("10.0", "10.0")) & @CRLF)

Exit(0)

Func _StrCmpLogicalW($s1, $s2)
        Return DllCall('shlwapi.dll', 'int', 'StrCmpLogicalW', 'wstr', $s1, 'wstr', $s2)[0]
EndFunc

Цитата:

Код:

Returns  0 if the strings are identical.
Returns  1 if the string pointed to by psz1 has a greater value than that pointed to by psz2.
Returns -1 if the string pointed to by psz1 has a lesser value than that pointed to by psz2.

1    w/s 5  ==> -1
1    w/s 5.0 ==> -1
1.0  w/s 5  ==> -1
1.0  w/s 5.0 ==> -1

10  w/s 5  ==> 1
10  w/s 5.0 ==> 1
10.0 w/s 5  ==> 1
10.0 w/s 5.0 ==> 1

10  w/s 10  ==> 0
10  w/s 10.0 ==> -1
10.0 w/s 10  ==> 1
10.0 w/s 10.0 ==> 0



Отдельное внимание на последнюю группу.

El Sanchez 23-01-2019 21:42 2854146

Цитата:

Цитата ErikPshat
огда получается, нужно добавить условие проверки ключа реестра под 7-ку. Правильно ли будет, если я сделаю так: »

ErikPshat, нет. Вы проверяете наличие PS 5.0, так что чтение из PowerShell\1 бессмысленно.
Цитата:

Цитата ErikPshat
Тогда при сравнении 10. < 5.1 разве система не поймёт, что нужно сравнивать цифры до точки, а потом после точки. »

ErikPshat, нет. Строковые литералы сравниваются посимвольно и сравнение закончится на первом символе, т.к. '1' < '5'.
Цитата:

Цитата Iska
10 w/s 10.0 ==> -1
10.0 w/s 10 ==> 1 »

Iska, хе-хе, об этом надо помнить. Кстати, StrCmpLogicalW еще и -2 возвращает, если какой-либо параметр пуст.

ErikPshat 24-01-2019 00:26 2854175

Iska, El Sanchez, ага, спасибо! Понятно, значит идёт посимвольное сравнение как текст, а не как цифры.

Да, я это на практике проверил, поменял в реестре версию PS, просто добавил 1 спереди, получилось 15.1 )))
Оказывается для 64-битки путь автоматически в реестре меняется на Wow6432Node:
Код:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\PowerShell\3\PowerShellEngine
И вывел через MsgBox версию, чтобы воочию убедиться верно ли возвращает:



Ну и далее пошло скачивание и установка, т.е. условие сравнения не выполнилось правильно. То есть, вы правы, сравнение идёт посимвольно и никакие точки, запятые, дроби тут не учитываются. Ещё нашёл функцию в Inno Preprocessor - DecodeVer и EncodeVer, но не понял, почему она не задействуется сразу, хотя вроде бы функция объявлена изначально по умолчанию.

Iska 24-01-2019 06:51 2854198

Цитата:

Цитата El Sanchez
Кстати, StrCmpLogicalW еще и -2 возвращает, если какой-либо параметр пуст. »

Что ж они, заразы, не пишут об том?

Но зато пишут не менее интересное:
Цитата:

Note Behavior of this function, and therefore the results it returns, can change from release to release. It should not be used for canonical sorting applications.
:lol:.


Цитата:

Цитата ErikPshat
Оказывается для 64-битки путь автоматически в реестре меняется на Wow6432Node: »

Да нет. Это только если Ваше приложение — x86 под x64 ОС. А так раздел HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell вполне себе существует под x64 ОС. У меня, например, под Windows 7 SP1 x64 он выглядит так:
Скрытый текст
Код:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell]
"DisablePromptToUpdateHelp"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1]
"Install"=dword:00000001
"PID"="89383-100-0001260-04309"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\0409]
"Install"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine]
"ApplicationBase"="C:\\Windows\\System32\\WindowsPowerShell\\v1.0"
"PSCompatibleVersion"="1.0, 2.0"
"RuntimeVersion"="v2.0.50727"
"ConsoleHostAssemblyName"="Microsoft.PowerShell.ConsoleHost, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=msil"
"ConsoleHostModuleName"="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\Microsoft.PowerShell.ConsoleHost.dll"
"PowerShellVersion"="2.0"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PSConfigurationProviders]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PSConfigurationProviders\Microsoft.PowerShell]
"ApplicationBase"="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\"
"AssemblyName"="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=msil"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell]
"Path"="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
"ExecutionPolicy"="RemoteSigned"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\ScriptedDiagnostics]
"ExecutionPolicy"="Unrestricted"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3]
"ConsoleHostShortcutTargetX86"=hex(2):25,00,50,00,72,00,6f,00,67,00,72,00,61,\
  00,6d,00,44,00,61,00,74,00,61,00,25,00,5c,00,4d,00,69,00,63,00,72,00,6f,00,\
  73,00,6f,00,66,00,74,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,5c,\
  00,53,00,74,00,61,00,72,00,74,00,20,00,4d,00,65,00,6e,00,75,00,5c,00,50,00,\
  72,00,6f,00,67,00,72,00,61,00,6d,00,73,00,5c,00,41,00,63,00,63,00,65,00,73,\
  00,73,00,6f,00,72,00,69,00,65,00,73,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,\
  77,00,73,00,20,00,50,00,6f,00,77,00,65,00,72,00,53,00,68,00,65,00,6c,00,6c,\
  00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,20,00,50,00,6f,00,77,00,\
  65,00,72,00,53,00,68,00,65,00,6c,00,6c,00,20,00,28,00,78,00,38,00,36,00,29,\
  00,2e,00,6c,00,6e,00,6b,00,00,00
"ConsoleHostShortcutTarget"=hex(2):25,00,50,00,72,00,6f,00,67,00,72,00,61,00,\
  6d,00,44,00,61,00,74,00,61,00,25,00,5c,00,4d,00,69,00,63,00,72,00,6f,00,73,\
  00,6f,00,66,00,74,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,5c,00,\
  53,00,74,00,61,00,72,00,74,00,20,00,4d,00,65,00,6e,00,75,00,5c,00,50,00,72,\
  00,6f,00,67,00,72,00,61,00,6d,00,73,00,5c,00,41,00,63,00,63,00,65,00,73,00,\
  73,00,6f,00,72,00,69,00,65,00,73,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,\
  00,73,00,20,00,50,00,6f,00,77,00,65,00,72,00,53,00,68,00,65,00,6c,00,6c,00,\
  5c,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,20,00,50,00,6f,00,77,00,65,\
  00,72,00,53,00,68,00,65,00,6c,00,6c,00,2e,00,6c,00,6e,00,6b,00,00,00
"Install"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3\0409]
"Install"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine]
"ApplicationBase"="C:\\Windows\\System32\\WindowsPowerShell\\v1.0"
"PSPluginWkrModuleName"="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\system.management.automation.dll"
"PSCompatibleVersion"="1.0, 2.0, 3.0, 4.0, 5.0, 5.1"
"RuntimeVersion"="v4.0.30319"
"ConsoleHostAssemblyName"="Microsoft.PowerShell.ConsoleHost, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=msil"
"ConsoleHostModuleName"="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\Microsoft.PowerShell.ConsoleHost.dll"
"PowerShellVersion"="5.1.14409.1005"


ErikPshat 24-01-2019 08:11 2854206

Iska, ну да, у меня то же самое. Просто я говорю о том, что по обычному пути поменял версию PowerShell, потом удивился, что как на скриншоте выше версия не изменилась. Сначала не понял, что за фокусы, подумал, может быть изменения не применились, перезагрузился, снова скомпилировал и опять показывает мне ответ 5.1, хотя я поменял на 15.1 ))) Потом вспомнил об этой ветке реестра, полез туда и там поменял, тогда оно и показалось во всей красе. Ну это я просто так написал, вдруг кому по ходу дела пригодится. Правда, чтобы сменить версию PS в реестре, пришлось себя владельцем ветки сделать, а потом и права выдать :D.

Iska 24-01-2019 19:23 2854353

Цитата:

Цитата ErikPshat
Правда, чтобы сменить версию PS в реестре, пришлось себя владельцем ветки сделать, а потом и права выдать :D. »

ErikPshat, обзаведитесь Far Manager'ом (и одним-двумя плагинами под него для работы с реестром) — и Вам никогда больше не придётся таким заниматься.

1specific 25-01-2019 14:05 2854525

Всем привет.
Ищу человека который отлично ладит с inno setup.
Задача: сделать стучалку на сервер при установке программы, чтобы можно было подсчитать количество уникальных установок (подсчет уже на уровне сервера и к задаче не имеет отношения). Более подробно писал об этом в этом посте.
Разумеется "не за спасибо".
Пишите в ЛС. Договоримся!

Iska 25-01-2019 17:59 2854583

Цитата:

Цитата 1specific
Ищу человека который отлично ладит с inno setup. »

El Sanchez, беритесь.

El Sanchez 25-01-2019 20:47 2854620


Цитата:

Цитата Iska
El Sanchez, беритесь. »

Iska, вменяемого ТЗ нет, показания меняются. Мне страшно. :)

Цитата:

Цитата 1specific
Задача: сделать стучалку на сервер при установке программы, чтобы можно было подсчитать количество уникальных установок (подсчет уже на уровне сервера и к задаче не имеет отношения) »

1specific, я уже спрашивал про "успешная установка", теперь пришла очередь спросить про "уникальных скачиваний" и "уникальных установок". Что считаем? Количество скачиваний <> количество установок. Скачивания считать бессмысленно, можно скачать установщик 1000 раз и ни разу ничего не поставить. Значит, установки. Чтобы посчитать количество уникальных установок, нужно дать определение уникальной установке. Считать ли установку уникальной, если делается второй раз в другую папку установки, нежели первая? А установка на другой физический диск уникальна?

TROY Diamond 25-01-2019 22:37 2854640

Цитата:

Цитата El Sanchez
вы не знаете размер будущих архивов, поэтому DiskSpaceLabel-у вам нечего предложить.

El Sanchez, а если я знаю, размер будущих архивов, хотя бы примерно, либо если нужен конкретный размер свободного места, например 15 ГБ, вполне хватит, это лучше чем 20-25, сколько хочет установщик с учётом распакованных архивов!

Цитата:

Цитата El Sanchez
разработчик руководствуется тупыми гайдами от Microsoft по разработке десктопных приложений, хотя, возможно, баг, но баг слишком уж долгоживущий в официальной версии, чтобы быть багом. Китайская версия данного поведения не имеет.

Так и какое же решение использовать китайскую версию или продолжать корректировать манифест у готового (скомпилированного) setup.exe?

Мне принципиально нужно чтобы установщик запускался и требовал права Администратора, а тех пользователей у которых нет прав Администратора или которые не хотят запускать с правами Админа установщик - обойдутся! (есть такие даже в 2019 году ещё) странно, - да, что программе которая копирует свои файлы в системные папки, и/или регистрирует какие-то библиотеки, делает записи в реестре - нужны права Администратора? )))

1specific 26-01-2019 00:49 2854659

Цитата:

Цитата El Sanchez
1specific, я уже спрашивал про "успешная установка", теперь пришла очередь спросить про "уникальных скачиваний" и "уникальных установок". Что считаем? Количество скачиваний <> количество установок. Скачивания считать бессмысленно, можно скачать установщик 1000 раз и ни разу ничего не поставить. Значит, установки. Чтобы посчитать количество уникальных установок, нужно дать определение уникальной установке. Считать ли установку уникальной, если делается второй раз в другую папку установки, нежели первая? А установка на другой физический диск уникальна? »

El Sanchez, Я уже косвенно отвечал в других постах на этот вопрос, в общем то уникальная установка = уникальный компьютер.
Разумеется скачивания и запуски установщика считать бессмысленно. Поэтому нужно считать только успешные установки. И после успешной установки выполнять сценарий отправки на сервер hwid пользователя (как идентификатор уникальной железяки = уникальной установки) и md5 установщика (как идентификатор реферала).
Знаю что md5 вариант не самый лучший. Но я исхожу из того, что просто не смогу физически создать и содержать для каждого партнера отдельный установщик, и обновлять его при необходимости. А вот md5 могу генерировать сервером и записывать в базу перед тем как отдать файл на скачивание, практически на лету.

Дополнительным преимуществом защиты от накрутки может быть отправка и других данных, например версия OS, локальная дата и время установки и т.п. - тут уже лучше с вами (исполнителем) пообщаться на эту тему лично.

Если будут еще вопросы - с радостью отвечу.

El Sanchez 26-01-2019 20:14 2854770

Цитата:

Цитата TROY Diamond
а если я знаю, размер будущих архивов, хотя бы примерно, либо если нужен конкретный размер свободного места, например 15 ГБ, вполне хватит, это лучше чем 20-25, сколько хочет установщик с учётом распакованных архивов! »

TROY Diamond, требуемый размер недоступен извне, повлиять на величину можно только в большую сторону.
Цитата:

Цитата TROY Diamond
Так и какое же решение использовать китайскую версию или продолжать корректировать манифест у готового (скомпилированного) setup.exe? »

TROY Diamond, вопрос и является ответом на него.
Цитата:

Цитата 1specific
И после успешной установки выполнять сценарий отправки на сервер hwid пользователя (как идентификатор уникальной железяки = уникальной установки) и md5 установщика (как идентификатор реферала). »

1specific, идентификатор реферала серверу известен и его можно сравнить с тем, что клиент вернет, а вот достоверность полученного HWID сервер не проверит. А еще будут качать, но ставить без Интернет, программа установлена, но сервер подтверждение не получит.

1specific 26-01-2019 22:39 2854797

Цитата:

Цитата El Sanchez
а вот достоверность полученного HWID сервер не проверит »

Верно. Но можно проверить его уникальность по существующим уже в базам. Это уже хоть что-то.
+ если сюда включить OS и возможно какие то другие уникальные данные (например дату установки винды, или какие то данные из реестра) то уже можно хоть какой то портрет пользователя получить.
Вариантов лучше я придумать не смог. Можете что-то предложить?

Цитата:

Цитата El Sanchez
А еще будут качать, но ставить без Интернет, программа установлена, но сервер подтверждение не получит. »

Ну это маловероятно учитывая специфику софта. Софт без интернета сам по себе бесполезен, так что ставить его будут те у кого интернет есть. Но если даже кто то поставит без интернета, то это небольшой процент, который можно включить в погрешность.

Iska 26-01-2019 23:09 2854806

Цитата:

Цитата El Sanchez
а вот достоверность полученного HWID сервер не проверит. »

Придумать какую-нибудь простенькую контрольную сумму, которую включать в отсылаемые данные, и по которой сервер сможет судить о том, что переданные данные были сгенерированы программно, а не представляют собой случайную отсебятину для накруток. Пока не разберут код или не накопят статистику передач — будет хоть какая-то гарантия «честности» полученных данных.

Цитата:

Цитата 1specific
Софт без интернета сам по себе бесполезен, так что ставить его будут те у кого интернет есть. Но если даже кто то поставит без интернета, »

Ещё один плюс в пользу того, что «стучать» надо из самого приложения, а не из инсталляции.

1specific 26-01-2019 23:31 2854816

Цитата:

Цитата Iska
Придумать какую-нибудь простенькую контрольную сумму, которую включать в отсылаемые данные, и по которой сервер сможет судить о том, что переданные данные были сгенерированы программно, а не представляют собой случайную отсебятину для накруток. »

Спасибо. Гениально и просто)) Насколько я знаю это еще называют солью (например в паролях её добавляют:) Ну примерно так, в целом посыл понятен )

Цитата:

Цитата Iska
Ещё один плюс в пользу того, что «стучать» надо из самого приложения, а не из инсталляции. »

Во первых это уже не партнерка за установку, а партнерка за запуск получится. Ну а во-вторых у меня нет возможности такое реализовать в ближайшей перспективе... Поэтому на данный момент лучше через установщик, чем никак.

TROY Diamond 27-01-2019 00:27 2854819

Цитата:

Цитата El Sanchez
требуемый размер недоступен извне, повлиять на величину можно только в большую сторону.

1. El Sanchez А, как же например, в репаках игр указывают Для установки (распаковки) требуется столько-то места и если его меньше установку продолжить невозможно? Это значение ведь указывается вручную?

2. El Sanchez и Iska - НЕ знаю у кого спросить, подскажите, пожалуйста, где можно найти информацию про подписывания цифровой подписью своего дистрибутива? Видел такую реализацию в некоторых репаках сделанных в Inno Setip и аддонах на основе SFX-архивов и Inno Setup. Пусть это будет "НЕ серьезная" цифровая подпись - просто чтобы проверяла целостность и контрольные суммы файла.

Iska 27-01-2019 01:09 2854821

Цитата:

Цитата TROY Diamond
Это значение ведь указывается вручную? »

Нет. Эти значения рассчитываются автоматически при создании инсталлятора в зависимости от объёма результирующих файлов.

TROY Diamond 27-01-2019 02:10 2854828

Iska, нет это нечто иное сделанное с помощью скрипта, т.к. дальнейшая установка невозможна если места не хватает! А "значения рассчитываются автоматически" - только информирует.

P.S. По второму вопросу кто может помочь?

Iska 27-01-2019 05:48 2854833

Цитата:

Цитата TROY Diamond
дальнейшая установка невозможна если места не хватает! »

Естественно. Откуда может взяться возможность что-то записать на раздел, если на нём не осталось свободного места?!

El Sanchez 27-01-2019 11:03 2854846

Цитата:

Цитата 1specific
Но можно проверить его уникальность по существующим уже в базам. Это уже хоть что-то. »

Нет у вас баз.
Цитата:

Цитата 1specific
если сюда включить OS и возможно какие то другие уникальные данные (например дату установки винды, или какие то данные из реестра) то уже можно хоть какой то портрет пользователя получить. »

1specific, OS, MAC, IP, CPUID, BIOS - все не то. Более-менее подходит связка серийный номер MB + код производителя HDD, на котором система лежит. Только серверу от этого HWID ни горячо, ни холодно.
Цитата:

Цитата Iska
Придумать какую-нибудь простенькую контрольную сумму, которую включать в отсылаемые данные, и по которой сервер сможет судить о том, что переданные данные были сгенерированы программно, а не представляют собой случайную отсебятину для накруток. »

Iska, алгоритм должен быть известен и серверу и установщику, а скриптовый движок в Inno штука ненадежная - можно восстановить исходный код секции Code до такого вида, что будет давать идентичный байткод.

1specific 27-01-2019 11:17 2854849

Цитата:

Цитата El Sanchez
Нет у вас баз. »

В смысле нету? Речь о моей базе. HWID туда записывается. Если такой уже есть в базе значит не засчитывается утсановка.

В целом не понятно какие варианты тогда есть чтобы реализовать задумку на уровне inno setup?)

nik1967 27-01-2019 14:24 2854870

Цитата:

Цитата TROY Diamond
где можно найти информацию про подписывания цифровой подписью своего дистрибутива?»

Ответил в PM.

Требуемое место установки

#Define NeedSize 5000
;;Если у вас архивы FreeArc, то здесь укажите сколько необходимо места в Мб
;;Иначе просто закоментируйте строку
;;Автор: Shegorat

[Setup]
AppName=My Program
AppVerName=My Program v 1.5
DefaultDirName={pf}\My Program
OutputDir=.
Compression=lzma/ultra
InternalCompressLevel=ultra
SolidCompression=yes

[Languages]
Name: ENG; MessagesFile: "compiler:Default.isl"
Name: RUS; MessagesFile: "compiler:Languages\Russian.isl"

[Files]
Source: {win}\help\*.hlp; DestDir: {app}\Files; Flags: external

[CustomMessages]
RUS.FreeSpace=Доступно места на диске:
RUS.NeedSpace=Требуется места на диске:
RUS.MB=Мб
RUS.GB=Гб
RUS.TB=Тб
ENG.FreeSpace=Free space on disk:
ENG.NeedSpace=Need space on disk:
ENG.MB=Mb
ENG.GB=Gb
ENG.TB=Tb

[code]
var
NeedSpaceLabel,FreeSpaceLabel: TLabel;
FreeMB, TotalMB: Cardinal;
SizeStr: String;
SizeInt: Integer;
SymbolNumber: Integer;

function GetSize(): Integer;
begin
SizeStr:= WizardForm.DiskSpaceLabel.Caption;
for SymbolNumber:= 97 to 122 do begin
while (Pos(Chr(SymbolNumber), SizeStr) > 0) do Delete(SizeStr, Pos(Chr(SymbolNumber), SizeStr),1);
while (Pos(AnsiUppercase(Chr(SymbolNumber)), SizeStr) > 0) do Delete(SizeStr, Pos(AnsiUppercase(Chr(SymbolNumber)), SizeStr),1);
end;
for SymbolNumber:= 192 to 255 do begin
while (Pos(Chr(SymbolNumber), SizeStr) > 0) do Delete(SizeStr, Pos(Chr(SymbolNumber), SizeStr),1);
end;
while (Pos('.', SizeStr) > 0) do Delete(SizeStr, Pos('.', SizeStr), 1);
Delete(SizeStr, Pos(',', SizeStr), 5)
Result:= StrToInt(Trim(SizeStr));
end;

function CompareNum(FirstNum, SecondNum: Integer): Boolean;
begin
if FirstNum < SecondNum then Result:= False else Result:= True;
end;

function NumToStr(Float: Extended): String;
begin
Result:= Format('%.2f', [Float]);
StringChange(Result, ',', '.');
while ( Pos('.', Result) > 0 ) and ( (Result[Length(Result)] = '0') or (Result[Length(Result)] = '.') ) do
SetLength(Result, Length(Result) - 1);
end;

function MbOrTb(Float: Extended): String;
begin
if
Float < 1024 then Result:= NumToStr(Float)+ExpandConstant(' {cm:MB}') else
if
Float/1024 < 1024 then Result:= NumToStr(Float/1024)+ExpandConstant(' {cm:GB}') else
Result:= NumToStr(Float/(1024*1024))+ExpandConstant(' {cm:TB}');
end;

procedure GetFreeSpaceCaption(Sender: TObject);
var
Path: String;
begin
Path:= ExtractFileDrive(WizardForm.DirEdit.Text);
GetSpaceOnDisk(Path, True, FreeMB, TotalMB);
FreeSpaceLabel.Caption:= ExpandConstant('{cm:FreeSpace} ') + MbOrTb(FreeMB);
NeedSpaceLabel.Caption:= ExpandConstant('{cm:NeedSpace} ') + MbOrTb(SizeInt);
if WizardForm.CurPageID = wpSelectDir then begin
WizardForm.NextButton.Enabled:= CompareNum(FreeMB, SizeInt);
end;
end;

procedure InitializeWizard();
begin
WizardForm.DiskSpaceLabel.Hide;
#ifdef NeedSize
SizeInt:= {#NeedSize}
#else
SizeInt:= GetSize;
#endif

NeedSpaceLabel:= TLabel.Create(WizardForm);
NeedSpaceLabel.SetBounds(ScaleX(0), ScaleY(198), ScaleX(209), ScaleY(13))
NeedSpaceLabel.Parent:= WizardForm.SelectDirPage;
NeedSpaceLabel.Transparent:= true;

FreeSpaceLabel:= TLabel.Create(WizardForm);
FreeSpaceLabel.SetBounds(ScaleX(0), ScaleY(216), ScaleX(209), ScaleY(13))
FreeSpaceLabel.Parent:= WizardForm.SelectDirPage;
FreeSpaceLabel.Transparent:= true;

WizardForm.DirEdit.OnChange:= @GetFreeSpaceCaption;
WizardForm.DirEdit.Text:= WizardForm.DirEdit.Text + #0;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpSelectDir then GetFreeSpaceCaption(nil);
end;

Iska 27-01-2019 14:50 2854879

Цитата:

Цитата El Sanchez
Iska, алгоритм должен быть известен и серверу и установщику »

Конечно. Иначе — какой смысл?!

Цитата:

Цитата El Sanchez
а скриптовый движок в Inno штука ненадежная - можно восстановить исходный код секции Code до такого вида, что будет давать идентичный байткод. »

Ото ж. Третий довод в пользу того, что:
Цитата:

Цитата Iska
…«стучать» надо из самого приложения, а не из инсталляции. »

:).

1specific 27-01-2019 18:49 2854923

Цитата:

Цитата Iska
Ото ж. Третий довод в пользу того, что:
Цитата Iska:
…«стучать» надо из самого приложения, а не из инсталляции. » »

Возможности такой нет.
Значит делаем как можем.
Кто готов - пожалуйста, буду рад обсудить детали и приступить.
На данный момент нужно хоть какое то решение, дальше уже можно будет переделывать и улучшать.

TROY Diamond 27-01-2019 19:36 2854933

Цитата:

Цитата Iska
Естественно. Откуда может взяться возможность что-то записать на раздел, если на нём не осталось свободного места?!

Iska, почему-то nik1967 - понял о чём речь и как сделать?

Iska 27-01-2019 20:23 2854943

TROY Diamond, значит, я был не прав. Однако сие никак не поможет изменить ситуацию, если места действительно не хватает.

El Sanchez 27-01-2019 20:41 2854946

Цитата:

Цитата 1specific
Значит делаем как можем. »

1specific, можно ограничиться серверной частью примерно так:
1. Компилируется мастер-копия установщика.
2. Клиент по партнерской ссылке запрашивает файл.
3. Сервер делает копию мастер-файла, генерирует GUID и записывает его в конец копии.
4. Копия отдается клиенту.
5. Если ошибок при приеме-передаче не было, GUID заносится в таблицу партнера в БД.
6. Сервер удаляет копию.
7. Установщик в конце установки считывает GUID и посылает его на сервер GET-запросом в параметрах.
8. Сервер проверяет GUID в БД. Если есть, то гут, партнеру +1, GUID удаляется из БД. Если нет, то попытка накрутки, баловство и прочие ништяки, с которыми скоро придется познакомиться.
Цитата:

Цитата TROY Diamond
почему-то nik1967 - понял о чём речь и как сделать »

TROY Diamond, а толку? Установщик посчитает 15 ГБ, а вы отобразите 10 ГБ. Если у юзера будет свободного места от 10 до 15 ГБ, то он увидит ругань, что нет места, а в ваш адрес полетит ругань уже юзерскыя, мол, "у миня 14 гигов ессть еще, какого оно 10 пишит тада?" (орфография пользователя сохранена)

1specific 27-01-2019 23:17 2854969

Цитата:

Цитата El Sanchez
Компилируется мастер-копия установщика. »

Каким образом сделать это на php? Я не встречал такого компилятора inno setup для php (а веб часть будет на php)

Цитата:

Цитата El Sanchez
Сервер делает копию мастер-файла, генерирует GUID и записывает его в конец копии. »

Какие в этом преимущества? md5 всё-ровно поменяется для каждой копии.


По сути вся схема реализации уже понятна.
От инсталлятора просто требуется отправить нужные данные на сервер и всё (+ возможно добавление контрольной суммы к каким то данным) . Это небольшой кусок кода. Возьметесь?

TROY Diamond 27-01-2019 23:51 2854971

Цитата:

Цитата El Sanchez
а толку? Установщик посчитает 15 ГБ, а вы отобразите 10 ГБ. Если у юзера будет свободного места от 10 до 15 ГБ, то он увидит ругань, что нет места, а в ваш адрес полетит ругань уже юзерскыя, мол, "у миня 14 гигов ессть еще, какого оно 10 пишит тада?" (орфография пользователя сохранена)

El Sanchez, поэтому я вас ОЧЕНЬ и просил такой скрипт, который будет удалять сразу все временные папки в процессе установки по её ходу, а НЕ по её окончании, как это делается в большинстве репаков игр!

Например, один архив (УСЛОВНО) весит в упакованном виде 700 МБ, распакованная папка, которая будет скопирована в процессе установки, будет занимать на ЖД 1,5 ГБ (условно), через 1-2 минуты ЭТА ПАПКА, будет упакована в архив и СРАЖУ ЖЕ УДАЛЕНА, останется только 700 МБ архив на ЖД пользователя, начнётся копирование следующей папки, которая также упакуется в архив и удалится. Поэтому 15 ГБ, с запасом хватит, а если бы папки НЕ удалялись бы сразу же, то тогда нужно было бы как раз 30 ГБ места на ЖД.

Игра в конечном итоге (в готовом к "употреблению" виде), по окончании установки, занимает на ЖД - всего 12 ГБ (условно) - я хочу задать 15 ГБ, с запасом, вместо 20-25 ГБ, сколько хочет Inno Setip из расчёта скомпилированного...

El Sanchez, мы друг друга правильно поняли? Теперь когда всё ясно можете, помочь?

El Sanchez 28-01-2019 13:12 2855011

Цитата:

Цитата 1specific
Каким образом сделать это на php? Я не встречал такого компилятора inno setup для php (а веб часть будет на php) »

1specific, мастер-копия - это то, что вы в Inno Setup сделаете и на свой сервер закинете. Измененные копии этого файла идут клиентам.
Цитата:

Цитата 1specific
Какие в этом преимущества? md5 всё-ровно поменяется для каждой копии. »

1specific, клиенту перед отправкой подтверждения установки необходимо будет эту MD5 посчитать, а это небыстрая операция, если файл большой.
Цитата:

Цитата 1specific
От инсталлятора просто требуется отправить нужные данные на сервер и всё (+ возможно добавление контрольной суммы к каким то данным) . Это небольшой кусок кода. »

1specific, отправляйте:
Скрытый текст

Код:

[Code]
#define A = (Defined UNICODE) ? "W" : "A"
const
  SXH_PROXY_SET_PROXY = 2;

procedure SendID;
var
  XMLHTTP: Variant;
  ProxyEnable: Cardinal;
  ProxyServer, ProxyOverride: string;
  Data: AnsiString;
begin
  XMLHTTP := CreateOleObject('MSXML2.ServerXMLHTTP');
  try
    if RegQueryDWordValue(HKCU, 'Software\Microsoft\Windows\CurrentVersion\Internet Settings', 'ProxyEnable', ProxyEnable) and (ProxyEnable = 1) then
    begin
      if RegQueryStringValue(HKCU, 'Software\Microsoft\Windows\CurrentVersion\Internet Settings', 'ProxyServer', ProxyServer) and
        RegQueryStringValue(HKCU, 'Software\Microsoft\Windows\CurrentVersion\Internet Settings', 'ProxyOverride', ProxyOverride) then
          XMLHTTP.setProxy(SXH_PROXY_SET_PROXY, ProxyServer, ProxyOverride);
    end;
    XMLHTTP.open('POST', 'https://httpbin.org/post'{'http://site.ru/success.php'}, False);
    XMLHTTP.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    Data := 'id=12345678'// custom data
    XMLHTTP.send(Data);
    Log(Format('Error Code: %s %s', [XMLHTTP.status, XMLHTTP.statusText]));
  except
    Log(GetExceptionMessage);
  finally
  end;
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
  case CurStep of
    ssPostInstall: SendID;
  end;
end;


Цитата:

Цитата TROY Diamond
один архив (УСЛОВНО) весит в упакованном виде 700 МБ, распакованная папка, которая будет скопирована в процессе установки, будет занимать на ЖД 1,5 ГБ (условно), через 1-2 минуты ЭТА ПАПКА, будет упакована в архив и СРАЖУ ЖЕ УДАЛЕНА, останется только 700 МБ архив на ЖД пользователя, начнётся копирование следующей папки, которая также упакуется в архив и удалится. Поэтому 15 ГБ, с запасом хватит, а если бы папки НЕ удалялись бы сразу же, то тогда нужно было бы как раз 30 ГБ места на ЖД. »

TROY Diamond, я это и сделал.
Цитата:

Цитата TROY Diamond
Игра в конечном итоге (в готовом к "употреблению" виде), по окончании установки, занимает на ЖД - всего 12 ГБ (условно) - я хочу задать 15 ГБ, с запасом, вместо 20-25 ГБ, сколько хочет Inno Setip из расчёта скомпилированного »

TROY Diamond, уменьшить требуемый размер 20-25 ГБ вы не сможете, величина рассчитывается в run-time и зависит от выбранных компонентов (если есть). Можно только увеличить через директиву ExtraDiskSpaceRequired. На знак "минус" в ее значении Inno ругается, отрицательное число в 16-тиричном представлении тоже не фурычит.

TROY Diamond 28-01-2019 21:12 2855079

El Sanchez и что никак не решаемо?

GrezeeBal 01-02-2019 19:32 2855790

Привет! Сразу скажу, что очень плохо разбираюсь в коде.

В общем, делаю установщик модификации для игры GTA и при установке данной игры в реестре создаётся путь к файлу gta_sa.exe(исполняемый файл). Я указываю в установщик путь к данному значению в реестр, чтобы в установщике автоматически указалась папка с игрой в качестве пути, но так как значение в реестре ведет прямо к exe файлу - он указывается в пути по умолчанию.

Вопрос: как исключить этот файл из значения, чтобы указывалась только папка с игрой?





Код:

DefaultDirName={reg:HKCU\Software\SAMP,gta_sa_exe|}

El Sanchez 01-02-2019 21:39 2855820

Цитата:

Цитата GrezeeBal
Вопрос: как исключить этот файл из значения, чтобы указывалась только папка с игрой? »

GrezeeBal,
Код:

DefaultDirName={code:ExtractFileDir|{reg:HKCU\Software\SAMP,gta_sa_exe|}}


GrezeeBal 01-02-2019 22:04 2855825

Цитата:

Цитата El Sanchez
DefaultDirName={code:ExtractFileDir|{reg:HKCU\Software\SAMP,gta_sa_exe|}} »

Спасибо большое!

OldGamer 12-02-2019 15:15 2857509

Здравствуйте!

Помогите, пожалуйста, разобраться с функцией AnimateWindow+прозрачностью окна при перемещении.

Проблема в следующем:

1) Плавное закрытие инсталлятора при выходе - работает (или работало) на отлично!

2) Добавил прозрачность окна при перемещении - работает, но плавное закрытие окна инсталлятора при нажатии на кнопку "Отмена" работать перестаёт.

Заранее Большое Спасибо!!!

Скрипт:

Код:

const
  WM_NCLBUTTONDOWN = $00A1;
  HTCAPTION = 2;
  WM_NCMOUSEMOVE = $00A0;
  GWL_EXSTYLE = -20;
  WS_EX_LAYERED = $80000;
  LWA_ALPHA = 2;
  TransparentPercent = 50;

var
  ComponentPage : TWizardPage;
  InstallGroupBox : TNewGroupBox;
  Installer    : TNewRadioButton;
  Portable      : TNewRadioButton;

function InstallerCheck: Boolean;
 begin
  Result := Installer.Checked;
 end;

function PortableCheck: Boolean;
 begin
  Result := Portable.Checked;
 end;

type TGUID          = record Data1: Cardinal; Data2, Data3: Word; Data4: array [0..8] of Char; end;

const PlayTask    = 0;
        SupportTask = 1;
var GameuxGUID: TGUID;

function GenerateGUID(var GUID: TGUID): Cardinal; external 'GenerateGUID@files:GameuxInstallHelper.dll stdcall setuponly';
function AddToGameExplorer(Binary: String; Path: String; InstallType: Integer; var GUID: TGUID): Cardinal; external 'AddToGameExplorerA@files:GameuxInstallHelper.dll stdcall setuponly';
function CreateTask(InstallType: Integer; var GUID: TGUID; TaskType: Integer; TaskNumber: Integer; TaskName: String; Binary: String; Parameters: String): Cardinal; external 'CreateTaskA@files:GameuxInstallHelper.dll stdcall setuponly';
function RetrieveGUIDForApplication(Binary: String; var GUID: TGUID): Cardinal; external 'RetrieveGUIDForApplicationA@{localappdata}\GameuxInstallHelper.dll stdcall uninstallonly';
function RemoveFromGameExplorer(var GUID: TGUID): Cardinal; external 'RemoveFromGameExplorer@{localappdata}\GameuxInstallHelper.dll stdcall uninstallonly';
function RemoveTasks(var GUID: TGUID): Cardinal; external 'RemoveTasks@{localappdata}\GameuxInstallHelper.dll stdcall uninstallonly';
procedure LoadSkin(lpszPath: String; lpszIniFileName: String); external 'LoadSkin@files:isskin.dll stdcall';
procedure UnloadSkin(); external 'UnloadSkin@files:isskin.dll stdcall';

function IntToHex(Int: Cardinal; Digits: Integer): String; var i, Digit: Integer; ch: Byte;
begin
  result:='';
  for i:=0 to Digits-1 do
    begin
    digit:=Int mod 16;
    Int:=Int div 16;
    if digit<0 then
      digit:=digit+16;
      ch:=Ord('0')+digit;
        if digit>9 then
        ch:=ch+7;
        result:=chr(ch)+result;
    end;
end;

function GetGUID(GGUID: TGUID): String; var i: Integer;
begin
  result:='{'+IntToHex(GGUID.Data1, 8)+'-'+IntToHex(GGUID.Data2, 4)+'-'+IntToHex(GGUID.Data3, 4)+'-'+IntToHex(Ord(GGUID.Data4[0]), 2)+IntToHex(Ord(GGUID.Data4[1]), 2)+'-';
  for i:=2 to 7 do result:=result+IntToHex(Ord(GGUID.Data4[i]), 2); result:=result+'}';
end;

procedure GDFInstall(Binary, MainExe: String);
begin
  GenerateGUID(GameuxGUID);
  AddToGameExplorer(ExpandConstant(Binary), ExpandConstant('{app}'), 3, GameuxGUID);

  CreateTask(3, GameuxGUID, PlayTask, 0, 'Play', ExpandConstant(MainExe), '');
end;

procedure win7fix;
  var regGDF: Cardinal;
  var GUXPath: string;
begin
GUXPath := 'Software\Microsoft\Windows\CurrentVersion\GameUX\Games\' + GetGUID(GameuxGUID);
  if isWin64 then
  begin
    if RegQueryDWordValue(HKLM64, GUXPath, 'IsSigned', regGDF) then
      if regGDF=0 then
        if RegDeleteValue(HKLM64, GUXPath, 'IsSigned') then
          RegWriteDWordValue(HKLM64, GUXPath, 'IsSigned', 1);
  end
  else
  begin
    if RegQueryDWordValue(HKLM, GUXPath, 'IsSigned', regGDF) then
      if regGDF=0 then
        if RegDeleteValue(HKLM, GUXPath, 'IsSigned') then
          RegWriteDWordValue(HKLM, GUXPath, 'IsSigned', 1);
  end;
end;

type
  TPBProc = function (h:hWnd;Msg,wParam,lParam:Longint):Longint;
 
var
  TimeLeftLabel : TLabel;

  PBOldProc    : Longint;
  eTime, sTime  : DWORD;

var
  BASS_Initialized: Boolean;

const
  AW_BLEND = $00080000;
  AW_HIDE = $00010000;
const
    LOAD_LIBRARY_AS_DATAFILE = $2;

#define A = (Defined UNICODE) ? "W" : "A"

function AnimateWindow(hWnd: HWND; dwTime: DWORD; dwFlags: DWORD): Boolean;
external 'AnimateWindow@user32 stdcall';
function LoadLibraryEx(lpFileName: String; hFile: THandle; dwFlags: DWORD): THandle; external 'LoadLibraryEx{#A}@kernel32.dll stdcall';
function LoadString(hInstance: THandle; uID: SmallInt; var lpBuffer: Char; nBufferMax: Integer): Integer; external 'LoadString{#A}@user32.dll stdcall';
function SHGetNewLinkInfo(pszLinkTo, pszDir: String; var pszName: Char; var pfMustCopy: Longint; uFlags: UINT): BOOL; external 'SHGetNewLinkInfo{#A}@shell32.dll stdcall';
function PinToTaskbar(const szFilename: String; IsPin: Boolean): Boolean;

var
    hInst: THandle;
    buf: array [0..255] of Char;
    i, res: Integer;
    strLnk, strVerb: String;
    objShell, colVerbs: Variant;
begin
    Result := False;
    if (GetWindowsVersion < $06010000) or not FileExists(szFilename) then Exit; { below Windows 7 }

    { String resources }
    if IsPin then
    begin
        if SHGetNewLinkInfo(szFilename, ExpandConstant('{tmp}'), buf[0], res, 0) then
        begin
            while buf[Length(strLnk)] <> #0 do Insert(buf[Length(strLnk)], strLnk, Length(strLnk)+1);
            if FileExists(ExpandConstant('{userappdata}\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\') + ExtractFileName(strLnk)) then Exit;
        end;
        res := 5386;        { Pin to Tas&kbar }
    end else res := 5387;  { Unpin from Tas&kbar }

    { Load string resource }
    hInst := LoadLibraryEx(ExpandConstant('{sys}\shell32.dll'), 0, LOAD_LIBRARY_AS_DATAFILE);
    if hInst <> 0 then
    try
        for i := 0 to LoadString(hInst, res, buf[0], 255)-1 do Insert(buf[i], strVerb, i+1);
        try
            objShell := CreateOleObject('Shell.Application');
            colVerbs := objShell.Namespace(ExtractFileDir(szFilename)).ParseName(ExtractFileName(szFilename)).Verbs;
            for i := 1 to colVerbs.Count do if CompareText(colVerbs.Item[i].Name, strVerb) = 0 then
            begin
                colVerbs.Item[i].DoIt;
                Result := True;
                Break;
            end;
        except
            Exit;
        end;
    finally
        FreeDLL(hInst);
    end;
end;

type
    TTimerProc = procedure(HandleW, Msg, idEvent, TimeSys: LongWord);
var
  PercentsTimer: LongWord;
  PercentsLabel: TLabel;

function GetWindowLong(hWnd: HWND; nIndex: Integer): Longint; external 'GetWindowLongA@user32.dll stdcall delayload';
function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: Longint): Longint; external 'SetWindowLongA@user32.dll stdcall';
function SetLayeredWindowAttributes(hwnd: HWND; crKey: TColor; bAlpha: BYTE; dwFlags: DWORD): Boolean; external 'SetLayeredWindowAttributes@user32.dll stdcall';
function CallBackProc(P:TPBProc;ParamCount:integer):LongWord; external 'wrapcallbackaddr@files:CallbackCtrl.dll stdcall';
function CallWindowProc(lpPrevWndFunc: Longint; hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint; external 'CallWindowProcA@user32.dll stdcall';
function GetTickCount: DWORD; external 'GetTickCount@kernel32.dll stdcall';
function WrapTimerProc(callback: TTimerProc; Paramcount: Integer): longword; external 'wrapcallback@files:innocallback.dll stdcall';
function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): longword; external 'SetTimer@user32';
function KillTimer(hWnd, nIDEvent: LongWord): LongWord; external 'KillTimer@user32 stdcall delayload';

procedure EnableTransparencyOnDrag(var Msg: TMsg; var Handled: Boolean);
begin
  if (Msg.message = WM_NCLBUTTONDOWN) and (Msg.wParam = HTCAPTION) then
  begin
    SetWindowLong(WizardForm.Handle, GWL_EXSTYLE, GetWindowLong(WizardForm.Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
    SetLayeredWindowAttributes(WizardForm.Handle, 0, (255 * TransparentPercent) / 100, LWA_ALPHA);
    Handled := False;
  end;
  if  Msg.message = WM_NCMOUSEMOVE then
  begin
    SetWindowLong(WizardForm.Handle, GWL_EXSTYLE, GetWindowLong(WizardForm.Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
    SetLayeredWindowAttributes(WizardForm.Handle, 0, 255, LWA_ALPHA);
    Handled := False;
  end;
end;

function LongintToStringTime(t:Longint):string;
var
  h,m,s:integer;
begin
  h:=t div 3600;
  t:=t-h*3600;
  m:=t div 60;
  s:=t-m*60;
  Result:='';
  if h>0 then Result:=Result+IntToStr(h)+' ÷. ';
  if (m>0) or (h>0) then Result:=Result+IntToStr(m)+' ìèí. ';
  if (m>0) or (h>0) or (s>0) then Result:=Result+IntToStr(s)+' ñåê.';
end;

function PBProc(h:hWnd;Msg,wParam,lParam:Longint):Longint;
var
  lt:Longint;
  dt,at,pr,i1,i2:Extended;
  p:string;
  tc:DWORD;
begin
  Result:=CallWindowProc(PBOldProc,h,Msg,wParam,lParam);
  if (Msg=$402) and (WizardForm.ProgressGauge.Position>WizardForm.ProgressGauge.Min) then begin
    i1:=WizardForm.ProgressGauge.Position-WizardForm.ProgressGauge.Min;
    i2:=WizardForm.ProgressGauge.Max-WizardForm.ProgressGauge.Min;

    tc:=GetTickCount;
    if (tc-eTime)>=1000 then begin //???????????? ????? ?????????? ?? ????? ????????? ?? ????, ??? ??? ? 1 ???????
      dt:=(tc-sTime)/1000;
      at:=i2*dt/i1;
      lt:=Round(at-dt)
      TimeLeftLabel.Caption:='Îñòàëîñü - '+LongintToStringTime(lt);
      eTime:=tc;
    end;

    pr:=i1*100/i2;
    p:=' - ['+Format('%f',[pr])+'%]';
    StringChange(p,',','.');
  end;
end;

procedure AllCancel;
begin
  SetWindowLong(WizardForm.ProgressGauge.Handle,-4,PBOldProc);
  TimeLeftLabel.Free;
end;

function InitializeSetup:boolean;
begin
ExtractTemporaryFile('steam.cjstyles');
  if not FileExists(ExpandConstant('{tmp}\CallbackCtrl.dll')) then ExtractTemporaryFile('CallbackCtrl.dll');
  LoadSkin(ExpandConstant('{tmp}')+'\steam.cjstyles', '');
  Result:=True;
end;

Function NumToStr(Float: Extended): String;
Begin
    Result:= Format('%.1n', [Float]); StringChange(Result, ',', '.');
    while ((Result[Length(Result)] = '0') or (Result[Length(Result)] = '.')) and (Pos('.', Result) > 0) do
        SetLength(Result, Length(Result)-1);
End;

Procedure PercentsProc(h, msg, idevent, dwTime: Longword);
Begin
  with WizardForm.ProgressGauge do
  begin
    PercentsLabel.Caption:= 'Âûïîëíåíî ' + NumToStr((Position*100)/Max) + ' %';
  end;
End;

const
  Indent=25;

function ssInitialize(hParent:HWND;ssTimeShow:integer;FadeOut:boolean;StretchMode:integer;BkgColor:DWORD):boolean; external 'ssInitialize@files:isgsg.dll stdcall delayload';
procedure ssDeInitialize; external 'ssDeInitialize@files:isgsg.dll stdcall delayload';
procedure ssSetBkgImage(FileName:PChar); external 'ssSetBkgImage@files:isgsg.dll stdcall delayload';
procedure ssAddImage(FileName:PChar); external 'ssAddImage@files:isgsg.dll stdcall delayload';
procedure ssStartShow; external 'ssStartShow@files:isgsg.dll stdcall delayload';
procedure ssStopShow; external 'ssStopShow@files:isgsg.dll stdcall delayload';
procedure ShowSplashScreen(p1:HWND;p2:string;p3,p4,p5,p6,p7:integer;p8:boolean;p9:Cardinal;p10:integer); external 'ShowSplashScreen@files:isgsg.dll stdcall delayload';
function GetSystemMetrics(nIndex:Integer):integer; external 'GetSystemMetrics@user32.dll stdcall delayload';

procedure RunListClickCheck(Sender: TObject);
var
  i:integer;
begin
  if WizardForm.RunList.Checked[WizardForm.RunList.ItemIndex] then begin
    for i:=0 to WizardForm.RunList.Items.Count-1 do
      WizardForm.RunList.Checked[i]:=False;
    WizardForm.RunList.Checked[WizardForm.RunList.ItemIndex]:=True;
  end;
end;

procedure InitializeWizard();
begin
Application.OnMessage:=@EnableTransparencyOnDrag;
begin
  ComponentPage := CreateCustomPage(wpInfoBefore, 'Âûáîð âåðñèè èãðû', 'Ïîæàëóéñòà, ñäåëàéòå âûáîð ïåðåä òåì, êàê ïðîäîëæèòü.');

  { InstallGroupBox }
InstallGroupBox := TNewGroupBox.Create(WizardForm);
with InstallGroupBox do
begin
Parent := ComponentPage.Surface;
SetBounds(ScaleX(0),ScaleY(0),ScaleX(63),ScaleY(70));
Caption := 'Version:';
end;

  { Installer }
  Installer := TNewRadioButton.Create(WizardForm);
  with Installer do
  begin
    Parent := ComponentPage.Surface;
    SetBounds(ScaleX(9),ScaleY(19),ScaleX(45),ScaleY(17));
    Caption := '32-bit';
  end;

  { Portable }
  Portable := TNewRadioButton.Create(WizardForm);
  with Portable do
  begin
    Parent := ComponentPage.Surface;
    SetBounds(ScaleX(9),ScaleY(43),ScaleX(45),ScaleY(17));
    Caption := '64-bit';
    Checked := True;
end;
begin
  ExtractTemporaryFile('Bass.dll');
  ExtractTemporaryFile('botva2.dll');
  ExtractTemporaryFile('volmax.png');
  ExtractTemporaryFile('volmin.png');
  ExtractTemporaryFile('volpb.png');
  ExtractTemporaryFile('voldote.png');
  ExtractTemporaryFile('Music.mp3');
  ExtractTemporaryFile('MusicButton.png');
  ExtractTemporaryFile('EG.png');
 
  ShowSplashScreen(WizardForm.Handle,ExpandConstant('{tmp}')+'\EG.png',5000,4000,3000,0,255,False,$FFFFFF,10);
  ssInitialize(GetWindowLong(MainForm.Handle,-8),18,True,2,$FF000000);

  WizardForm.RunList.OnClickCheck:=@RunListClickCheck;
  BASS_Init('{tmp}\Music.mp3')
  BASS_CreateMediaPlayer(WizardForm, '{tmp}\volmax.png', '{tmp}\volmin.png', '{tmp}\volpb.png', '{tmp}\voldote.png', 20, 325)
  BASS_Initialized := True;
  ExtractTemporaryFile('0.png');
  ssSetBkgImage(ExpandConstant('{tmp}')+'\0.png');
  WizardForm.TypesCombo.ItemIndex:=0;
 
  PercentsLabel:= TLabel.Create(WizardForm);
  with PercentsLabel do
  begin
    Left:= WizardForm.ProgressGauge.Left;
    Top:= WizardForm.ProgressGauge.Top + WizardForm.ProgressGauge.Height + ScaleY(10);
    Width:= WizardForm.StatusLabel.Width;
    Height:= WizardForm.StatusLabel.Height;
    AutoSize:= False;
    Transparent := True;
    Parent:= WizardForm.InstallingPage;
  end;
end;
end;
end;

procedure CurStepChanged(CurStep: TSetupStep);
var Version: TWindowsVersion;
begin
  GetWindowsVersionEx(Version);
  if (CurStep = ssPostInstall) and Version.NTPlatform and (Version.Major > 5) then begin
    GDFInstall('{#GDFBinary}', '{#GDFExe}');
      win7fix;
  end;
begin
  case CurStep of
    ssInstall: begin
      TimeLeftLabel:=TLabel.Create(nil);
      with TimeLeftLabel do begin
        Parent:=WizardForm.InstallingPage;
        AutoSize:=True;
        SetBounds(WizardForm.ProgressGauge.Left + ScaleX(250),WizardForm.ProgressGauge.Top + ScaleY(30),ScaleY(80),ScaleY(21));
      end;
sTime:=GetTickCount;
      eTime:=sTime;

      PBOldProc:=SetWindowLong(WizardForm.ProgressGauge.Handle,-4,CallBackProc(@PBProc,4));
    end;
    ssPostInstall: AllCancel;
  end;
begin
  if CurStep=ssInstall then begin
    ExtractTemporaryFile('1.png');
    ssAddImage(ExpandConstant('{tmp}')+'\1.png');
    ExtractTemporaryFile('2.png');
    ssAddImage(ExpandConstant('{tmp}')+'\2.png');
    ExtractTemporaryFile('3.png');
    ssAddImage(ExpandConstant('{tmp}')+'\3.png');
    ExtractTemporaryFile('4.png');
    ssAddImage(ExpandConstant('{tmp}')+'\4.png');
    ExtractTemporaryFile('5.png');
    ssAddImage(ExpandConstant('{tmp}')+'\5.png');
    ExtractTemporaryFile('6.png');
    ssAddImage(ExpandConstant('{tmp}')+'\6.png');
    ExtractTemporaryFile('7.png');
    ssAddImage(ExpandConstant('{tmp}')+'\7.png');;
    ExtractTemporaryFile('8.png');
    ssAddImage(ExpandConstant('{tmp}')+'\8.png');
    ExtractTemporaryFile('9.png');
    ssAddImage(ExpandConstant('{tmp}')+'\9.png');
    ExtractTemporaryFile('10.png');
    ssAddImage(ExpandConstant('{tmp}')+'\10.png');
PercentsTimer:= SetTimer(0, 0, 100, WrapTimerProc(@PercentsProc, 4));
    ExtractTemporaryFile('0.png');
    ssAddImage(ExpandConstant('{tmp}')+'\0.png');
    ssStartShow;
  end;
  if CurStep=ssPostInstall then ssStopShow;
end;
end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
case CurPageID of
    wpFinished: end
  if IsTaskSelected('Pin') then
        PinToTaskbar(ExpandConstant('{app}\Eternal Darkness-Sanitys Requiem.exe'), True);
  if CurPageID=wpInstalling then begin;
    WizardForm.MainPanel.Visible:=False;
    WizardForm.Bevel1.Visible:=False;
    WizardForm.Width:=ScaleX(395);
    WizardForm.Height:=ScaleY(142);
    WizardForm.Left:=ScaleX(GetSystemMetrics(0)-WizardForm.Width-Indent);
    WizardForm.Top:=ScaleY(GetSystemMetrics(1)-WizardForm.Height-Indent);
    WizardForm.InnerNotebook.Left:=ScaleX(10);
    WizardForm.InnerNotebook.Top:=ScaleY(10);
    WizardForm.InnerNotebook.Width:=ScaleX(370);
    WizardForm.StatusLabel.Left:=ScaleX(0);
    WizardForm.StatusLabel.Top:=ScaleY(0);
    WizardForm.StatusLabel.Width:=WizardForm.InnerNotebook.Width;
    WizardForm.FileNameLabel.Left:=ScaleX(0);
    WizardForm.FileNameLabel.Top:=ScaleY(20);
    WizardForm.FileNameLabel.Width:=WizardForm.InnerNotebook.Width;
    WizardForm.ProgressGauge.Top:=ScaleY(40);
    WizardForm.ProgressGauge.Width:=WizardForm.InnerNotebook.Width;
    WizardForm.CancelButton.Left:=ScaleX(154);
    WizardForm.CancelButton.Top:=ScaleY(80);
  end;
  if (CurPageID=wpFinished) or (CurPageID=wpInfoAfter) then begin
    WizardForm.RunList.Checked[0]:=True;
    if WizardForm.Width<>502 then begin
      WizardForm.Visible:=False;
      WizardForm.Width:=ScaleX(502);
      WizardForm.Height:=ScaleY(392);
      WizardForm.Left:=(GetSystemMetrics(0)-WizardForm.Width) div 2;
      WizardForm.Top:=(GetSystemMetrics(1)-WizardForm.Height) div 2;
      WizardForm.MainPanel.Visible:=True;
      WizardForm.Bevel1.Visible:=True;
      WizardForm.InnerNotebook.Left:=ScaleX(40);
      WizardForm.InnerNotebook.Top:=ScaleY(72);
      WizardForm.InnerNotebook.Width:=ScaleX(417);
      WizardForm.Visible:=True;
    end;
  end;
end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  Result := True;
  if CurPageID=wpFinished then
  begin
    if WizardForm.RunList.Checked[0] then
    Result := True;
  end;
end;

procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
  if MsgBox(SetupMessage(msgExitSetupMessage), mbConfirmation, MB_OKCANCEL) = IDOK then
  begin
    Confirm := False;
    AnimateWindow(WizardForm.Handle, 2500, AW_BLEND or AW_HIDE);
    Cancel := True;
  end else
  Cancel := False;
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
Binary: String;
GUID: TGUID;
begin
if CurUninstallStep=usUninstall then
begin
Binary:=ExpandConstant('{#GDFBinary}');
RetrieveGUIDForApplication(Binary, GUID);
RemoveFromGameExplorer(GUID);
RemoveTasks(GUID);
UnloadDll(ExpandConstant('{localappdata}\GameuxInstallHelper.dll'));
end;
  begin
    if (CurUninstallStep=usUninstall) then
      begin
    case CurUninstallStep of
      usUninstall: begin
        PinToTaskbar(ExpandConstant('{app}\Eternal Darkness-Sanitys Requiem.exe'), False);
      end;
  end;
end;
end;
end;

procedure DeinitializeSetup();
begin
if BASS_Initialized then
begin
KillTimer(0, PercentsTimer);
UnloadSkin();
  ssDeInitialize;
  BASS_DeInit;
    gdipShutdown
end;
end;


pollipen 19-02-2019 09:10 2858715

парни подскажите, как сделать что бы после установки в тихом режиме с ключом (/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-) программа не запускалась?
потому что там стоит галачка
Скрытый текст

El Sanchez 19-02-2019 09:51 2858722

Цитата:

Цитата pollipen
как сделать что бы после установки в тихом режиме с ключом (/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-) программа не запускалась?
потому что там стоит галачка »

pollipen, в скрипте флаг skipifsilent выставлен, запускаться не должна.

pollipen 19-02-2019 10:20 2858732

нет всё равно запуск идёт программы

mariolast 24-02-2019 22:57 2859741

Есть пример скрипта для обработки своих параметров при установке через /silent?
Скажем /1 задает одни умолчальные параметры чекбоксов, /2 другие.
Давно уже не занимался Inno

FiRmaN 01-03-2019 19:07 2860739

Всем привет. Кто может помочь, как снять обводку с кнопок. В скриптинге нуб:)

Вот архив с скриптом. http://rgho.st/6hwhMlbnC

Iska 01-03-2019 19:31 2860749

FiRmaN, значит, пора учиться.

FiRmaN 01-03-2019 20:06 2860756

Цитата:

Цитата Iska
FiRmaN, значит, пора учиться. »

Есть материал где можно прочесть как убрать эту обводку?

Nordek 02-03-2019 11:36 2860864

Цитата:

Цитата FiRmaN
как убрать эту обводку? »

Пример:
Код:

[Code]
procedure InitializeWizard();
begin
  WizardForm.NextButton.Default := False;
end;

А также (Вдруг тоже приспичит):
Код:

[Code]
procedure InitializeWizard();
begin
  WizardForm.GroupEdit.AutoSelect := False;
  WizardForm.NextButton.AutoSelect := False;
end;

Дальше сами.

habib2302 03-03-2019 21:01 2861093

Доброе время суток. Нужно, чтобы при выборе или отмене компонента и задачи добавлялась или удалялась часть команды из секции run?
Например: При выборе задачи "Создать ярлык на РС" добавлялась команда SHORTCUT_DESKTOP=1.

Код:

[Run]
Filename: msiexec.exe; Parameters: "/I Setup.msi /qf ALL_USERS=1 SHORTCUT_DESKTOP=1 INSTALLDIR=""{app}"""; Check: not WizardSilent; Flags: waituntilterminated hidewizard;


Iska 03-03-2019 22:33 2861108

habib2302, нет, нельзя. Файл инсталляции формируется в момент его создания. Работайте с набором задач, для которых будут разные параметры у исполняемой команды, либо работайте непосредственно в коде.

P.S. Я надеюсь, Ваша инсталляция не состоит только из одного этого файла?

habib2302 03-03-2019 22:46 2861113

Цитата:

Цитата Iska
либо работайте непосредственно в коде »

В принципе я надеялся на помощь т.к я в коде не силен. (Если есть возможность сделать код)
Цитата:

Цитата Iska
P.S. Я надеюсь, Ваша инсталляция не состоит только из одного этого файла? »

Нет

boss911 04-03-2019 02:00 2861134

Цитата:

Цитата habib2302
Например: При выборе задачи "Создать ярлык на РС" добавлялась команда SHORTCUT_DESKTOP=1. »

Код:

[Tasks]
Name: DesktopIcon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked

[Run]
Filename: {sys}\msiexec.exe; Parameters: "/I Setup.msi /qf ALL_USERS=1 SHORTCUT_DESKTOP=1 INSTALLDIR=""{app}"""; Check: not WizardSilent; Flags: waituntilterminated hidewizard; Tasks: DesktopIcon
Filename: {sys}\msiexec.exe; Parameters: "/I Setup.msi /qf ALL_USERS=1 INSTALLDIR=""{app}"""; Check: not WizardSilent; Flags: waituntilterminated hidewizard; Tasks: not DesktopIcon

В зависимости от выбора или не выбора задачи (по умолчанию не выбрано, флаг 'unchecked'), будет выполняться только один из указанных запусков (по умолчанию без параметра 'SHORTCUT_DESKTOP=1'). С компонентом можно сделать аналогично.

habib2302 04-03-2019 02:15 2861139

boss911, помимо ярлыков на рс есть 4 компонента и ярлык в пуск

Iska 04-03-2019 04:09 2861143

Начинают выясняться интересные подробности…
Цитата:

Цитата habib2302
boss911, помимо ярлыков на рс есть 4 компонента и ярлык в пуск »

habib2302, о которых мы, конечно, должны были догадаться? Вы написали конкретный пример «например» — Вам дали на него конкретный ответ. Хотите чего-то сложного с кучей условий и зависимостей — изучайте и берите в руки PascalScript.

habib2302 04-03-2019 04:30 2861145

Iska, уже сделал. посредством записи команд в ini файл через секцию [Ini] и чтение из ini файла через код

OldGamer 05-03-2019 22:39 2861608

Вложений: 1
Ребята, подскажите пожалуйста, как можно изменить стандартное окно с выбором языков установки?
Чтобы было похоже на то, что во вложении.

usermode 08-03-2019 20:36 2862170

помогите забороть странный колбек:

Скрытый текст

[Setup]
AppName=DeltaMAX
AppVerName=DeltaMAX 2.0.1.0
DefaultDirName={tmp}
OutputDir=c:\Files\

[code]
type
EnumCallback=procedure(retcode: integer;lpUser:Longint);

function WrapMyCallback(callback:EnumCallback; paramcount:integer):longword;
external 'wrapcallback@{sd}\Files\innocallback.dll stdcall';

type
DELTAMAX_ENCODE_OPTIONS = record
lpszLicensedTo: ansistring;
lpszLicenseKey: ansistring;
nMemoryMax: Integer;
nMemoryMaxPercent: Integer;
nFreeMemoryMin: Integer;
nLowMemMode: Integer;
nFootprintSize: Integer;
bAutoIncreaseFootprintSize: bool;
bEnableMultiPass: bool;
nMultiPassThreshold: Integer;
nMultiPassMaxAdditionalPasses: Integer;
pProgressCallback: longword;
lpUserData: integer;
end;

procedure DeltaMAXInitEncodeOptions(pOptions: DELTAMAX_ENCODE_OPTIONS);
external 'DeltaMAXInitEncodeOptions@{sd}\Files\DeltaMAX.dll cdecl';

function DeltaMAXEncode(szSource: ansistring; szTarget: ansistring; szDiff: ansistring; pOptions: DELTAMAX_ENCODE_OPTIONS): Integer;
external 'DeltaMAXEncode@{sd}\Files\DeltaMAX.dll cdecl';

procedure ProcessDiff(code: integer; lpUser:Longint);
begin
MsgBox('data', mbError, MB_OK);
end;

var
Data: PAnsiChar;
Options: DELTAMAX_ENCODE_OPTIONS;
callback:longword;
userdata:ansistring;

function initializesetup():boolean;
var
err: Integer;
n,s: ansistring;
begin
callback:=WrapMyCallback(@ProcessDiff,2);

n := 'DEMO';
s := 'DEMO';

DeltaMAXInitEncodeOptions(Options);

Options.lpszLicensedTo := n;
Options.lpszLicenseKey := s;
Options.nMemoryMax := 0;
Options.nMemoryMaxPercent := 80;
Options.nFreeMemoryMin := 8;
Options.nLowMemMode := 1;
Options.nFootprintSize := 0;
Options.bAutoIncreaseFootprintSize := true;
Options.bEnableMultiPass := false;
Options.nMultiPassThreshold := 0;
Options.nMultiPassMaxAdditionalPasses := 1;

//Options.lpUserData := 0;
//Options.pProgressCallback := callback;

err := DeltaMAXEncode('D:\1.txt', 'D:\2.txt', 'D:\patch.diff', Options);

if err <> 0 then
MsgBox('Bad! ' + IntToStr(err), mbError, MB_OK) else
MsgBox('Success! ' + IntToStr(err), mbError, MB_OK);
end;


сам sdk в аттаче. нужно, чтобы в структуре параметр pProgressCallback корректно исполнял колбек для обсчета процентов согласно документации SDK. полагаю, у меня ошибка в данных lpUserData, я не знаю какой указатель и куда должен быть использован.

для использования надо из папки SDK\Redist скопировать ANSI версию DeltaMAX.dll в C:\Files, туда же InnoCallback.dll.
также нужно поместить 1.txt и 2.txt с различающимися данными. D:\patch.diff - сюда будут записаны файл с изменениями.
из соображений копирайтов, серийный номер не прикладываю, нужно будет подождать пять секунд и нажать OK для запуска процесса.

El Sanchez 10-03-2019 12:17 2862348

Цитата:

Цитата usermode
помогите забороть странный колбек »

usermode,
Скрытый текст

Код:

[Setup]
AppName=DeltaMAX
AppVerName=DeltaMAX 2.0.1.0
DefaultDirName={tmp}
OutputDir=.

[Files]
Source: {#ifdef UNICODE}Unicode\{#endif}DeltaMAX.dll; Flags: dontcopy;
Source: InnoCallback.dll; Flags: dontcopy

[Code]
type
  TMessageCallback = function(nMessageCode: Integer; lpUserData: LongWord): BOOL;
  TProgressCallback = function(dPercentDone: Single; lpUserData: LongWord): BOOL;

  TDeltaMAXEncodeOptions = record
    lpszLicensedTo: string;
    lpszLicenseKey: string;
    nMemoryMax: Integer;
    nMemoryMaxPercent: Integer;
    nFreeMemoryMin: Integer;
    nLowMemMode: Integer;
    nFootprintSize: Integer;
    bAutoIncreaseFootprintSize: BOOL;
    bEnableMultiPass: BOOL;
    nMultiPassThreshold: Integer;
    nMultiPassMaxAdditionalPasses: Integer;
    pProgressCallback: LongWord;
    pMessageCallback: LongWord;
    lpUserData: LongWord;
  end;

function WrapMessageCallback(Callback: TMessageCallback; ParamCount: Integer): LongWord; external 'wrapcallback@files:innocallback.dll stdcall';
function WrapProgressCallback(Callback: TProgressCallback; ParamCount: Integer): LongWord; external 'wrapcallback@files:innocallback.dll stdcall';
procedure DeltaMAXInitEncodeOptions(var pOptions: TDeltaMAXEncodeOptions); external 'DeltaMAXInitEncodeOptions@files:DeltaMAX.dll cdecl';
function DeltaMAXEncode(szSource, szTarget, szDiff: string; var pOptions: TDeltaMAXEncodeOptions): Integer; external 'DeltaMAXEncode@files:DeltaMAX.dll cdecl';

function ProgressCallback(dPercentDone: Single; lpUserData: LongWord): BOOL;
begin
  Result := True;
  Log(Format('Progress: %n%%', [dPercentDone]));
end;

function MessageCallback(nMessageCode: Integer; lpUserData: LongWord): BOOL;
begin
  Result := True;
  Log(Format('Message code: %d', [nMessageCode]));
end;

function InitializeSetup: Boolean;
var
  LOptions: TDeltaMAXEncodeOptions;
  LResultCode: Integer;
begin
  try
    DeltaMAXInitEncodeOptions(LOptions);
    LOptions.lpszLicensedTo := 'DEMO';
    LOptions.lpszLicenseKey := 'DEMO';
    LOptions.bEnableMultiPass := False;
    LOptions.nMultiPassThreshold := 0;
    LOptions.nMultiPassMaxAdditionalPasses := 1;
    LOptions.pProgressCallback := WrapProgressCallback(@ProgressCallback, 2);
    LOptions.pMessageCallback := WrapMessageCallback(@MessageCallback, 2);
    LResultCode := DeltaMAXEncode(ExpandConstant('{src}\1.txt'), ExpandConstant('{src}\2.txt'), ExpandConstant('{src}\patch.diff'), LOptions);
    if LResultCode <> 0 then
      RaiseException(Format('Encode failed with error code: %d', [LResultCode]));
  except
    ShowExceptionMessage;
  finally
  end;


usermode 10-03-2019 15:02 2862366

El Sanchez, благодарю! :victory:

Давно не кодил и ошибка основная у меня была в том, что я полностью не описал структуру, почему то решил, что можно некоторые параметры не описывать и оставить себе только нужные - а так делать нельзя, такое можно только в коде функции. К тому же не выполнил главного условия True функции колбека, без которого это дело тоже не заведется. Также прошляпил var в прототипах, хотя использовал почему-то out и работало..

Вопрос у меня следующий, проценты выполнения привязаны только к прогресс бару? Вообще я хотел бы адаптировать под консольное приложение на дельфи и мне там было бы неплохо прогресс выполнения привязать к строке, отображающей проценты в числовом виде. Пока не могу придумать как описать проценты от 0 до 100 в ProgressCallback, ибо даже если вручную указать min 0, max 100, step 1, то общее количество вызовов в колбеке мы не знаем, их может быть 250, 400 и т.д.

по идее в dPercentDone должно лежать число максимального цикла колбека, чтобы выполнить обсчет процентов? может быть потому что другой тип данных Single, а не Double? а с Double работать не хочет. надо будет с дельфи повозиться, посмотреть как там дела будут обстоять с Double.

добавлено
вобщем, проблема решена на дельфи:
Скрытый текст
function DiffProgressCallback(nn:double; lpUserData:pointer): bool; stdcall;
begin
Application.ProcessMessages;
Form1.edt1.Text := IntToStr(round(nn));
Form1.pb1.position:=round(nn);
Result:=True;
end;

double нормально отрабатывает, только сначала не понял, почему по третьему кругу прогресс бар и проценты идут. оказалось, так надо :) разные этапы так разделяются.

я проверил код на Inno и на Delphi, что-то типа:
ppos:=0;
...
в колбеке:
inc(ppos);
и считаем проценты по ppos, минусуя 100 процентов при превышении интервала.
сравнив выполнение с double на дельфи и там же рядом inc кода на Inno - абсолютно одинаково считает, единственное на Inno надо учитывать "переполнение" счетчика процентов, когда идет вторая и третяя стадия выполнения. извращаться с Single в данном случае не обязательно :)

El Sanchez 10-03-2019 19:18 2862405

Цитата:

Цитата usermode
Также прошляпил var в прототипах, хотя использовал почему-то out и работало.. »

usermode, в данном случае без разницы.
Цитата:

Цитата usermode
Вопрос у меня следующий, проценты выполнения привязаны только к прогресс бару? »

usermode, прогресс там привязан к разным операциям в течении сессии. Запустите Bin\MFC60Client.exe и увидите, что прогресс там несколько раз полностью доходит до конца, общего нет.
Цитата:

Цитата usermode
по идее в dPercentDone должно лежать число максимального цикла колбека, чтобы выполнить обсчет процентов? может быть потому что другой тип данных Single, а не Double? а с Double работать не хочет. надо будет с дельфи повозиться, посмотреть как там дела будут обстоять с Double. »

usermode, нормально в Delphi должно быть, это в PascalScript флоаты дурные. Single я поставил, потому что с другими типами ошибки, с ним же без ошибок, но проценты не считает :).

usermode 10-03-2019 19:46 2862408

El Sanchez, да, я это уловил и отредактировал предыдущее сообщение, вопрос полностью решен, спасибо еще раз!

там кстати на количество проходов влияют параметры:

LOptions.bEnableMultiPass := true;
LOptions.nMultiPassThreshold := 0;
LOptions.nMultiPassMaxAdditionalPasses := 3;

если мультипроходы отключены или выставлены в 1, то только один раз до 100 процентов выполняется. а на образце по дефолту 3 прохода выставляется, поэтому чуть не запутался с этим, думал глюки снова :)

mdli 28-03-2019 19:51 2865618

Подскажите каким способом можно скрыть кнопку Inno Setup из панели задач ? Окно я скрываю, а кнопка остается и показывает прогресс распаковки, мне это не нужно.
SetWindowLong пробовал, не помогает.

Iska 29-03-2019 04:05 2865711

Цитата:

Цитата mdli
каким способом можно скрыть кнопку Inno Setup из панели задач ? »

Зачем?

El Sanchez 31-03-2019 10:24 2866062

Цитата:

Цитата mdli
Подскажите каким способом можно скрыть кнопку Inno Setup из панели задач ? »

mdli,
Код:

#ifndef IS_ENHANCED
const
  GW_OWNER = 4;

function GetWindow(hWnd: HWND; uCmd: UINT): HWND; external 'GetWindow@user32.dll stdcall';
#endif
function ShowWindow(hWnd: Integer; uType: Integer): Integer; external 'ShowWindow@user32.dll stdcall';

procedure FormActivate(Sender: TObject);
begin
  ShowWindow({#ifdef IS_ENHANCED}Application.Handle{#else}GetWindow(MainForm.Handle, GW_OWNER){#endif}, SW_HIDE);
end;

procedure InitializeWizard;
begin
  WizardForm.OnActivate := @FormActivate;
end;


SBalykov 01-04-2019 15:05 2866203

Вложений: 1
Добрый день!
Помогите решить проблему сохранения файлов SlideShow в память и последующей их воспроизведения из памяти:
Код:

#ifndef IS_ENHANCED
#error Для компиляции данного скрипта необходимо расширенное издание Inno Setup (restools)!
#endif

#define SLIDE "4"

[Setup]
AppName=My Application
AppVersion=1.5
DefaultDirName={sd}\My Application

[Files]
Source: Sourse\*; Flags: dontcopy

[_Code]
type
#ifdef UNICODE
  PChar = PAnsiChar;
#else
  AnsiChar = Char;
#endif

var
i: Integer;

function ssInitialize(hParent: HWND; ssTimeShow: Integer; FadeOut: Boolean; StretchMode: Integer; BkgColor: DWORD): Boolean; external 'ssInitialize@{tmp}\isgsg.dll stdcall delayload';
procedure ssAddImage(FileName: PChar); external 'ssAddImage@files:isgsg.dll stdcall delayload';
procedure ssDeInitialize; external 'ssDeInitialize@files:isgsg.dll stdcall delayload';
procedure ssStartShow; external 'ssStartShow@files:isgsg.dll stdcall delayload';
procedure ssStopShow; external 'ssStopShow@files:isgsg.dll stdcall delayload';

{* Запуск отображения слайдшоу *}
function InitializeSlideShow: Boolean;
begin
  ExtractTemporaryFile('isgsg.dll');
  Result := ssInitialize(WizardForm.Handle, 2, True, 0, 0);
for i := 1 to {#SLIDE} do begin
  ExtractTemporaryFile(IntToStr(i)+'.jpg');
  ssAddImage(ExpandConstant('{tmp}\'+IntToStr(i)+'.jpg'));
  end;
  Sleep(5);
  ssStartShow;
end;

procedure InitializeWizard();
begin
  InitializeSlideShow;
end;

procedure DeinitializeSetup();
begin
  ssStopShow;
  ssDeInitialize;
end;


El Sanchez 01-04-2019 21:05 2866233

Цитата:

Цитата SBalykov
Помогите решить проблему сохранения файлов SlideShow в память и последующей их воспроизведения из памяти »

SBalykov, а пущай для начала автор библиотеки реализует ssAddImage с загрузкой из TStream.

SBalykov 02-04-2019 02:40 2866264

El Sanchez
Понял.
Спасибо за ответ...

ErikPshat 10-04-2019 08:34 2867260

Здравствуйте! Есть ли способ извлечения файлов из инсталлятора во время запуска не в папку {tmp)?
Предположим в секции [Files] помещаю файл:
Код:

[Files]
Source: "Include\utility.exe"; DestDir: "{tmp}"; Flags: dontcopy

Затем, при запуске инсталлятора я извлекаю этот файл во временную директорию как обычно такой командой:
Код:

ExtractTemporaryFile('utility.exe');
Но, если мне нужно извлекать не в {tmp}, а допустим, в папку "С:\Tools\utility.exe", тогда это просто так не получится? Что-то пробовал менять путь, выдаёт ошибку.

Пока ничего не приходит в голову, как копировать файл из временной папки, типа так:
Код:

ExtractTemporaryFile('utility.exe');
FileCopy(ExpandConstant('{tmp}\utility.exe'), ExpandConstant('С:\Tools\utility.exe'), True);


Irenis 10-04-2019 17:40 2867318

Добрый день. Подскажите пожалуйста, как сделать так, чтоб при установке приложения, на рабочем столе создавался ярлык со ссылкой, которую можно открыть через указанный браузер?
Например, чтоб сайт yandex.ru открывался через Explorer, нужно создать на рабочем столе такой ярлык
«C:\Program Files\Internet Explorer\iexplore.exe» //yandex.ru

Можно ли в inno setyp сделать подобное, чтоб создавался ярлык со ссылкой, которая открывалась бы через указанный браузер?

usermode 10-04-2019 17:58 2867324

ErikPshat, а с помощью ExtractTemporaryFiles(s) никак это не сделаешь. Если посмотреть исходники, то там код для этих функций работает только в пределах временной папки.
Так что способ копирования вполне себе, только не забудь перед копированием файла создать нужные папки, если они не существуют, например: ForceDirectories(ExpandConstant('{sd}\Tools'))

Iska 10-04-2019 18:23 2867334

Цитата:

Цитата usermode
там код для этих функций работает только в пределах временной папки. »

И это правильно.

Irenis 10-04-2019 20:12 2867347

Цитата:

Цитата Irenis
Например, чтоб сайт yandex.ru открывался через Explorer, нужно создать на рабочем столе такой ярлык
«C:\Program Files\Internet Explorer\iexplore.exe» //yandex.ru

Можно ли в inno setyp сделать подобное, чтоб создавался ярлык со ссылкой, которая открывалась бы через указанный браузер? »

Ну или как то по другому. Например, запакую я браузер хромиум (или любой другой браузер) через inno setyp, затем нужно, чтоб после установки этого браузера на другом компьютере и последующего запуска, открывалась не домашняя страница браузера, а та сслыка, которую я указала. Возможно ли так сделать? Подскажите, плиз.

ErikPshat 10-04-2019 21:25 2867357

Цитата:

Цитата usermode
только не забудь перед копированием файла создать нужные папки, если они не существуют, например: ForceDirectories(ExpandConstant('{sd}\Tools')) »

Ага, это я понял, т.к., если папки не существует, тогда копирование файлов само не создаёт папки.
Правда я создаю папку такой командой: CreateDir(ExpandConstant('{src}\Tools'));

Цитата:

Цитата Iska
И это правильно. »

Странно, почему-бы не сделать извлечение из экзешника по указанному пути. Тут такое дело и просто уже надоело бороться со школьниками, которые создают на компе профиль на кириллице. Получается путь к папке %TEMP% по умолчанию в таком виде: C:\Users\Вася Пупкин\AppData\Local\Temp
А используемая конфиденциальная утилита, от именитого производителя Sony, не понимает кириллицу и аналогов не имеет.
Так вот такие юзеры постоянно жалуются, типа нифига не работает ваша прога. И это довольно частая проблема. Надоело каждый день по 10 раз объяснять, что не надо называть комп и имя профиля, создавать почтовые ящики, исполььзовать пароли - на кириллице.

ErikPshat 10-04-2019 22:41 2867369

Цитата:

Цитата Irenis
Ну или как то по другому. Например, запакую я браузер хромиум (или любой другой браузер) через inno setyp, затем нужно, чтоб после установки этого браузера на другом компьютере и последующего запуска, открывалась не домашняя страница браузера, а та сслыка, которую я указала. Возможно ли так сделать? Подскажите, плиз. »

А с каким умыслом устанавливать на комп юзера свой браузер? Дкмаю никому не понравится, если у него на компе вдруг появится Internet Explorer или Opera, либо мазила, и зачем-то именно в этом стороннем браузере будет открываться ссылка.

Выводите просто ярлык интернета на рабрчий стол. А при его запуске, будет у юзера открываться его браузер, выставленный у него по умолчанию. Воспользуйтесь официальной функцией Inno Setup по созданию ярлыков. Укажите секцию [Icons] и выводите URL-ярлык, например так:
Код:

[Icons]
Name: "{commondesktop}\Открыть в Яндекс"; Filename: "https://yandex.ru"


Dodakaedr 10-04-2019 22:42 2867370

Цитата:

Цитата Irenis
Например, чтоб сайт yandex.ru открывался через Explorer, нужно создать на рабочем столе такой ярлык »

Цитата:

Цитата Irenis
Ну или как то по другому. »

Как вариант

Код:

[Setup]
AppName=App
AppverName=App v1.0
DefaultDirName={pf}\App
OutputDir=.

// 1 вариант
[ini]
Filename: "{userdesktop}\HomePageWeb.url"; Section: "InternetShortcut"; Key: "URL"; String: "https://yandex.ru";

// 2 вариант
[icons]
Name: "{userdesktop}\HomePageWeb2"; Filename: """C:\Program Files\Internet Explorer\iexplore.exe"""; Parameters: "//yandex.ru";


Цитата:

Цитата ErikPshat
Есть ли способ извлечения файлов из инсталлятора во время запуска не в папку {tmp)? »

Есть такой (расширенная версия inno setup):
Скрытый текст
Код:

[Setup]
AppName=App
AppverName=App v1.0
DefaultDirName={pf}\App
OutputDir=.

[Files]
Source: "Include\utility.exe"; DestDir: "{tmp}"; Flags: dontcopy

[Code]
function InitializeSetup(): Boolean;
begin
  Result := True;
  CreateDir(ExpandConstant('{src}\Tools'));
  ExtractTemporaryFileEx('utility.exe', ExpandConstant('{src}\Tools'));
end;


Iska 11-04-2019 03:36 2867393

Цитата:

Цитата ErikPshat
Тут такое дело и просто уже надоело бороться со школьниками, которые создают на компе профиль на кириллице. Получается путь к папке %TEMP% по умолчанию в таком виде: C:\Users\Вася Пупкин\AppData\Local\Temp
А используемая конфиденциальная утилита, от именитого производителя Sony, не понимает кириллицу и аналогов не имеет. »

Так здесь проблема с программистами, которые в XXI веке продолжают считать, что в мире не существует никакого иного языка, кроме английского.

Irenis 11-04-2019 11:31 2867417

Цитата:

Цитата Dodakaedr
Как вариант »

Спасибо, вариант 2 очень помог. А нельзя немного сложнее сделать, чтоб при первом запуске ярлыка открывалась одна ссылка, а при всех последующих запусках другая? Например, создался ярлык на рабочем столе, при первом запуске он самоудалился и вместо него появился другой ярлык, с таким же названием, но уже с другой ссылкой. И при этом сохранялось бы условие запуска этих ярлыков через тот браузер, который я указала.

Dodakaedr 11-04-2019 15:47 2867444

Irenis, Только если через планировщик. Но вообще такое не рекомендуется.

alexander-mex 18-04-2019 08:32 2868200

Всем привет! На работе дали задание сделать сборник инсталляторов. Этим я никогда не занимался. Есть 2 основные программы и 2 файла которые устанавливают службы (ярлыки). Можно ли сделать с помощью этой программы сборник, чтобы открывалось окно и я мог выбрать, что хочу установить?

usermode 18-04-2019 10:47 2868224

Цитата:

Цитата alexander-mex
Можно ли сделать с помощью этой программы сборник, чтобы открывалось окно и я мог выбрать, что хочу установить? »

Имеется в виду оболочку как в старых добрых авторанах на дисках? В Inno можно, но лучше в "гуевых" программах типа AutoPlay Menu Builder или AutoPlay Media Studio.

alexander-mex 18-04-2019 15:09 2868257

Спасибо! Попробую

ZVSRus 18-04-2019 16:06 2868264

Цитата:

Цитата alexander-mex
Можно ли сделать с помощью этой программы сборник, чтобы открывалось окно и я мог выбрать, что хочу установить?

Сделано на Inno Setup

Сделано на Inno Setup

ROMKA-1977 27-04-2019 01:04 2869368

Здраствуйте. Подскажите пож. константу папки Сохраненные игры (C:\Users\XXX\Saved Games). В справке такой нет.

habib2302 27-04-2019 01:39 2869371

ROMKA-1977, как вариант
Код:

{sd}\Users\{username}\Saved Games

или

Код:

[Code]
  if RegValueExists(HKEY_CURRENT_USER, 'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders', '{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}') then
  begin
   
// The value exists
 
end;
end;

или

Код:

{reg:HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders,%7B{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}}

{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4} = это путь к папке в случае если пользователь изменит путь через свойства. Проверил от 7 и до 10. Везде один и тот же {4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}

habib2302 27-04-2019 14:07 2869410

ROMKA-1977, или же
%USERPROFILE%\Saved Games

ErikPshat 27-04-2019 19:43 2869435

Цитата:

Цитата Iska
Так здесь проблема с программистами, которые в XXI веке продолжают считать, что в мире не существует никакого иного языка, кроме английского. »

Ага, тут в продолжение разговора, я всё-таки решил использовать эту злополучную утилиту, которая не понимает в путях не только символы кириллицы, но и другие нестандартные символы, отличные от букв и цифр ANSI алфавита: [A-z0-9]. Вообщем мне удалось соорудить проверку на символы кириллицы и оно прекрасно работает.
IsAnsi
Наверху кода создаю такую функцию:
Код:

function IsAnsi(S: String): Boolean; var S1, S2: string;
begin S1 := AnsiUppercase(S); S2 := Uppercase(S); if CompareStr(S1, S2) = 0 then
  begin S1 := Lowercase(S); S2 := AnsiLowercase(S); if CompareStr(S1, S2) = 0 then
    Result := True;
  end;
end;

А потом, там где я хочу произвести проверку, вставляю код проверки символов в пути к папке программы и при обнаружении вывожу предупреждение с завершением работы:
Код:

if not (IsAnsi(ExpandConstant('{src}'))) then
  begin MsgBox(ExpandConstant('{cm:CirillicPATH}')+#10#10+ExpandConstant('{src}'),mbError,MB_OK);
  Exit;
end;

Но теперь я хочу дополнить проверку и на нестандартные символы, типа !, "@, #, $, %, ^, &, *,...
В инете нашёл такую интересную процедуру определения символов по их номерам и даже по диапазонам номеров в десятичном виде:
Код:

procedure justNumbers(Sender: TObject; var Key: Char);
begin
  if not ((Key = #8) or (Key = #43) or ((Key >= #48) and (Key <= #57))) then
  begin
    Key := #0;
  end;
end;

Но вот что-то никак ума не приложу, как бы мне теперь объединить эти две конструкции, чтобы и символы кириллицы анализировала, и нестандартные символы определяла?
Либо отказаться от первой функции и сделать определение символов по их номерам?
Чую собака неглубоко зарыта, но что-то у меня пока не получается никак.

usermode 28-04-2019 22:54 2869538

Для одного из проектов искал самый быстрый подсчет crc32 для файлов и решил сделать dll, кому интересно забирайте в аттаче.
подробнее...
Алгоритм работает так: если поддержку SSE 4.2 процессор имеет, срабатывает аппаратный подсчет crc32c (с - использование Intel полинома: $1EDC6F41), в противном случае, если процессор слишком старый и не имеет поддержку SSE 4.2, то срабатывает crc32cfast с оптимизацией на ассемблере (имеет тот же результат подсчета). отличие результата подсчета от стандартного crc32 только из-за использования другого инициализационного полинома.

По заверению авторов кода, результаты подсчета следующие:
- Our optimized unrolled x86 version - aka crc32cfast() - performs the test at a very good pace of 1.7 GB/s;
- SSE 4.2 version - aka crc32csse42() - gives an amazing 3.7 GB/s speed (on both Win32 and Win64 platforms);
- simple rolled version of the algorithm (similar to the one in Delphi zlib unit) runs at 330 MB/s.

Основано на:
https://synopse.info/fossil/info/8fe7cc53b7

ErikPshat 29-04-2019 09:01 2869560

usermode, ещё одна DLL конечно никогда не помешает. Только в наши времена подсчёт CRC32 имеет актуальность на маленьких файлах, пускай даже самый быстрый подсчёт CRC32. По крайней мере даже MD5 быстрее подсчитывается стандартной функцией препроцессора GetMD5OfFile, не говоря уже про более точный SHA-1 и более быстрый подсчёт больших файлов по 1-4-10-20 Гига стандартной функцией препроцессора GetSHA1OfFile. Может быть я ошибаюсь, вашу утилиту не пробовал, но на практике часто приходится подсчитывать файлы по 4 и более Гб, так вот, какой бы быстрый не был бы CRC32, так это можно уснуть надолго, тогда как SHA-1 обычно замечено мною, что на несколько махов быстрее подсчитывается :)

Кстати, стоит мне изменить путь s:='D:\somebigfile.dat'; или подсунуть по этому пути реальный файл, как прога тут же выдаёт ошибку:



Ну а мне никто так и не поможет?

usermode 29-04-2019 11:32 2869572

ErikPshat, у меня dll на всех ОС, включая Windows 10, работает нормально. Может причина в "неуниверсальных" параметрах выделения или освобождения памяти.
Можно попросить протестировать "болванку" на дельфи? Нужно прописать путь к существующему файлу, нажать каждую кнопку и сообщить, на каких будут ошибки. Заодно сравните на гигабайтных файлах скорость подсчета сравнительно md5 и sha-1 (предпочтительно на ssd при наличии) и убедитесь в обратном :)
У меня на ssd подсчитывает фильм 2.22 Gb стандартной системной реализацией за 4.8sec, sse4.2 за 0.8sec, fast assembler за 1.2 sec.

Цитата:

Ну а мне никто так и не поможет?
когда-то давно писал такой "дурацкий" код на проверку символов, которые указаны в abc, все остальные несуществующие символы будут отсчитывать ошибку.
Скрытый текст
Код:

procedure InitializeWizard;     
var
  i,j: integer;   
  s,abc: string;                                             
begin
  j  := 0;
  abc := '0123456789абв%*@abc';

  s:='012';

  for i:=1 to Length(s) do
  begin
    if Pos(s[i],abc) = 0 then
    inc(j);
  end;

  if j >= 1 then
  begin
    MsgBox('Error! 0123456789абв%*@abc chars only are allowed!', mbInformation, MB_OK);
    Exit;
  end;
end;


лучше учесть те символы, что можно, чем учитывать все, что нельзя.

add
причина ошибки dll в некорректном определении технологии SSE 4.2, там где ее нет, например на CPU с SSE 4.1, она определяется что есть.

ErikPshat 29-04-2019 14:26 2869582

Цитата:

Цитата usermode
причина ошибки dll в некорректном определении технологии SSE 4.2, там где ее нет, например на CPU с SSE 4.1, она определяется что есть. »

Ну вот, значит нужно над совместимостью поработать ;)



За код спасибо, правда я видел подобные варианты, но видимо это самый универсальный вариант, правда я хотел бы взять диапазон через Key: Char по нумерации в таблице ASCII-символов.

usermode 29-04-2019 15:01 2869586

Вложений: 1
CRC32-C Ansi/Unicode Dlls *fixed*
Пришлось исправлять косяки разработчиков, плохо работало определение наличия технологии SSE 4.2 (кто ж мог подумать :) )
в оригинале:
test edx,$100000 // перепутали регистр, по которому берется информация для SSE 4.2
setz al // неправильная установка флага
исправленный:
test ecx,$100000 // fix
setne al // fix

фикс основан на интеловских доках, где достаточно сделать проверку только на поддержку SSE 4.2:
https://software.intel.com/en-us/art...struction-sets

ErikPshat 29-04-2019 17:24 2869611

usermode, окей, теперь работает. Но так не честно. Чтобы быть объективным, тогда уж надо подсчитать время и потом сравнивать посекундно, какая функция ведёт подсчёт быстрее. Вот так я подсчитал время перед стартом подсчёта контрольной суммы и после, заодно можно сравить по времени подсчёт MD5 и SHA-1 того же файла:
Скрипт
Код:

;InnoSetupVersion=5.6.1 (Unicode)
#define CP = (Defined UNICODE) ? "unicode" : "ansi"

[Setup]
AppName=test
AppVerName=test
OutputDir=...
OutputBaseFilename=HachCheck
CreateAppDir=no
Uninstallable=no
CreateUninstallRegKey=no

[Files]
Source: crc32c_{#CP}.dll; Flags: dontcopy;

[*Code*]
function GetCRC32COfFile(FilePath: String): Cardinal;
external 'GetCRC32COfFile@files:crc32c_{#CP}.dll stdcall';

procedure InitializeWizard;
var
  md5, sha1, t1, t2, t3, t4, t5, t6, f1, FileName: string;
  crc: cardinal;
begin
  if GetOpenFileName(ExpandConstant('Выберите файл'),FileName,ExpandConstant('{src}'),ExpandConstant('Выбрать любой файл ')+'(*.*)|*.*','*') then
    if MsgBox(ExpandConstant('Выбран файл')+#10#10+FileName+#10#10+ExpandConstant('Подсчитать контрольную сумму файла "'+ExtractFileName(FileName)+'" ?'), mbInformation, MB_YESNO) = IDYES then
  begin
  if FileExists(FileName) then
    begin
      t1:=GetDateTimeString('hh:nn:ss', '-', ':');
      crc:=GetCRC32COfFile(FileName);
      t2:=GetDateTimeString('hh:nn:ss', '-', ':');
      f1:=Format('%.8x',[crc]);
      MsgBox(ExpandConstant('Старт вычисления:  '+t1)+#10+#10+ExpandConstant('Хэш сумма CRC32:  '+f1)+#10#10+ExpandConstant('Конец вычисления:  '+t2), mbInformation, MB_OK);
    end;
    begin
      t3:=GetDateTimeString('hh:nn:ss', '-', ':');
      md5:=GetMD5OfFile(FileName);
      t4:=GetDateTimeString('hh:nn:ss', '-', ':');
      MsgBox(ExpandConstant('Старт вычисления:  '+t3)+#10+#10+ExpandConstant('Хэш сумма MD5:  '+md5)+#10#10+ExpandConstant('Конец вычисления:  '+t4), mbInformation, MB_OK);
    end;
    begin
      t5:=GetDateTimeString('hh:nn:ss', '-', ':');
      sha1:=GetSHA1OfFile(FileName);
      t6:=GetDateTimeString('hh:nn:ss', '-', ':');
      MsgBox(ExpandConstant('Старт вычисления:  '+t5)+#10+#10+ExpandConstant('Хэш сумма SHA-1:  '+sha1)+#10#10+ExpandConstant('Конец вычисления:  '+t6), mbInformation, MB_OK);
    end;
    MsgBox(ExpandConstant('CRC32 :'+#10#10+'Старт вычисления:  '+t1)+#10+#10+ExpandConstant('Конец вычисления:  '+t2)+#10+#10+#10+
          ExpandConstant('MD5  :'+#10#10+'Старт вычисления:  '+t3)+#10+#10+ExpandConstant('Конец вычисления:  '+t4)+#10+#10+#10+
          ExpandConstant('SHA-1 :'+#10#10+'Старт вычисления:  '+t5)+#10+#10+ExpandConstant('Конец вычисления:  '+t6), mbInformation, MB_OK);
  end;
end;


Лучше видно будет на больших файлах, где-то 2-4 Гб, чем больше - тем очевиднее. Вот тогда можно и рассудить.
Вот пример вычисления чек-сумм файла 3,80 ГБ:

  • CRC32: 01 мин 32 сек
  • M D 5 : 00 мин 39 сек
  • SHA-1 : 01 мин 52 сек
MD5 у меня всегда почему-то быстрее всего подсчитывает.

Dodakaedr 29-04-2019 19:58 2869619

Цитата:

Цитата ErikPshat
Но вот что-то никак ума не приложу, как бы мне теперь объединить эти две конструкции, чтобы и символы кириллицы анализировала, и нестандартные символы определяла? »

Такой вариант сойдет?
Скрытый текст
Код:

function IsAnsiOrSym(S: String): Boolean;
var
  n: string;
  i,j: integer;
begin
  if CompareStr(AnsiUppercase(S), Uppercase(S)) = 0 then
  if CompareStr(Lowercase(S), AnsiLowercase(S)) = 0 then Result := True;
  if result then
  begin
    n := '!"@#$%^&*';
    for i:=1 to length(s) do
    for j:=1 to length(n) do
    begin
      if s[i] = n[j] then
      begin
        Result := False;
        exit;
      end;
    end;
    end;
end;


usermode 30-04-2019 01:16 2869665

ErikPshat, а у меня такие результаты на ssd на файле в 2.22Gb:
Скрытый текст
Код:

#define CP = (Defined UNICODE) ? "unicode" : "ansi" 

[Setup]
AppName=test
AppVerName=test
DefaultDirName={tmp}
CreateAppDir=no
Uninstallable=no
CreateUninstallRegKey=no
                                           
[Files]
Source: crc32c_{#CP}.dll; Flags: dontcopy;                             
                                                             
[.Code]                                                         
function GetCRC32COfFile(FilePath: String): Cardinal;                   
external 'GetCRC32COfFile@files:crc32c_{#CP}.dll stdcall';
                   
function GetTickCount: Dword;
external 'GetTickCount@kernel32.dll stdcall'; 
   
function FormatTime(time: int64): string;
 var
  Ms : Int64;
  H, M, S : Integer;
begin
  Ms := time;
  H := Ms div (60 * 60 * 1000);
  Ms := Ms mod (60 * 60 * 1000);
  M := Ms div (60 * 1000);
  Ms := Ms mod (60 * 1000);
  S := Ms div 1000;
  Ms := Ms mod 1000;
  Result := Format('%.2dh:%.2dm:%.2ds:%.3dms',[H,M,S,Ms]);
end; 
                                                     
///////////////////////////                                                   
procedure InitializeWizard;     
var
  s: string; 
  c: cardinal; 
  Elapsed,Start,Stop:int64;                                               
begin
  s:='C:\44.txt';
  if FileExists (s) then
  begin
    Elapsed := 0;
    Start:=GetTickCount;
    c:=GetCRC32COfFile(s);
    Stop:=GetTickCount;
    Elapsed:=Stop-Start;
    MsgBox(Format('%.8x',[c])+' Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
    /////////////
    Elapsed := 0;
    Start:=GetTickCount;
    s:=GetMD5OfFile(s);
    Stop:=GetTickCount;
    Elapsed:=Stop-Start;
    MsgBox(s+' Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
  end;
end;


C5433036 Time: 00h:00m:00s:842ms
---------------------------
9e7592826a085607311cd0a38f17ef19 Time: 00h:00m:04s:602ms

p.s. там еще может быть момент "первого чтения". когда доступ к диску замедлен, либо тот же диск интенсивно задействован прриложениями, тогда изначально может показаться что CRC32 "тормозит", но на самом деле оно всяко быстрее md5, по крайней мере на моем Core i7 процессоре.

ErikPshat 30-04-2019 02:48 2869667

Цитата:

Цитата Dodakaedr
Такой вариант сойдет? »

О, да! Думаю, самый оптимальный и самый хитрый и короткий вариант. Как раз то, что надо. Я ещё отдельно выставил 2 разные переменные в первой и второй проверке и вывожу 2 разных сообщения: по поводу символов кириллицы и по поводу нестандартных символов. То есть, теперь распознавание получается более точнее, нежели одно общее. Спасибо ещё раз!!!

Цитата:

Цитата usermode
C5433036 Time: 00h:00m:00s:842ms
---------------------------
9e7592826a085607311cd0a38f17ef19 Time: 00h:00m:04s:602ms »

Видимо у вас процессор использует инструкции процессора SSE 4.2 и код DLL просто заточен и оптимизирован под эти инструкции, вот и получается у вас подсчёт CRC32 быстрее, т.к. инструкции MD5 не оптимизированы.
А у меня, как я ранее выкладывал скриншот своего процессора на нетбуке Asus Eee PC 1215N Intel Atom D525, то у него SSE3 максимум, поэтому MD5 вычисляется намного быстрее. Вот результаты на файле 3,77 ГБ:Так что, ваш код DLL получается только для избранных выигрышный. Может быть его как-то оптимизировать под SSE3?

usermode 30-04-2019 11:06 2869698

Цитата:

Цитата ErikPshat
Может быть его как-то оптимизировать под SSE3? »

только начиная с SSE 4.2 есть аппаратная инструкция crc32. в dll используется самый оптимизированный подсчет на ассемблере даже без SSE 4.2, не знаю в чем магия, утверждать и спорить не буду, но в очередной раз предположу: скорость чтения с ноутбучного hdd, до 110-120 мегабайт в секунду, ssd до 550 mb/s. По заявлениям разработчиков на современных Intel процессорах скорость подсчета алгоритма crc32cfast - 1.7 Gb/s, crc32csse42 - 3.5 Gb/s. Такого чтения не может обеспечить любой адекватный носитель.

А попробуйте еще виндовый апишный подсчет crc32, будет ли он у вас быстрее, чем подсчет в dll (у меня виндовый подсчет медленнее в 10 раз):
Скрытый текст
Код:

#define CP = (Defined UNICODE) ? "unicode" : "ansi" 
#define AW = (Defined UNICODE) ? "W" : "A" 
[Setup]
AppName=test
AppVerName=test
DefaultDirName={tmp}
CreateAppDir=no
Uninstallable=no
CreateUninstallRegKey=no
                                           
[Files]
Source: crc32c_{#CP}.dll; Flags: dontcopy;                             
                                                             
[.Code] 
type
  TMyMsg = record hWnd: HWND; msg, wParam: Word; lParam: LongWord; Time: TFileTime; pt: TPoint; end;
                                                         
function GetCRC32COfFile(FilePath: String): Cardinal;                   
external 'GetCRC32COfFile@files:crc32c_{#CP}.dll stdcall';
                   
function GetTickCount: Dword;
external 'GetTickCount@kernel32.dll stdcall'; 
   
function RtlComputeCrc32(dwInitial: Cardinal; const pData: Longint; iLen: Integer): Cardinal;
external 'RtlComputeCrc32@ntdll.dll stdcall';

function ReadFile(hFile: THandle; lpBuffer: Longint; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: Longint): BOOL;
external 'ReadFile@kernel32.dll stdcall';

function GetProcessHeap: THandle;
external 'GetProcessHeap@kernel32.dll stdcall';

function HeapAlloc(hHeap: THandle; dwFlags, dwBytes: DWORD): Longint;
external 'HeapAlloc@kernel32.dll stdcall';

function HeapSize(hHeap: THandle; dwFlags: DWORD; lpMem: Longint): DWORD;
external 'HeapSize@kernel32.dll stdcall';

function HeapFree(hHeap: THandle; dwFlags: DWORD; lpMem: Longint): BOOL;
external 'HeapFree@kernel32.dll stdcall';

function PeekMessage(var lpMsg: TMyMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL;
external 'PeekMessage{#AW}@user32.dll stdcall';

function TranslateMessage(const lpMsg: TMyMsg): BOOL;
external 'TranslateMessage@user32.dll stdcall';

function DispatchMessage(const lpMsg: TMyMsg): Longint;
external 'DispatchMessage{#AW}@user32.dll stdcall';

function CreateFile(lpFileName: String; dwDesiredAccess: DWORD; dwShareMode: DWORD; lpSecurityAttributes: DWORD; dwCreationDisposition: DWORD; dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle;
external 'CreateFile{#AW}@kernel32.dll stdcall';

function CloseHandle(hObject: THandle): BOOL;
external 'CloseHandle@kernel32.dll stdcall';

const
  PAGE_READONLY = $0002;
  FILE_MAP_READ = $0004;
  HEAP_ZERO_MEMORY = $0008;
  FILE_FLAG_SEQUENTIAL_SCAN = $08000000;

  GENERIC_READ        = $80000000;
  GENERIC_WRITE      = $40000000;
  GENERIC_EXECUTE    = $20000000;
  GENERIC_ALL        = $10000000;
  FILE_SHARE_READ    = 1;
  FILE_SHARE_WRITE    = 2;
  FILE_SHARE_DELETE  = 4;
  CREATE_NEW          = 1;
  CREATE_ALWAYS      = 2;
  OPEN_EXISTING      = 3;
  OPEN_ALWAYS        = 4;
  TRUNCATE_EXISTING  = 5;

  INVALID_HANDLE_VALUE = (-1);

procedure AppProcessMessage;
var
  Msg: TMyMsg;
begin
  while PeekMessage(Msg, 0, 0, 0, 1) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
end;

function GetCRC32OfFile(FileName: string): Cardinal;
var
  hFile, hHeap: THandle;
  lpBuffer: Longint;
  dwBufferSize, dwRead: DWORD;                         
begin
  Result := 0;
  hFile := CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
  if hFile = INVALID_HANDLE_VALUE then Exit;
  try
    hHeap := GetProcessHeap;
    if hHeap = 0 then Exit;
    lpBuffer := HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 32*1024);
    if lpBuffer = 0 then Exit;
    dwBufferSize := HeapSize(hHeap, 0, lpBuffer);
    if dwBufferSize = 0 then Exit;
    while ReadFile(hFile, lpBuffer, dwBufferSize, dwRead, 0) and BOOL(dwRead > 0) do
    begin
      AppProcessMessage; 
      Result := RtlComputeCrc32(Result, lpBuffer, dwRead);
    end;
  finally
    if hHeap <> 0 then
      HeapFree(hHeap, 0, lpBuffer);
    CloseHandle(hFile);
  end;
end;

function FormatTime(time: cardinal{int64}): string;
 var
  Ms : cardinal{int64};
  H, M, S : Integer;
begin
  Ms := time;
  H := Ms div (60 * 60 * 1000);
  Ms := Ms mod (60 * 60 * 1000);
  M := Ms div (60 * 1000);
  Ms := Ms mod (60 * 1000);
  S := Ms div 1000;
  Ms := Ms mod 1000;
  Result := Format('%.2dh:%.2dm:%.2ds:%.3dms',[H,M,S,Ms]);
end; 
                                                     
///////////////////////////                                                   
procedure InitializeWizard;     
var
  s: string; 
  c: cardinal; 
  Elapsed,Start,Stop:cardinal{int64};                                               
begin
  s:='C:\44.txt';
  if FileExists (s) then
  begin
    Elapsed := 0;
    Start:=GetTickCount;
    c:=GetCRC32OfFile(s);
    Stop:=GetTickCount;
    Elapsed:=Stop-Start;
    MsgBox(Format('%.8x',[c])+' Api CRC32 Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
    /////////////
    Elapsed := 0;
    Start:=GetTickCount;
    c:=GetCRC32COfFile(s);
    Stop:=GetTickCount;
    Elapsed:=Stop-Start;
    MsgBox(Format('%.8x',[c])+' Fast CRC-32C Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
    /////////////
    Elapsed := 0;
    Start:=GetTickCount;
    s:=GetMD5OfFile(s);
    Stop:=GetTickCount;
    Elapsed:=Stop-Start;
    MsgBox(s+' Inno MD5 Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
  end;
end;



В интернетах должна быть реализация md5 под sse2, хотя некоторые разработчики для своих брутилок тоже делали на ассемблере очень быстрые алгоритмы :)

ErikPshat 30-04-2019 11:53 2869727

Цитата:

Цитата usermode
А попробуйте еще виндовый апишный подсчет crc32, будет ли он у вас быстрее, чем подсчет в dll (у меня виндовый подсчет медленнее в 10 раз) »

Ну на файле 3,8 Гб
  • API: 01:53:085
  • Fast CRC-32C: 00:07:801
  • MD5: 00:15:787
Пару раз прогонял, результаты почти практически такие же. Fast CRC-32C конечно намного быстрее считает, только почему-то CRC разные показывает :)

Цитата:

Цитата Dodakaedr
if s[i] = n[j] then »

Эмм, что-то у меня это равенство ни при каких условиях не выполняется, хоть есть нестандартные символы, хоть нет.

usermode 30-04-2019 12:05 2869728

Цитата:

Цитата ErikPshat
Fast CRC-32C конечно намного быстрее считает »

полагаю, что проблема замедленного подсчета , это первичный доступ чтения, чтобы убедиться, переместите в скрипте код подсчета md5 на первое место - будет ли средний результат в тех же 15 секунд.

Цитата:

Цитата ErikPshat
только почему-то CRC разные показывает »

это потому, что в CRC-32C используется другой Intel-овский полином (приставка С намекает), но сам алгоритм абсолютно идентичный.

ErikPshat 30-04-2019 12:30 2869735

usermode, переместил MD5 на первое место, то же самое: 00:15:678
А вот API CRC32: 00:00:015 - как так возможно? :)
А Fast CRC-32C: 00:00:000 :)
В общем, на первом результате происходит долгое ожидание, такое впечатление, что файл просто сначала кэшируется во временную память, ну и на раскрутку цилиндров видимо тратится время. А второй и третий результат выдаётся практически тут же.

usermode 30-04-2019 12:49 2869738

Цитата:

Цитата ErikPshat
А вот API CRC32: 00:00:015 - как так возможно?
А Fast CRC-32C: 00:00:000 »

сказывается 3 день Пасхи :) не назначил отдельную переменную для имени файла, и s потом вместо файла указывало на посчитанную ранее md5 сумму.
Скрытый текст
Код:

#define CP = (Defined UNICODE) ? "unicode" : "ansi" 
#define AW = (Defined UNICODE) ? "W" : "A" 
[Setup]
AppName=test
AppVerName=test
DefaultDirName={tmp}
CreateAppDir=no
Uninstallable=no
CreateUninstallRegKey=no
                                           
[Files]
Source: crc32c_{#CP}.dll; Flags: dontcopy;                             
                                                             
[.Code] 
type
  TMyMsg = record hWnd: HWND; msg, wParam: Word; lParam: LongWord; Time: TFileTime; pt: TPoint; end;
                                                         
function GetCRC32COfFile(FilePath: String): Cardinal;                   
external 'GetCRC32COfFile@files:crc32c_{#CP}.dll stdcall';
                   
function GetTickCount: Dword;
external 'GetTickCount@kernel32.dll stdcall'; 
   
function RtlComputeCrc32(dwInitial: Cardinal; const pData: Longint; iLen: Integer): Cardinal;
external 'RtlComputeCrc32@ntdll.dll stdcall';

function ReadFile(hFile: THandle; lpBuffer: Longint; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: Longint): BOOL;
external 'ReadFile@kernel32.dll stdcall';

function GetProcessHeap: THandle;
external 'GetProcessHeap@kernel32.dll stdcall';

function HeapAlloc(hHeap: THandle; dwFlags, dwBytes: DWORD): Longint;
external 'HeapAlloc@kernel32.dll stdcall';

function HeapSize(hHeap: THandle; dwFlags: DWORD; lpMem: Longint): DWORD;
external 'HeapSize@kernel32.dll stdcall';

function HeapFree(hHeap: THandle; dwFlags: DWORD; lpMem: Longint): BOOL;
external 'HeapFree@kernel32.dll stdcall';

function PeekMessage(var lpMsg: TMyMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL;
external 'PeekMessage{#AW}@user32.dll stdcall';

function TranslateMessage(const lpMsg: TMyMsg): BOOL;
external 'TranslateMessage@user32.dll stdcall';

function DispatchMessage(const lpMsg: TMyMsg): Longint;
external 'DispatchMessage{#AW}@user32.dll stdcall';

function CreateFile(lpFileName: String; dwDesiredAccess: DWORD; dwShareMode: DWORD; lpSecurityAttributes: DWORD; dwCreationDisposition: DWORD; dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle;
external 'CreateFile{#AW}@kernel32.dll stdcall';

function CloseHandle(hObject: THandle): BOOL;
external 'CloseHandle@kernel32.dll stdcall';

const
  PAGE_READONLY = $0002;
  FILE_MAP_READ = $0004;
  HEAP_ZERO_MEMORY = $0008;
  FILE_FLAG_SEQUENTIAL_SCAN = $08000000;

  GENERIC_READ        = $80000000;
  GENERIC_WRITE      = $40000000;
  GENERIC_EXECUTE    = $20000000;
  GENERIC_ALL        = $10000000;
  FILE_SHARE_READ    = 1;
  FILE_SHARE_WRITE    = 2;
  FILE_SHARE_DELETE  = 4;
  CREATE_NEW          = 1;
  CREATE_ALWAYS      = 2;
  OPEN_EXISTING      = 3;
  OPEN_ALWAYS        = 4;
  TRUNCATE_EXISTING  = 5;

  INVALID_HANDLE_VALUE = (-1);

procedure AppProcessMessage;
var
  Msg: TMyMsg;
begin
  while PeekMessage(Msg, 0, 0, 0, 1) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
end;

function GetCRC32OfFile(FileName: string): Cardinal;
var
  hFile, hHeap: THandle;
  lpBuffer: Longint;
  dwBufferSize, dwRead: DWORD;                         
begin
  Result := 0;
  hFile := CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
  if hFile = INVALID_HANDLE_VALUE then Exit;
  try
    hHeap := GetProcessHeap;
    if hHeap = 0 then Exit;
    lpBuffer := HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 32*1024);
    if lpBuffer = 0 then Exit;
    dwBufferSize := HeapSize(hHeap, 0, lpBuffer);
    if dwBufferSize = 0 then Exit;
    while ReadFile(hFile, lpBuffer, dwBufferSize, dwRead, 0) and BOOL(dwRead > 0) do
    begin
      AppProcessMessage; 
      Result := RtlComputeCrc32(Result, lpBuffer, dwRead);
    end;
  finally
    if hHeap <> 0 then
      HeapFree(hHeap, 0, lpBuffer);
    CloseHandle(hFile);
  end;
end;

function FormatTime(time: int64): string;
 var
  Ms : int64;
  H, M, S : Integer;
begin
  Ms := time;
  H := Ms div (60 * 60 * 1000);
  Ms := Ms mod (60 * 60 * 1000);
  M := Ms div (60 * 1000);
  Ms := Ms mod (60 * 1000);
  S := Ms div 1000;
  Ms := Ms mod 1000;
  Result := Format('%.2dh:%.2dm:%.2ds:%.3dms',[H,M,S,Ms]);
end; 
                                                     
///////////////////////////                                                   
procedure InitializeWizard;     
var
  s,fs: string; 
  c: cardinal; 
  Elapsed,Start,Stop:int64;                                               
begin
  fs:='C:\44.txt';
  if FileExists (fs) then
  begin
    Elapsed := 0;
    Start:=GetTickCount;
    s:=GetMD5OfFile(fs);
    Stop:=GetTickCount;
    Elapsed:=Stop-Start;
    MsgBox(s+' Inno MD5 Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
    /////////////
    Elapsed := 0;
    Start:=GetTickCount;
    c:=GetCRC32OfFile(fs);
    Stop:=GetTickCount;
    Elapsed:=Stop-Start;
    MsgBox(Format('%.8x',[c])+' Api CRC32 Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
    /////////////
    Elapsed := 0;
    Start:=GetTickCount;
    c:=GetCRC32COfFile(fs);
    Stop:=GetTickCount;
    Elapsed:=Stop-Start;
    MsgBox(Format('%.8x',[c])+' Fast CRC-32C Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
  end;
end;


ErikPshat,
http://qaru.site/questions/332124/crc32-vs-crc32c

Dodakaedr 30-04-2019 18:46 2869785

Цитата:

Цитата ErikPshat
Эмм, что-то у меня это равенство ни при каких условиях не выполняется, хоть есть нестандартные символы, хоть нет. »

На какой символ проверяете?
Цитата:

Цитата ErikPshat
Я ещё отдельно выставил 2 разные переменные в первой и второй проверке »

они не могли испортить функцию?
Попробуйте еще так:
Скрытый текст
Код:

[Setup]
AppName=App
AppverName=App v1.0
DefaultDirName={pf}\App
OutputDir=.

[Code]
var
  errorcode: integer;

function IsAnsiOrSym(S: String; var ResultError: integer): Boolean;
var
  n: string;
  i,j: integer;
begin
  if CompareStr(AnsiUppercase(S), Uppercase(S)) = 0 then
  if CompareStr(Lowercase(S), AnsiLowercase(S)) = 0 then Result := True else Result := False;
  if not result then ResultError := 1;
  if result then
  begin
    n := '!"@#$%^&*';
    for i:=1 to length(s) do
    for j:=1 to length(n) do
    begin
      if s[i] = n[j] then
      begin
        Result := False;
        ResultError := 2;
        exit;
      end;
    end;
    end;
end;

procedure InitializeWizard();
begin
  if not (IsAnsiOrSym(ExpandConstant('{src}'), errorcode)) then if (errorcode=1) then MsgBox('Найдена кириллица в: '+ExpandConstant('{src}'),mbError,MB_OK);
  if not (IsAnsiOrSym(ExpandConstant('{src}'), errorcode)) then if (errorcode=2) then MsgBox('Найден спецсимвол в: '+ExpandConstant('{src}'),mbError,MB_OK);
end;


ErikPshat 30-04-2019 20:50 2869800

Цитата:

Цитата Dodakaedr
На какой символ проверяете?
они не могли испортить функцию? »

Вполне может быть я что-то не так подхимичил. Вроде бы по логике всё так же должно было остаться.
Я разделил ту функцию на 2 отдельные функции. Ну там переменную "n" поменял на "m", т.к. первая у меня уже используется в коде.
Вот моя химия:
Код:

function IsAnsi(S: String): Boolean;
begin if CompareStr(AnsiUppercase(S), Uppercase(S)) = 0 then
begin if CompareStr(Lowercase(S), AnsiLowercase(S)) = 0 then Result := True; end; end;

function IsSymb(S: String): Boolean; var m: String; i, j: Integer;
begin
  m := '!"@#$%^&*';
  for i:=1 to length(S) do
  for j:=1 to length(m) do
  begin if S[i] = m[j] then Result := False; end;
end;

procedure InitializeWizard();
if not(IsAnsi(ExpandConstant('{src}'))) then begin MsgBox(ExpandConstant('{cm:CirillicPATH}')+#10#10+ExpandConstant('{src}'), mbError, MB_OK);Exit;end;
if not(IsSymb(ExpandConstant('{src}'))) then begin MsgBox(ExpandConstant('{cm:SimbolsPATH}')+#10#10+ExpandConstant('{src}'), mbError, MB_OK);Exit;end;


Проверил ваш код. Всё отлично работает! Из функции exit; перенёс в исполняемый код, т.к. мне нужно, чтобы после оповещения, окно закрывалось и прекращало работу.
Спасибо большое!!!

vk_k14m@vk 08-06-2019 20:28 2874898

Народ, у меня вопрос по секции [UninstallDelete]. При удалении приложения нужно так же удалять конфиг приложения. Но можно ли сделать, что б уинсталлер просил подтверждение при удалении?

Dodakaedr 08-06-2019 21:58 2874904

Цитата:

Цитата vk_k14m@vk
можно ли сделать, что б уинсталлер просил подтверждение при удалении? »

Код:

[Setup]
AppName=App
AppverName=App v1.0
DefaultDirName={pf}\App
OutputDir=.

[Code]
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usPostUninstall then
    if MsgBox('Также удалить настройки программы?', mbConfirmation, MB_YESNO)=IDYES then DeleteFile(ExpandConstant('{commonappdata}\Proga\config.cfg'));
end;


Iska 08-06-2019 22:56 2874915

Dodakaedr, лучше бы вопрос задавался в самом начале процесса деинсталляции, а не в конце (если я правильно понял логику кода).

vk_k14m@vk 08-06-2019 23:30 2874919

Цитата:

Цитата Iska
лучше бы вопрос задавался в самом начале процесса деинсталляции, а не в конце (если я правильно понял логику кода). »

Мне нужно что б удалилось само приложение, и в конце деинсталлер уточнял, удалять ли и конфиг тоже. Или оставить...

И наверно нужно было уточнять, что конфиг не один а несколько. И достоверно известна только папка в которой они находятся, но не их названия...

Изменил код на как мне казалось рабочий вариант.
[code]
Код:

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usPostUninstall then
    if MsgBox('Также удалить настройки программы?', mbConfirmation, MB_YESNO)=IDYES then DelTree('{app}\config', True, True, True);
end;

Но нет. Установщик спросил удалять или нет, и при согласии файлы остались на месте. Что я сделал не так?

Dodakaedr 08-06-2019 23:49 2874922

Цитата:

Цитата vk_k14m@vk
И наверно нужно было уточнять, что конфиг не один а несколько »

Уточняйте все и сразу: какого рода ваши конфиги, маска файлов подойдет?

Цитата:

Цитата Iska
лучше бы вопрос задавался в самом начале процесса деинсталляции »

Если пользователь удаляет прогу, то ему, я думаю, все равно где задавать вопрос.

И судя по ответу
Цитата:

Цитата vk_k14m@vk
Мне нужно что б удалилось само приложение, и в конце деинсталлер уточнял »

я предоставил пример что требовалось. И сейчас будем пол страницы узнавать подробности конфигов.

Iska 09-06-2019 00:46 2874926

Цитата:

Цитата Dodakaedr
Если пользователь удаляет прогу, то ему, я думаю, все равно где задавать вопрос. »

Сугубо с точки зрения эргономики — в начале, ибо в противном случае на мелких (по количеству файлов) инсталляциях навряд ли время под процесс основной деинсталляции будет особо продолжительным, а вот на крупных — данная пауза будет заметно раздражать.

Цитата:

Цитата Dodakaedr
И судя по ответу я предоставил пример что требовалось. И сейчас будем пол страницы узнавать подробности конфигов. »

Ну, это как обычно ;).

vk_k14m@vk 09-06-2019 00:51 2874927

Цитата:

Цитата Dodakaedr
Уточняйте все и сразу: какого рода ваши конфиги, маска файлов подойдет? »

3 маски нужно. Там конфиги трех разных расширений...

Dodakaedr 09-06-2019 07:56 2874940

Цитата:

Цитата vk_k14m@vk
Что я сделал не так? »

Указали не правильную константу.

vk_k14m@vk 09-06-2019 17:41 2874984

Цитата:

Цитата Dodakaedr
Указали не правильную константу. »

Ясно...

vk_k14m@vk 12-06-2019 20:04 2875412

Народ. Есть игра, в корне которой лежит текстовый файл config.ksc, с текстом
Код:

(const) %[
 "saveDataLocation" => "file://./d/документы/fateavedata"
]

d/документы/fateavedata - это папка в которую игра будет сохранятся.

Так вот как бы настроить создание этого файла в установщике?

Нужно что б на странице выбора папки установки игры, или на следующей после этой странице можно было выбрать путь к папке сохранения (и создание этой папки если ее нет). И после завершения установки этот путь должен прописаться в файле config.ksc

Как бы это провернуть? Надеюсь на вашу помощь...

El Sanchez 13-06-2019 16:20 2875495

Цитата:

Цитата vk_k14m@vk
Так вот как бы настроить создание этого файла в установщике? »

Скрытый текст

Код:

[Code]
procedure RtlMoveMemory(Dest: PAnsiChar; Source: string; Len: Integer); external 'RtlMoveMemory@kernel32.dll stdcall';

var
  SaveDataLocationPage: TInputDirWizardPage;

procedure SetSaveDataLocation;
var
  S1: string;
  S2: AnsiString;
begin
  S1 := SaveDataLocationPage.Values[0];
  StringChangeEx(S1, ':', '', True);
  StringChangeEx(S1, '\', '/', True);
  S1 := '%["saveDataLocation" => "file://./' + S1 + '"]';
  S2 := StringOfChar(#0, Length(S1) shl 1);
  RtlMoveMemory(S2, S1, Length(S2));
  S2 := Chr($FF) + Chr($FE) + S2;
  SaveStringToFile(ExpandConstant(CurrentFileName), S2, False);
end;

procedure CreateSaveDataLocationPage;
begin
  SaveDataLocationPage := CreateInputDirPage(wpSelectDir, 'caption', 'description', 'subcaption', False, 'fateavedata');
  SaveDataLocationPage.Add('prompt');
end;

procedure InitializeWizard;
begin
  CreateSaveDataLocationPage;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  case CurPageID of
    SaveDataLocationPage.ID:
      if SaveDataLocationPage.Values[0] = '' then
        SaveDataLocationPage.Values[0] := ExpandConstant('{app}\fateavedata');
  end;
end;


Dodakaedr 13-06-2019 19:32 2875508

Цитата:

Цитата El Sanchez
S2 := Chr($FF) + Chr($FE) + S2; »

А какие начальные байты у ANSI?

Iska 13-06-2019 20:53 2875518

Dodakaedr, никаких. Для ANSI и OEM нет BOM.

vk_k14m@vk 14-06-2019 00:13 2875522

El Sanchez, к сожалению твой код не работает. Или правильнее будет сказать, работает не до конца. Страница в выбором папки установки и правда появилась.
https://i106.fastpic.ru/big/2019/061...eabf7dd4c8.png

Вот только файл config.ksc с текстом
Код:

(const) %[
 "saveDataLocation" => "file://./{app}\fateavedata"
]

в папке с игрой не появляется. Может я что-то не так сделал?
Скрытый текст
Код:

; Скрипт создан при помощи мастера создания скриптов.
; СМ. ДОКУМЕНТАЦИЮ ДЛЯ ИЗУЧЕНИЯ ДЕТАЛЕЙ ОТНОСИТЕЛЬНО СОЗДАНИЯ ФАЙЛОВ СКРИПТА INNO SETUP!

#define MyAppName "Fate/Stay Night [Realta Nua] - Ultimate Edition"
#define MyAppVerName "Fate/Stay Night [Realta Nua] - Ultimate Edition v0.9.1"
#define MyAppPublisher "Type-Moon"
#define MyAppExeName "Fate.exe"

[Setup]
AppName={#MyAppName}
AppVerName={#MyAppVerName}
AppPublisher={#MyAppPublisher}
DefaultDirName=D:\Games\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
OutputDir=D:\
OutputBaseFilename=setup
DisableWelcomePage=no
SetupIconFile=D:\Fate/Stay Night [Realta Nua] - Ultimate Edition\icon.ico
WizardImageFile=D:\Fate/Stay night\WizardImageFile.bmp
WizardSmallImageFile=D:\Fate/Stay night\WizardSmallImageFile.bmp
Compression=lzma/ultra64
SolidCompression=yes
DiskSpanning=yes
DiskSliceSize=1073741824

[Languages]
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "D:\Fate/Stay Night [Realta Nua] - Ultimate Edition\Fate.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "D:\Fate/Stay Night [Realta Nua] - Ultimate Edition\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; ОТМЕТЬТЕ: Не используйте "Флажки: Проигнорировать версию" на любых общедоступных системных файлах

[Code ]
procedure RtlMoveMemory(Dest: PAnsiChar; Source: string; Len: Integer); external 'RtlMoveMemory@kernel32.dll stdcall';

var
  SaveDataLocationPage: TInputDirWizardPage;

procedure SetSaveDataLocation;
var
  S1: string;
  S2: AnsiString;
begin
  S1 := SaveDataLocationPage.Values[0];
  StringChangeEx(S1, ':', '', True);
  StringChangeEx(S1, '\', '/', True);
  S1 := '%["saveDataLocation" => "file://./' + S1 + '"]';
  S2 := StringOfChar(#0, Length(S1) shl 1);
  RtlMoveMemory(S2, S1, Length(S2));
  S2 := Chr($FF) + Chr($FE) + S2;
  SaveStringToFile(ExpandConstant(CurrentFileName), S2, False);
end;

procedure CreateSaveDataLocationPage;
begin
  SaveDataLocationPage := CreateInputDirPage(wpSelectDir, 'Выбор папки сохранений', 'В какую папку должна сохраняться игра Fate/Stay Night [Realta Nua] - Ultimate Edition?', 'Программа настроит сохранения игры Fate/Stay Night [Realta Nua] - Ultimate Edition в следующую папку.', False, 'fateavedata');
  SaveDataLocationPage.Add('Нажмите «Далее», что бы продолжить. Если вы хотите выбрать другую папку, нажмите «Обзор».');
end;

procedure InitializeWizard;
begin
  CreateSaveDataLocationPage;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  case CurPageID of
    SaveDataLocationPage.ID:
      if SaveDataLocationPage.Values[0] = '' then
        SaveDataLocationPage.Values[0] := ExpandConstant('{app}\fateavedata');
  end;
end;

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#MyAppName}}"; Flags: nowait postinstall skipifsilent



А еще, можно как то разобрать уже созданный установщик что б узнать исходный код? Я не знаю в какой программе он был создан, но очень бы хотелось его разобрать...

ErikPshat 14-06-2019 01:01 2875526

vk_k14m@vk, ну свою прогу вы можете распаковать этим: Inno Setup Unpacker
Секцию Code вы конечно не дизассемблируете, т.к. она в бинарном виде изначально будет упакована, но всё остальное прекрасно извлекается.
А вот надо сначала узнать, в какой программе был создан экзешник, потом извлекать соответствующим софтом.

vk_k14m@vk 14-06-2019 01:04 2875528

Цитата:

Цитата ErikPshat
ну свою прогу вы можете распаковать этим: Inno Setup Unpacker
Секцию Code вы конечно не дизассемблируете, т.к. она в бинарном виде изначально будет упакована, но всё остальное прекрасно извлекается.
А вот надо сначала узнать, в какой программе был создан экзешник, потом извлекать соответствующим софтом. »

Жаль. Тот установщик который я хочу распаковать не содержит в себе файлов. Он качает их откуда-то в интернете. Так что скорее всего мне именно секция Code и нужна.

А можно как то узнать в какой программе был создан установщик?

ErikPshat 14-06-2019 01:33 2875529

Цитата:

Цитата vk_k14m@vk
А можно как то узнать в какой программе был создан установщик? »

Вот вам список прог в помощь: PEiD, DiE (Detect It Easy), Bit Detector, SCANiT, ExeScan, FastScanner и PE Tools
Ну или вот вам пару ресурсов:
  1. https://exelab.ru/download.php
  2. http://www.manhunter.ru/underground/...ih_faylov.html

El Sanchez 14-06-2019 09:54 2875539

Цитата:

Цитата vk_k14m@vk
Вот только файл config.ksc с текстом в папке с игрой не появляется. Может я что-то не так сделал? »

vk_k14m@vk, ой, не все скопировал у себя, когда пост оформлял. Добавить в [Files] пустышку config.ksc:
Код:

[Files]
Source: config.ksc; DestDir: {app}; AfterInstall: SetSaveDataLocation


vk_k14m@vk 14-06-2019 10:24 2875540

Цитата:

Цитата El Sanchez
ой, не все скопировал у себя, когда пост оформлял. Добавить в [Files] пустышку config.ksc: »

Теперь файл создается. Это уже хорошо. Но ошибка все еще есть.

Создается файл с таким содержимым
Код:

%["saveDataLocation" => "file://./D/Games/Fate/Stay Night [Realta Nua] - Ultimate Edition/fateavedata"]
А должно быть такое
Код:

(const) %[
 "saveDataLocation" => "file://./D/Games/Fate/Stay Night [Realta Nua] - Ultimate Edition/fateavedata"
]

Из-за чего игра крашится после первого запуска. А при втором запуске крашится моментально...

El Sanchez 14-06-2019 14:39 2875556

Цитата:

Цитата vk_k14m@vk
Из-за чего игра крашится после первого запуска. А при втором запуске крашится моментально »

vk_k14m@vk, а (const) добавить к S1 := '(const) %["saveDataLocation" => "file://./' + S1 + '"]';?

Dodakaedr 14-06-2019 19:25 2875571

Цитата:

Цитата vk_k14m@vk
А должно быть такое »

Код:

S1 := '(const) %['+#13' "saveDataLocation" => "file://./' + S1 + '"'+#13+']';
и добавьте еще это
Код:

if not DirExists(s1) then ForceDirectories(s1);
после
Код:

S1 := SaveDataLocationPage.Values[0];
в процедуре SetSaveDataLocation.

Bio_Hazard 07-07-2019 22:36 2878683

Здравствуйте!
Есть небольшой простой скрипт для установки мода в игру. Он делает бекап оригинальных файлов, копирует новые и создает деинсталлятор.
Его необходимо немного усовершенствовать:
1. Создать резервную копию файлов Game.dll и Game_DX11.dll.
2. Скопировать в корень игры 4 файла XVI32 .cmd/.exe/.ini/.xsc
3. Выполнить XVI32.cmd
4. Удалить эти 4 файла.
5. При деинсталляции вернуть исходные Game.dll и Game_DX11.dll.
Можете помочь с такой задачей?
P.S. с Inno Setup (да и в принципе с программированием) не дружу совсем.
Файл 158063

El Sanchez 09-07-2019 11:01 2878880

Bio_Hazard, а пункты 2-4 это и есть усовершенствования по сравнению с "копирует новые"?
Скрытый текст

Код:

#define AppName "Game Name"

[Setup]
AppName={#AppName} Mod
AppVersion=1.0
DefaultDirName={pf}\{#AppName}
DirExistsWarning=no

[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl

[Files]
Source: {app}\Game.dll; DestDir: {app}; DestName: Game.dll.bkp; Flags: external skipifsourcedoesntexist
Source: {app}\Game_DX11.dll; DestDir: {app}; DestName: Game_DX11.dll.bkp; Flags: external skipifsourcedoesntexist
Source: xvi32.*; DestDir: {app}; Flags: deleteafterinstall

[Run]
Filename: {app}\xvi32.cmd; Flags: runhidden shellexec skipifdoesntexist

[UninstallDelete]
Type: files; Name: {app}\Game.dll.bkp
Type: files; Name: {app}\Game_DX11.dll.bkp

[Code]
procedure RestoreFromBackup(const AFileName: string);
var
  LFileName: string;
begin
  LFileName := ChangeFileExt(AFileName, '');
  if FileExists(LFileName) then
    FileCopy(AFileName, ChangeFileExt(AFileName, ''), False);
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  case CurUninstallStep of
    usUninstall:
      begin
        RestoreFromBackup(ExpandConstant('{app}\Game.dll.bkp'));
        RestoreFromBackup(ExpandConstant('{app}\Game_DX11.dll.bkp'));
      end;
  end;
end;


Bio_Hazard 09-07-2019 15:37 2878922

Цитата:

Цитата Bio_Hazard
Есть небольшой простой скрипт для установки мода в игру. Он делает бекап оригинальных файлов, копирует новые и создает деинсталлятор. »

Это делает текущий скрипт.

Я не знаю, почему мой архив не подгрузился (Файл 158063), но взяв большую часть Вашего кода, совместил его со "своим" и немного доработав XVI32.cmd, я получил рабочий, полностью удовлетворяющий мои цели скрипт. Может получилось немного топорно, но работает.

Вот что получилось:
Код:

#define ModName "TQRagnarökMod by BioHazardN7"
#define ModVersion "2.3.27"
#define ModShortDescription "Модификация для Titan Quest"

[Setup]
AppId={{70653654-6624-42B4-B9A4-CAE370D75364}
AppName={#ModName} {#ModVersion}
AppVerName={#ModName} {#ModVersion}
// AppPublisher=http://tqrm.zzz.com.ua
// AppPublisherURL=http://tqrm.zzz.com.ua
// AppSupportURL=http://tqrm.zzz.com.ua
// AppUpdatesURL=http://tqrm.zzz.com.ua
DefaultDirName={code:GetInstallationPath}
DefaultGroupName={#ModName}
DirExistsWarning=no
DisableWelcomePage=no
AllowNoIcons=true
InfoBeforeFile=Data\Description.rtf
OutputDir=Release
OutputBaseFilename=TQRagnarokMod2327a_Installer
SetupIconFile=Data\Icon.ico
// Степень сжатия. Сильное: lzma/ultra
Compression=none
SolidCompression=true
VersionInfoVersion={#ModVersion}
// VersionInfoCompany=http://tqrm.zzz.com.ua
VersionInfoDescription={#ModShortDescription}
WizardImageFile=Data\Poster.bmp
// VersionInfoCopyright=(c) http://tqrm.zzz.com.ua
WizardSmallImageFile=Data\Logo.bmp

[Languages]
Name: russian; MessagesFile: compiler:Languages\Russian.isl

[Files]
Source: Files\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs; BeforeInstall: CreateBackup
Source: {app}\Game.dll; DestDir: {app}; DestName: Game.dll.bak; Flags: external skipifsourcedoesntexist
Source: {app}\Game_DX11.dll; DestDir: {app}; DestName: Game_DX11.dll.bak; Flags: external skipifsourcedoesntexist

[Run]
Filename: {app}\xvi32.cmd; Flags: runhidden shellexec skipifdoesntexist

[UninstallDelete]
Type: files; Name: {app}\Game.dll.bak
Type: files; Name: {app}\Game_DX11.dll.bak

[Icons]
Name: {group}\{cm:ProgramOnTheWeb,{#ModName} {#ModVersion}}; Filename: http://tqrm.zzz.com.ua
Name: {group}\Последняя версия {#ModName}; Filename: http://tqrm.zzz.com.ua/ru/#download
Name: {group}\The latest version of {#ModName}; Filename: http://tqrm.zzz.com.ua/en/#download
Name: {group}\www.titanquest.org.ua; Filename: https://titanquest.org.ua/tqragnarokmod_by_biohazardn7
Name: {group}\vk.com; Filename: https://vk.com/tqrm_n7
Name: {group}\Telegram; Filename: https://t.me/TQRM_N7
Name: {group}\{cm:UninstallProgram,{#ModName} {#ModVersion}}; Filename: {uninstallexe}

// [Messages]
// BeveledLabel=http://tqrm.zzz.com.ua

[code]

procedure RestoreFromBackup(const AFileName: string);
var
  LFileName: string;
begin
  LFileName := ChangeFileExt(AFileName, '');
  if FileExists(LFileName) then
    FileCopy(AFileName, ChangeFileExt(AFileName, ''), False);
end;

// DETECT PREVIOUS VERSION

function InitializeSetup(): Boolean;
begin
  Result := True;
  if RegKeyExists(HKEY_LOCAL_MACHINE,
      'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{70653654-6624-42B4-B9A4-CAE370D75364}_is1') or
    RegKeyExists(HKEY_LOCAL_MACHINE,
      'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{70653654-6624-42B4-B9A4-CAE370D75364}_is1') or
    RegKeyExists(HKEY_CURRENT_USER,
      'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{70653654-6624-42B4-B9A4-CAE370D75364}_is1') then
  begin
    Log('NEEED')
    //MsgBox('Для переустановки или установки новой версии - необходимо удалить предыдущую', mbInformation, MB_OK);
    //Result := False;
  end;
end;

// CLICKABLE LINK TO TQ SITE

procedure BevelLabelClick(Sender: TObject);
var ErrorCode: Integer;
begin
ShellExec('open','http://tqrm.zzz.com.ua','', '', SW_SHOW, ewNoWait, ErrorCode)
end;

procedure InitializeWizard();
begin
with WizardForm do begin
with BeveledLabel do begin
OnClick:=@BevelLabelClick;
Font.Color:=clBlue;
Enabled:=True;
Cursor:=crHand;
end;
end;
end;

// PAGE WITH DESTINATION

procedure CurPageChanged(CurPageID: Integer);
begin
If CurPageID=wpSelectDir then
begin
  WizardForm.DirEdit.Enabled := True;
  WizardForm.DirBrowseButton.Enabled := True;
end
else
end;


// CREATE BACKUP BEFORE INSTALL

procedure CreateBackup;
var
  srcFile, destFile: string;
  begin
  if RegKeyExists(HKEY_LOCAL_MACHINE,
      'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{70653654-6624-42B4-B9A4-CAE370D75364}_is1') or
    RegKeyExists(HKEY_LOCAL_MACHINE,
      'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{70653654-6624-42B4-B9A4-CAE370D75364}_is1') or
    RegKeyExists(HKEY_CURRENT_USER,
      'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{70653654-6624-42B4-B9A4-CAE370D75364}_is1') then
      begin
      // Do nothing
      end
      else
          begin
            srcFile:= ExpandConstant(CurrentFileName);
            destFile:= srcFile + '.bak';
            DeleteFile(destFile);
            RenameFile(srcFile, destFile);
          end
  end;
 
procedure RestoreBackup(backupDir: string);
var
srcFile, destFile: string;
FSR, DSR: TFindRec;
FindResult: Boolean;
APath: string;
begin
APath := AddBackslash(backupDir);
FindResult := FindFirst(APath + '*.bak', FSR);
try
while FindResult do
begin
if FSR.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
begin
srcFile:= APath + FSR.Name;
destFile:= Copy(srcFile, 0, Length(srcFile)-4);
DeleteFile(destFile);
RenameFile(srcFile, destFile);
end;
FindResult := FindNext(FSR);
end;
FindResult := FindFirst(APath + '*.*', DSR);
while FindResult do
begin
if ((DSR.Attributes and FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY) and
not ((DSR.Name = '.') or (DSR.Name = '..')) then
{Recursion} RestoreBackup(APath + DSR.Name);
FindResult := FindNext(DSR);
end;
finally
FindClose(FSR);
FindClose(DSR);
end;
end;

// RESTORE BACKUP AFTER UNINSTALL

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usPostUninstall then
  begin
    RestoreBackup(ExpandConstant('{app}'))
  end;
  begin
    case CurUninstallStep of
      usUninstall:
        begin
          RestoreFromBackup(ExpandConstant('{app}\Game.dll.bak'));
          RestoreFromBackup(ExpandConstant('{app}\Game_DX11.dll.bak'));
        end;
    end;
  end;
end;

// DETECT PATH OF INSTALLATION

var
  InstallationPath: string;

function GetInstallationPath(Param: string): string;
begin
  { Detected path is cached, as this gets called multiple times }
  if InstallationPath = '' then
  begin
    if RegQueryStringValue(
        HKLM32, 'SOFTWARE\WOW6432Node\GOG.com\Games\1196955511',
        'path', InstallationPath) then
    begin
      Log('Detected GOG installation: ' + InstallationPath);
    end
      else
    if RegQueryStringValue(
        HKLM64, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 475150',
        'InstallLocation', InstallationPath) then
    begin
      Log('Detected Steam installation: ' + InstallationPath);
    end
      else
    begin
      InstallationPath := ExpandConstant('{pf}');
      MsgBox('Не удалось автоматически определить где установлена игра. В ходе установки укажите путь вручную', mbInformation, MB_OK);
      Log('No installation detected, using the default path: ' + InstallationPath);
    end;
  end;
  Result := InstallationPath;
end;



Спасибо за помощь!

El Sanchez 09-07-2019 21:39 2879046

Цитата:

Цитата Bio_Hazard
я получил рабочий, полностью удовлетворяющий мои цели скрипт »

Bio_Hazard, использование явного указания WOW6432Node в коде - это преступление против человечества, уберите все RegKeyExists, где есть WOW6432Node в параметре.

Bio_Hazard 09-07-2019 23:06 2879065

Цитата:

Цитата El Sanchez
использование явного указания WOW6432Node в коде - это преступление против человечества, уберите все RegKeyExists, где есть WOW6432Node в параметре. »

Спасибо за совет, исправил.

Bio_Hazard 16-07-2019 15:16 2880055

Здравствуйте. Обнаружился косяк при установке на 32-х битных системах (обнаружилось на Windows 7)
Ошибка
Код инсталлятора:
Код:

#define ModName "TQRagnarökMod by BioHazardN7"
#define ModVersion "2.3.27"
#define ModShortDescription "Модификация для Titan Quest"

[Setup]
AppId={{70653654-6624-42B4-B9A4-CAE370D75364}
AppName={#ModName} {#ModVersion}
AppVerName={#ModName} {#ModVersion}
// AppPublisher=http://tqrm.zzz.com.ua
// AppPublisherURL=http://tqrm.zzz.com.ua
// AppSupportURL=http://tqrm.zzz.com.ua
// AppUpdatesURL=http://tqrm.zzz.com.ua
DefaultDirName={code:GetInstallationPath}
DefaultGroupName={#ModName}
DirExistsWarning=no
DisableWelcomePage=no
AllowNoIcons=true
InfoBeforeFile=Data\Description.rtf
OutputDir=Release
OutputBaseFilename=TQRagnarokMod2327a_Installer
SetupIconFile=Data\Icon.ico
// Степень сжатия. Сильное: lzma/ultra
Compression=none
SolidCompression=true
VersionInfoVersion={#ModVersion}
// VersionInfoCompany=http://tqrm.zzz.com.ua
VersionInfoDescription={#ModShortDescription}
WizardImageFile=Data\Poster.bmp
// VersionInfoCopyright=(c) http://tqrm.zzz.com.ua
WizardSmallImageFile=Data\Logo.bmp

[Languages]
Name: russian; MessagesFile: compiler:Languages\Russian.isl

[Files]
Source: Files\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs; BeforeInstall: CreateBackup
Source: {app}\Game.dll; DestDir: {app}; DestName: Game.dll.bak; Flags: external skipifsourcedoesntexist
Source: {app}\Game_DX11.dll; DestDir: {app}; DestName: Game_DX11.dll.bak; Flags: external skipifsourcedoesntexist

[Run]
Filename: {app}\xvi32.cmd; Flags: runhidden shellexec skipifdoesntexist

[UninstallDelete]
Type: files; Name: {app}\Game.dll.bak
Type: files; Name: {app}\Game_DX11.dll.bak

[Icons]
Name: {group}\{cm:ProgramOnTheWeb,{#ModName} {#ModVersion}}; Filename: http://tqrm.zzz.com.ua
Name: {group}\Последняя версия {#ModName}; Filename: http://tqrm.zzz.com.ua/ru/#download
Name: {group}\The latest version of {#ModName}; Filename: http://tqrm.zzz.com.ua/en/#download
Name: {group}\www.titanquest.org.ua; Filename: https://titanquest.org.ua/tqragnarokmod_by_biohazardn7
Name: {group}\vk.com; Filename: https://vk.com/tqrm_n7
Name: {group}\Telegram; Filename: https://t.me/TQRM_N7
Name: {group}\{cm:UninstallProgram,{#ModName} {#ModVersion}}; Filename: {uninstallexe}

// [Messages]
// BeveledLabel=http://tqrm.zzz.com.ua

[code]

procedure RestoreFromBackup(const AFileName: string);
var
  LFileName: string;
begin
  LFileName := ChangeFileExt(AFileName, '');
  if FileExists(LFileName) then
    FileCopy(AFileName, ChangeFileExt(AFileName, ''), False);
end;

// DETECT PREVIOUS VERSION

function InitializeSetup(): Boolean;
begin
  Result := True;
  if RegKeyExists(HKEY_LOCAL_MACHINE,
      'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{70653654-6624-42B4-B9A4-CAE370D75364}_is1') or
    RegKeyExists(HKEY_CURRENT_USER,
      'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{70653654-6624-42B4-B9A4-CAE370D75364}_is1') then
  begin
    Log('NEEED')
    //MsgBox('Для переустановки или установки новой версии - необходимо удалить предыдущую', mbInformation, MB_OK);
    //Result := False;
  end;
end;

// CLICKABLE LINK TO TQ SITE

procedure BevelLabelClick(Sender: TObject);
var ErrorCode: Integer;
begin
ShellExec('open','http://tqrm.zzz.com.ua','', '', SW_SHOW, ewNoWait, ErrorCode)
end;

procedure InitializeWizard();
begin
with WizardForm do begin
with BeveledLabel do begin
OnClick:=@BevelLabelClick;
Font.Color:=clBlue;
Enabled:=True;
Cursor:=crHand;
end;
end;
end;

// PAGE WITH DESTINATION

procedure CurPageChanged(CurPageID: Integer);
begin
If CurPageID=wpSelectDir then
begin
  WizardForm.DirEdit.Enabled := True;
  WizardForm.DirBrowseButton.Enabled := True;
end
else
end;


// CREATE BACKUP BEFORE INSTALL

procedure CreateBackup;
var
  srcFile, destFile: string;
  begin
  if RegKeyExists(HKEY_LOCAL_MACHINE,
      'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{70653654-6624-42B4-B9A4-CAE370D75364}_is1') or
    RegKeyExists(HKEY_CURRENT_USER,
      'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{70653654-6624-42B4-B9A4-CAE370D75364}_is1') then
      begin
      // Do nothing
      end
      else
          begin
            srcFile:= ExpandConstant(CurrentFileName);
            destFile:= srcFile + '.bak';
            DeleteFile(destFile);
            RenameFile(srcFile, destFile);
          end
  end;
 
procedure RestoreBackup(backupDir: string);
var
srcFile, destFile: string;
FSR, DSR: TFindRec;
FindResult: Boolean;
APath: string;
begin
APath := AddBackslash(backupDir);
FindResult := FindFirst(APath + '*.bak', FSR);
try
while FindResult do
begin
if FSR.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
begin
srcFile:= APath + FSR.Name;
destFile:= Copy(srcFile, 0, Length(srcFile)-4);
DeleteFile(destFile);
RenameFile(srcFile, destFile);
end;
FindResult := FindNext(FSR);
end;
FindResult := FindFirst(APath + '*.*', DSR);
while FindResult do
begin
if ((DSR.Attributes and FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY) and
not ((DSR.Name = '.') or (DSR.Name = '..')) then
{Recursion} RestoreBackup(APath + DSR.Name);
FindResult := FindNext(DSR);
end;
finally
FindClose(FSR);
FindClose(DSR);
end;
end;

// RESTORE BACKUP AFTER UNINSTALL

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usPostUninstall then
  begin
    RestoreBackup(ExpandConstant('{app}'))
  end;
  begin
    case CurUninstallStep of
      usUninstall:
        begin
          RestoreFromBackup(ExpandConstant('{app}\Game.dll.bak'));
          RestoreFromBackup(ExpandConstant('{app}\Game_DX11.dll.bak'));
        end;
    end;
  end;
end;

// DETECT PATH OF INSTALLATION

var
  InstallationPath: string;

function GetInstallationPath(Param: string): string;
begin
  { Detected path is cached, as this gets called multiple times }
  if InstallationPath = '' then
  begin
    if RegQueryStringValue(
        HKLM32, 'SOFTWARE\GOG.com\Games\1196955511',
        'path', InstallationPath) then
    begin
      Log('Detected GOG installation: ' + InstallationPath);
    end
      else
    if RegQueryStringValue(
        HKLM64, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 475150',
        'InstallLocation', InstallationPath) then
    begin
      Log('Detected Steam installation: ' + InstallationPath);
    end
      else
    begin
      InstallationPath := ExpandConstant('{pf}');
      MsgBox('Не удалось автоматически определить где установлена игра. В ходе установки укажите путь вручную', mbInformation, MB_OK);
      Log('No installation detected, using the default path: ' + InstallationPath);
    end;
  end;
  Result := InstallationPath;
end;


Можете подсказать как исправить?

Dodakaedr 16-07-2019 16:11 2880065

Цитата:

Цитата Bio_Hazard
Обнаружился косяк при установке на 32-х битных системах »

Замените функцию и пробуйте
Скрытый текст
Код:

function GetInstallationPath(Param: string): string;
begin
  { Detected path is cached, as this gets called multiple times }
  if InstallationPath = '' then
  begin
    if RegQueryStringValue(
        HKLM32, 'SOFTWARE\GOG.com\Games\1196955511',
        'path', InstallationPath) then
    begin
      Log('Detected GOG installation: ' + InstallationPath);
    end
      else
    if IsWin64 then
    if RegQueryStringValue(
        HKLM64, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 475150',
        'InstallLocation', InstallationPath) then
    begin
      Log('Detected Steam installation: ' + InstallationPath);
    end
      else
    begin
      InstallationPath := ExpandConstant('{pf}');
      MsgBox('Не удалось автоматически определить где установлена игра. В ходе установки укажите путь вручную', mbInformation, MB_OK);
      Log('No installation detected, using the default path: ' + InstallationPath);
    end;
  end;
  Result := InstallationPath;
end;


Bio_Hazard 18-07-2019 12:18 2880407

Цитата:

Цитата Dodakaedr
Замените функцию и пробуйте »

Спасибо, работает.

Romann_ 22-07-2019 22:28 2881052

Цитата:

Как вставить видео в инсталлятор?
этой библиотекой ещё можно
норм библиотека от Vintage)
Всем привет.
Все ссылки, в прочем как и имеющиеся советы - устарели. Может ли кто нибудь подсказать - как в инсталлятор вставить фоновое видео, вместо картинки?
********************************************
И ещё вопрос - как можно нормально проверить системные требования? - Уже третьи сутки ищу по форумам, везде попадается старый код для проверки XPюши или ниже, найти бы способ проверки современных ОС, а так же разрядность системы. Ну и не помешало бы адекватно проверить и остальные сис. требования, а то я нашёл старенький скрипт инсталлятора с проверкой - у меня стоит видюха на 6Гб, а проверка на 1024 - а пишет, что моего видео не достаточно, только на ОЗУ нормально работает.

Romann_ 24-07-2019 12:36 2881225

Цитата:

Цитата Romann_
так же разрядность системы »

Нашёл необходимый код, имеем такое:
Код:


procedure UpdateInfo();
var
  DeviceName, DeviceKey: String;
begin
  ChangeText := False

  GetWindowsVersionEx(Version)

  // Операционная система:
  SystemVersionPanel.Color := clBlack
    SystemVersionPanel.Font.Color := clGreen

  DeviceKey := 'Software\Microsoft\Windows NT\CurrentVersion'
  if not UsingWinNT then StringChange(DeviceKey, 'Windows NT', 'Windows')
        RegQueryStringValue(HKLM, DeviceKey, 'ProductName', DeviceName)
  if RegQueryStringValue(HKLM, DeviceKey, 'CSDVersion', DeviceKey) then
    DeviceName := DeviceName + ' ' + DeviceKey
        StringChange(DeviceName, 'Microsoft ', '')
  SystemVersionPanel.Text := ' ' + DeviceName + ' сборка ' + IntToStr(Version.Major) + '.' + IntToStr(Version.Minor) +
                            '.' + IntToStr(Version.Build)

  if (Pos('Windows 10', SystemVersionPanel.Text) = 0) and  // Windows 10
    (Pos('Windows 7', SystemVersionPanel.Text) = 0) then  // Windows 7
    begin
      SystemVersionPanel.Color := clBlack
      SystemVersionPanel.Font.Color := clRed
      ChangeText := True
    end
...
...
...

Всё работает. Но как можно ещё проверить разрядность системы?(У некоторых всё ещё есть win7 х86.)

habib2302 24-07-2019 12:42 2881226

Romann_, можете еще проштудировать форум http://krinkels.org/

ErikPshat 24-07-2019 13:30 2881228

Цитата:

Цитата Romann_
Но как можно ещё проверить разрядность системы?(У некоторых всё ещё есть win7 х86.) »

Ну могу поделиться готовым рабочим шаблоном по определению версии Windows (XP/7/Vista/8/8.1/10) и её разрядности. Там как раз ответы на все ваши вопросы, надеюсь разберётесь. Правда там подмешано определение, скачивание и установка нужной версии PowerShell. Ну и ещё там подключён плагин "Inno Download Plugin", подключён скин и подключена заставка, ну и ещё 3 языка. Надеюсь вы сами сможете убрать что лишнее и применить по своему назначению... Правда там это всё реализовано совсем по-другому, у меня прекрасно работает, может пригодится и поможет. Название программы и ссылки изменены. Не забудьте убрать нижнее подчёркивание из названия секции [_Code]
Скрипт полный
Код:

;InnoSetupVersion=5.6.1 (Unicode)
#pragma include __INCLUDE__ + ";" + ReadReg(HKLM, "Software\Mitrich Software\Inno Download Plugin", "InstallDir")

#define MyApp "My Super-Puper Programm"
#define ShortName "MSPP"
#define Version "3.4.2"
#define Publisher "by SuperUser"
#define Team "Super Team"
#define URL "http://forum.oszone.net/post-2881225.html"
#define UpdatesURL "https://github.com/SuperUser/SuperTeam/blob/master/update.exe"
#define ExeName "MSPP"
#define Skin "CrystalBlue"

[Setup]
AppId={{E4F0B51A-4567-4C49-AD5D-D9A8B6BBBCF3F}
AppName={#ShortName}
AppVersion={#Version}
AppVerName={#MyApp} v{#Version}
AppPublisher={#MyApp} {#Team}
AppPublisherURL={#URL}
AppSupportURL={#URL}
AppUpdatesURL={#UpdatesURL}
DefaultDirName={sd}\{#ShortName}
DefaultGroupName={#ShortName}
ShowLanguageDialog=no
UninstallDisplayIcon={app}\MSPP.exe
UninstallDisplayName={#ShortName}
AllowNoIcons=yes
OutputDir=.
OutputBaseFilename=setup
SetupIconFile=embedded\myicon.ico
WizardImageFile=embedded\WizardImage.bmp
WizardSmallImageFile=embedded\WizardSmallImage.bmp
WizardImageAlphaFormat=premultiplied
VersionInfoCompany={#Team}
VersionInfoCopyright={#ShortName} {#Publisher}
VersionInfoDescription={#MyApp} {#Publisher}
VersionInfoVersion={#Version}
Compression=lzma2/max
SolidCompression=Yes

#include <idp.iss>
#include <idplang\Russian.iss>
#include <idplang\German.iss>

[Files]
Source: "embedded\ISSkin\ISSkinU.dll"; DestDir: {tmp}; Flags: dontcopy
Source: "embedded\ISSkin\Styles\{#Skin}.cjstyles"; DestDir: {tmp}; Flags: dontcopy
Source: "embedded\7z.dll"; DestDir: {tmp}; Flags: dontcopy
Source: "embedded\7z.exe"; DestDir: {tmp}; Flags: dontcopy
Source: "embedded\7z32.dll"; DestDir: {tmp}; Flags: dontcopy
Source: "embedded\7z32.exe"; DestDir: {tmp}; Flags: dontcopy
Source: "{app}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "embedded\EN\config.ini"; DestDir: "{app}"; Languages: en; Flags: ignoreversion
Source: "embedded\RU\config.ini"; DestDir: "{app}"; Languages: ru; Flags: ignoreversion
Source: "embedded\DE\config.ini"; DestDir: "{app}"; Languages: de; Flags: ignoreversion

[Languages]
Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"; InfoBeforeFile: "embedded\InfoBefore-ru.rtf"
Name: "en"; MessagesFile: "compiler:Default.isl"; InfoBeforeFile: "embedded\InfoBefore-en.rtf"
Name: "de"; MessagesFile: "compiler:Languages\German.isl"; InfoBeforeFile: "embedded\InfoBefore-de.rtf"

[CustomMessages]
ru.CautionXP64=Для работы программы требуется PowerShell 5.1.%nНа Windows XP 64bit программа не сможет скачивать обновления для конвертации игр и выполнять некоторые другие функции.
ru.CautionVI64=Для работы программы требуется PowerShell 5.1.%nНа Windows Vista 64bit программа не сможет скачивать обновления для конвертации игр и выполнять некоторые другие функции.
ru.Caution7064=На компьютере обнаружена устаревшая версия PowerShell.%nПосле установки программы будет произведено скачивание и установка обновления PowerShell 5.1 для Windows 7 64bit.%n%nПожалуйста, дождитесь завершения обновления!
ru.Caution8064=На компьютере обнаружена устаревшая версия PowerShell.%nПосле установки программы будет произведено скачивание и установка обновления PowerShell 5.1 для Windows 8.0 64bit.%n%nПожалуйста, дождитесь завершения обновления!
ru.Caution8164=На компьютере обнаружена устаревшая версия PowerShell.%nПосле установки программы будет произведено скачивание и установка обновления PowerShell 5.1 для Windows 8.1 64bit.%n%nПожалуйста, дождитесь завершения обновления!
ru.CautionXP32=Для работы программы требуется PowerShell 5.1.%nНа Windows XP 32bit программа не сможет скачивать обновления для конвертации игр и выполнять некоторые другие функции.
ru.CautionVI32=Для работы программы требуется PowerShell 5.1.%nНа Windows Vista 32bit программа не сможет скачивать обновления для конвертации игр и выполнять некоторые другие функции.
ru.Caution7032=На компьютере обнаружена устаревшая версия PowerShell.%nПосле установки программы будет произведено скачивание и установка обновления PowerShell 5.1 для Windows 7 32bit.%n%nПожалуйста, дождитесь завершения обновления!
ru.Caution8132=На компьютере обнаружена устаревшая версия PowerShell.%nПосле установки программы будет произведено скачивание и установка обновления PowerShell 5.1 для Windows 8.1 32bit.%n%nПожалуйста, дождитесь завершения обновления!

en.CautionXP64=The program requires PowerShell 5.1.%nOn Windows XP 64bit, the program will not be able to download updates for converting games and perform some other functions.
en.CautionVI64=The program requires PowerShell 5.1.%nOn Windows Vista 64bit, the program will not be able to download updates for converting games and perform some other functions.
en.Caution7064=An outdated version of PowerShell has been detected on your computer.%nAfter installing the program, the PowerShell 5.1 update for Windows 7 64bit will be downloaded and installed.%n%nPlease wait until the update is complete!
en.Caution8064=An outdated version of PowerShell has been detected on your computer.%nAfter installing the program, the PowerShell 5.1 update for Windows 8.0 64bit will be downloaded and installed.%n%nPlease wait until the update is complete!
en.Caution8164=An outdated version of PowerShell has been detected on your computer.%nAfter installing the program, the PowerShell 5.1 update for Windows 8.1 64bit will be downloaded and installed.%n%nPlease wait until the update is complete!
en.CautionXP32=The program requires PowerShell 5.1.%nOn Windows XP 32bit, the program will not be able to download updates for converting games and perform some other functions.
en.CautionVI32=The program requires PowerShell 5.1.%nOn Windows Vista 32bit, the program will not be able to download updates for converting games and perform some other functions.
en.Caution7032=An outdated version of PowerShell has been detected on your computer.%nAfter installing the program, the PowerShell 5.1 update for Windows 7 32bit will be downloaded and installed.%n%nPlease wait until the update is complete!
en.Caution8132=An outdated version of PowerShell has been detected on your computer.%nAfter installing the program, the PowerShell 5.1 update for Windows 8.1 32bit will be downloaded and installed.%n%nPlease wait until the update is complete!

de.CautionXP64=Das Programm erfordert PowerShell 5.1.%nUnter Windows XP 64bit kann das Programm keine Updates zum Konvertieren von Spielen herunterladen und einige andere Funktionen ausführen.
de.CautionVI64=Das Programm erfordert PowerShell 5.1.%nUnter Windows Vista 64bit kann das Programm keine Updates zum Konvertieren von Spielen herunterladen und einige andere Funktionen ausführen.
de.Caution7064=Auf Ihrem Computer wurde eine veraltete Version von PowerShell erkannt.%nNach der Installation des Programms wird das PowerShell 5.1-Update für Windows 7 64bit heruntergeladen und installiert.%n%nBitte warten Sie bis das Update abgeschlossen ist!
de.Caution8064=Auf Ihrem Computer wurde eine veraltete Version von PowerShell erkannt.%nNach der Installation des Programms wird das PowerShell 5.1-Update für Windows 8.0 64bit heruntergeladen und installiert.%n%nBitte warten Sie bis das Update abgeschlossen ist!
de.Caution8164=Auf Ihrem Computer wurde eine veraltete Version von PowerShell erkannt.%nNach der Installation des Programms wird das PowerShell 5.1-Update für Windows 8.1 64bit heruntergeladen und installiert.%n%nBitte warten Sie bis das Update abgeschlossen ist!
de.CautionXP32=Das Programm erfordert PowerShell 5.1.%nUnter Windows XP 32bit kann das Programm keine Updates zum Konvertieren von Spielen herunterladen und einige andere Funktionen ausführen.
de.CautionVI32=Das Programm erfordert PowerShell 5.1.%nUnter Windows Vista 32bit kann das Programm keine Updates zum Konvertieren von Spielen herunterladen und einige andere Funktionen ausführen.
de.Caution7032=Auf Ihrem Computer wurde eine veraltete Version von PowerShell erkannt.%nNach der Installation des Programms wird das PowerShell 5.1-Update für Windows 7 32bit heruntergeladen und installiert.%n%nBitte warten Sie bis das Update abgeschlossen ist!
de.Caution8132=Auf Ihrem Computer wurde eine veraltete Version von PowerShell erkannt.%nNach der Installation des Programms wird das PowerShell 5.1-Update für Windows 8.1 32bit heruntergeladen und installiert.%n%nBitte warten Sie bis das Update abgeschlossen ist!

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"

[Icons]
Name: "{group}\{#ShortName}"; Filename: "{app}\{#ExeName}"
Name: "{group}\{cm:ProgramOnTheWeb,{#ShortName}}"; Filename: "{#URL}"
Name: "{group}\{cm:UninstallProgram,{#ShortName}}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#ShortName}"; Filename: "{app}\{#ExeName}"; Tasks: desktopicon
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#ShortName}"; Filename: "{app}\{#ExeName}"; Tasks: quicklaunchicon

[Run]
Filename: "{app}\{#ExeName}"; Description: "{cm:LaunchProgram,{#StringChange(ShortName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

[_Code]
procedure LoadSkin(lpszPath: String; lpszIniFileName: String); external 'LoadSkin@files:ISSkinU.dll stdcall';
procedure UnloadSkin(); external 'UnloadSkin@files:ISSkinU.dll stdcall';
function ShowWindow(hWnd: Integer; uType: Integer): Integer; external 'ShowWindow@user32.dll stdcall';

function IsWindowsVersionOrNewer(Major, Minor: Integer): Boolean;
var
  Version: TWindowsVersion;
begin
  GetWindowsVersionEx(Version);
  Result := (Version.Major > Major) or ((Version.Major = Major) and (Version.Minor >= Minor));
end;

function IsWindowsXPOrNewer: Boolean; begin Result := IsWindowsVersionOrNewer(5, 1); end;
function IsWindowsViOrNewer: Boolean; begin Result := IsWindowsVersionOrNewer(6, 0); end;
function IsWindows70OrNewer: Boolean; begin Result := IsWindowsVersionOrNewer(6, 1); end;
function IsWindows80OrNewer: Boolean; begin Result := IsWindowsVersionOrNewer(6, 2); end;
function IsWindows81OrNewer: Boolean; begin Result := IsWindowsVersionOrNewer(6, 3); end;
function IsWindows10OrNewer: Boolean; begin Result := IsWindowsVersionOrNewer(10,0); end;

function InitializeSetup(): Boolean;
begin
  ExtractTemporaryFile('{#Skin}.cjstyles');
  LoadSkin(ExpandConstant('{tmp}\{#Skin}.cjstyles'), '');
        Result := True;
end;

// Скачиваем PowerShell 5.1 под нашу версию Windows и битность...
procedure InitializeWizard;
var
  PSVersion: String;
begin
  RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine','PowerShellVersion', PSVersion);
  if Copy(PSVersion,1,3) < '5.1' then
  begin
    if IsWin64 then
    begin
      if IsWindowsXPOrNewer and not IsWindowsViOrNewer then begin MsgBox(ExpandConstant('{cm:CautionXP64}'),mbCriticalError, MB_OK); end else
      if IsWindowsViOrNewer and not IsWindows70OrNewer then begin MsgBox(ExpandConstant('{cm:CautionVI64}'),mbCriticalError, MB_OK); end else
      if IsWindows70OrNewer and not IsWindows80OrNewer then begin MsgBox(ExpandConstant('{cm:Caution7064}'), mbInformation, MB_OK);
        idpAddFileSize('https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win7AndW2K8R2-KB3191566-x64.zip',ExpandConstant('{tmp}\Win7AndW2K8R2-KB3191566-x64.zip'),68076477); end else
      if IsWindows80OrNewer and not IsWindows81OrNewer then begin MsgBox(ExpandConstant('{cm:Caution8064}'), mbInformation, MB_OK);
        idpAddFileSize('https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/W2K12-KB3191565-x64.msu',ExpandConstant('{tmp}\W2K12-KB3191565-x64.msu'),21585220); end else
      if IsWindows81OrNewer and not IsWindows10OrNewer then begin MsgBox(ExpandConstant('{cm:Caution8164}'), mbInformation, MB_OK);
        idpAddFileSize('https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win8.1AndW2K12R2-KB3191564-x64.msu',ExpandConstant('{tmp}\Win8.1AndW2K12R2-KB3191564-x64.msu'),19878906); end;
    end
    else
    begin
      if IsWindowsXPOrNewer and not IsWindowsViOrNewer then begin MsgBox(ExpandConstant('{cm:CautionXP32}'),mbCriticalError, MB_OK); end else
      if IsWindowsViOrNewer and not IsWindows70OrNewer then begin MsgBox(ExpandConstant('{cm:CautionVI32}'),mbCriticalError, MB_OK); end else
      if IsWindows70OrNewer and not IsWindows80OrNewer then begin MsgBox(ExpandConstant('{cm:Caution7032}'), mbInformation, MB_OK);
        idpAddFileSize('https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win7-KB3191566-x86.zip',ExpandConstant('{tmp}\Win7-KB3191566-x86.zip'),44821734); end else
      if IsWindows81OrNewer and not IsWindows10OrNewer then begin MsgBox(ExpandConstant('{cm:Caution8132}'), mbInformation, MB_OK);
        idpAddFileSize('https://download.microsoft.com/download/6/F/5/6F5FF66C-6775-42B0-86C4-47D41F2DA187/Win8.1-KB3191564-x86.msu',ExpandConstant('{tmp}\Win8.1-KB3191564-x86.msu'),15231117); end;
    end;
    idpDownloadAfter(wpReady);
  end;
end;

// Во время показа страницы загрузки открываем по умолчанию скрытые детали загрузки...
procedure CurPageChanged(CurPageID: Integer);
begin
 if Assigned(IDPForm.Page) then
  begin
  if CurPageID = IDPForm.Page.ID then
    begin
    // Показать детали загрузки
    idpShowDetails(True);
    // Скрываем кнопку Подробно/Скрыть
    IDPForm.DetailsButton.Visible := False;
    end;
  end;
end;

// Распаковываем ранее скачанный ZIP/MSU и запускаем установку...
procedure CurStepChanged(CurStep: TSetupStep);
var
  ResultCode: Integer;
begin
  if CurStep = ssPostInstall then
  begin
    if IsWin64 then
    begin
      if FileExists(ExpandConstant('{tmp}\Win7AndW2K8R2-KB3191566-x64.zip')) then
      begin
        ExtractTemporaryFile('7z.exe');
        ExtractTemporaryFile('7z.dll');
        ShellExec('open',ExpandConstant('{tmp}\7z.exe'),ExpandConstant('x -y -oExtractedArchive ')+ExpandConstant('Win7AndW2K8R2-KB3191566-x64.zip'),'',SW_HIDE,ewWaitUntilTerminated,ResultCode);
        ShellExec('open',ExpandConstant('{sys}\wusa.exe'),ExpandConstant('{tmp}\ExtractedArchive\Win7AndW2K8R2-KB3191566-x64.msu'),'',SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode);
      end;
      if FileExists(ExpandConstant('{tmp}\W2K12-KB3191565-x64.msu')) then ShellExec('open',ExpandConstant('{sys}\wusa.exe'),ExpandConstant('{tmp}\W2K12-KB3191565-x64.msu'),'',SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode);
      if FileExists(ExpandConstant('{tmp}\Win8.1AndW2K12R2-KB3191564-x64.msu')) then ShellExec('open',ExpandConstant('{sys}\wusa.exe'),ExpandConstant('{tmp}\Win8.1AndW2K12R2-KB3191564-x64.msu'),'',SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode);
    end
    else
    begin
      if FileExists(ExpandConstant('{tmp}\Win7-KB3191566-x86.zip')) then
      begin
        ExtractTemporaryFile('7z32.exe');
        ExtractTemporaryFile('7z32.dll');
        ShellExec('open',ExpandConstant('{tmp}\7z32.exe'),ExpandConstant('x -y -oExtractedArchive ')+ExpandConstant('Win7-KB3191566-x86.zip'),'',SW_HIDE,ewWaitUntilTerminated,ResultCode);
        ShellExec('open',ExpandConstant('{sys}\wusa.exe'),ExpandConstant('{tmp}\ExtractedArchive\Win7-KB3191566-x86.msu'),'',SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode);
      end;
      if FileExists(ExpandConstant('{tmp}\Win8.1-KB3191564-x86.msu')) then ShellExec('open',ExpandConstant('{sys}\wusa.exe'),ExpandConstant('{tmp}\Win8.1-KB3191564-x86.msu'),'',SW_SHOWNORMAL,ewWaitUntilTerminated,ResultCode);
    end;
  end;
end;

procedure DeinitializeSetup();
begin
  ShowWindow(StrToInt(ExpandConstant('{wizardhwnd}')), 0);
  UnloadSkin();
end;


Romann_ 07-08-2019 06:26 2882967

Цитата:

Цитата Romann_
так же разрядность системы »

Нашёл необходимый код, имеем такое:
Код:


procedure UpdateInfo();
var
  DeviceName, DeviceKey: String;
begin
  ChangeText := False

  GetWindowsVersionEx(Version)

  // Операционная система:
  SystemVersionPanel.Color := clBlack
    SystemVersionPanel.Font.Color := clGreen

  DeviceKey := 'Software\Microsoft\Windows NT\CurrentVersion'
  if not UsingWinNT then StringChange(DeviceKey, 'Windows NT', 'Windows')
        RegQueryStringValue(HKLM, DeviceKey, 'ProductName', DeviceName)
  if RegQueryStringValue(HKLM, DeviceKey, 'CSDVersion', DeviceKey) then
    DeviceName := DeviceName + ' ' + DeviceKey
        StringChange(DeviceName, 'Microsoft ', '')
  SystemVersionPanel.Text := ' ' + DeviceName + ' сборка ' + IntToStr(Version.Major) + '.' + IntToStr(Version.Minor) +
                            '.' + IntToStr(Version.Build)

  if (Pos('Windows 10', SystemVersionPanel.Text) = 0) and  // Windows 10
    (Pos('Windows 7', SystemVersionPanel.Text) = 0) then  // Windows 7
    begin
      SystemVersionPanel.Color := clBlack
      SystemVersionPanel.Font.Color := clRed
      ChangeText := True
    end
...
...
...

Всё работает. Но как можно ещё проверить разрядность системы?

ErikPshat 07-08-2019 08:34 2882970

Цитата:

Цитата Romann_
Но как можно ещё проверить разрядность системы? »

Вы уже третий раз задаёте один и тот же вопрос :) Выше же я вам дал код определения разрядности системы, просто там в соответствии с разрядностью идёт скачивание PowerShell определённой версии и разрядности, а вам надо было просто подменить тот код на вывод информации на экран, либо воспроизведение каких-либо действий, по вашему желанию.
В общем вот вам чистый код по определению разрядности с подробными комментариями "//", строки с комментариями можете после осознования удалить, простая функция Inno Setup:
Код:

// До секции CODE прописываем свои текстовые сообщения, чтобы не отнимать место в коде программы в секции CODE:

[CustomMessages]
Info-text-x64=У вас разрядность системы Windows - x64.%nЭто значит, что система 64-битная.%n%nНе переживайте, всё будет хорошо.
Info-text-x86=У вас разрядность системы Windows - x86.%nЭто значит, что система 32-битная.%n%nНе переживайте, всё будет хорошо.

// То, что ниже, пишем в секции CODE:

// Если у вас x64, тогда...
if IsWin64 then
    // Выполняем в таком случае код между "begin" и "end" (между стартом и концом):
    begin
        // Выводим оповещение об разрядности x64 на экран:
        MsgBox(ExpandConstant('{cm:Info-text-x64}'), mbInformation, MB_OK);
    end

// В противном случае (т.е. если у вас не x64, а значит x86):
else
    // Выполняем в таком случае код между "begin" и "end" (между стартом и концом)
    begin
        // Выводим оповещение об разрядности x86 на экран
        MsgBox(ExpandConstant('{cm:Info-text-x86}'), mbInformation, MB_OK);
    end;



Время: 11:47.

Время: 11:47.
© OSzone.net 2001-