FAQ FAQ по Inno Setup

Shegorat

Lord of Madness
Администратор
Эта тема предназначена как сборник скриптов и примеров.
Правила в этой теме следующие:
1. Один пост - один пример.
2. Все посты оформляются в виде вопрос - ответ.
3. Для большего удобства новые посты оформляются также как уже существующие. Ниже пример формления
4. Если к вашему примеру прилагаются файлы, заливайте их во вложение.

[B][COLOR=DarkRed]В:[/COLOR][/B] Как написать простейший инсталлятор?
[B][COLOR=DarkBlue]О:[/COLOR][/B] Примерно так
[SPOILER=Код][CODE]
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
UninstallDisplayIcon={app}\MyProg.exe
Compression=lzma2
SolidCompression=yes
OutputDir=userdocs:Inno Setup Examples Output

[Files]
Source: "MyProg.exe"; DestDir: "{app}"
Source: "MyProg.chm"; DestDir: "{app}"
Source: "Readme.txt"; DestDir: "{app}"; Flags: isreadme

[Icons]
Name: "{group}\My Program"; Filename: "{app}\MyProg.exe"
[/CODE][/SPOILER]
 

Shegorat

Lord of Madness
Администратор
В: Как узнать где находится Setup.exe на CD или на жестком диске?
О: Примерно так
Код:
[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirName={pf}\MyApp

[code]
type
  SECURITY_ATTRIBUTES = record
    nLength: DWord;
    lpSecurityDescriptor: longint;
    bInheritHandle: Boolean;
  end;

const
  GENERIC_READ = $80000000;
  GENERIC_WRITE = $40000000;
  CREATE_ALWAYS = 2;

function CreateFile(lpFileName: PChar; dwDesiredAccess, dwShareMode: DWord; LPSECURITY_ATTRIBUTES: SECURITY_ATTRIBUTES; dwCreationDisposition, dwFlagsAndAttributes: DWord; hTemplateFile: THandle): THandle; external 'CreateFileA@kernel32.dll stdcall';
function CloseHandle(Handle: THandle): Boolean; external 'CloseHandle@kernel32.dll stdcall';

function ISEnvHDD(): Boolean;
var Hndl: Thandle; SA: SECURITY_ATTRIBUTES;
begin
  Result:= False;
  SA.nLength:=SizeOf(SA);
  SA.bInheritHandle:=True;
  Hndl:= CreateFile(PChar(ExpandConstant('{src}\test.tmp')), GENERIC_READ or GENERIC_WRITE, 0, SA, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  if Hndl>0 then Result:= True else Result:=False;
  CloseHandle(Hndl);
  DeleteFile(ExpandConstant('{src}\test.tmp'));
end;

function InitializeSetup(): Boolean;
begin
Result:= True;
if ISEnvHDD then begin
  MsgBox('Setup.exe Находится на HDD. Запуск невозможен', mbConfirmation, MB_OK);
  Result:=False;
end;
end;
 

Shegorat

Lord of Madness
Администратор
В: Как сделать проверку через реестр установлена программа или нет?
О: Так
Код:
[Setup]
AppName=MyApp
AppverName=MyApp
DefaultDirName={pf}\MyApp

[Registry]
Root: HKLM; Subkey: SOFTWARE\MyApp; ValueName: InstallPath; ValueType: string; ValueData: {app}; Flags: uninsdeletekey

[code]
function InitializeSetup(): Boolean;
begin
  Result:= True;
  if RegValueExists(HKLM, 'SOFTWARE\MyApp', 'InstallPath') then begin
    MsgBox('Копия данной программы уже установлена! Установка будет прекращена', mbConfirmation, MB_OK);
    Result:= False;
  end;
end;
 

Shegorat

Lord of Madness
Администратор
В: Как добавить описание к компонентам в ComponentsList?
О: Вот пример без использования различных библиотек (Требуется расширенная версия InnoSetup от ResTools)
Код:
[Setup]
AppName=My Program
AppVerName=My Program 1.5
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
ComponentsListTVStyle=true

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

[CustomMessages]
russian.ComponentsName1=Моя программа™
russian.ComponentsName2=Помощь
russian.ComponentsName2_1=Документация
russian.ComponentsName2_2=Руководство пользователя
russian.ComponentsInfoPanel1=Описание
russian.ComponentsInfoPanel2=Наведите курсор мыши на компонент, чтобы прочитать его описание.
russian.ComponentsDescription1=Устанавливается обязательно
russian.ComponentsDescription2=Помощь
russian.ComponentsDescription3=Прочитать документацию
russian.ComponentsDescription4=Прочитать руководство пользователя

[Components]
Name: readme; Description: Справка; Types: full custom;
Name: readme\en; Description: "Английская "; Types: full custom; Flags: fixed
Name: readme\ru; Description: Русская; Types: full

;*************************************************************************
Name: plugs; Description: Плагины; Types: full ; Flags: collapsed
Name: plugs\wlx; Description: Внутреннего просмотра; Types: full
Name: plugs\wcx; Description: Архиваторные; Types: full
Name: plugs\wfx; Description: Системные; Types: full
Name: plugs\wfx\CanonCam; Description: CanonCam; Types: full
Name: plugs\wfx\PluginManager; Description: PluginManager; Types: full
Name: plugs\wfx\Registry; Description: Registry; Types: full
Name: plugs\wfx\Services; Description: Services; Types: full
Name: plugs\wfx\StartupGuard; Description: StartupGuard; Types: full
Name: plugs\wdx; Description: Другие; Types: full

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

var
  Descs: array of TComponentDesc;
  Info: TNewStaticText;
  InfoCaption: TNewStaticText;
  InfoPanel: TPanel;
  Indx: Integer;

procedure ShowDescription(Sender: TObject; X, Y, Index: Integer; Area: TItemArea);
var i: Integer;
begin
  Indx:=-1;
  for i:= 0 to GetArrayLength(Descs)-1 do begin
  if (Descs[i].Index=Index) then begin Indx:=i; Break end; end;
  if (Indx >=0)and(Area=iaItem) then Info.Caption:= Descs[Indx].Description else Info.Caption:= ExpandConstant('{cm:ComponentsInfoPanel2}');
end;

procedure AddDescription(AIndex: Integer; ADescription: String);
var i, k: Integer;
begin
i:= GetArrayLength(Descs); SetArrayLength(Descs, i+1);
Descs[i].Description:= ADescription; Descs[i].Index:= AIndex-1
end;

procedure InitializeWizard();
begin
  WizardForm.TypesCombo.Visible:=False;
  WizardForm.ComponentsList.Height := ScaleY(181) - WizardForm.TypesCombo.Top;
  WizardForm.ComponentsList.Top := WizardForm.TypesCombo.Top;
  WizardForm.ComponentsList.Width := ScaleX(417);
  WizardForm.ComponentsList.OnItemMouseMove:= @ShowDescription

  InfoPanel := TPanel.Create(WizardForm);
  InfoPanel.Parent := WizardForm.SelectComponentsPage;
  InfoPanel.Caption := '';
  InfoPanel.Top := ScaleY(190);
  InfoPanel.Left := ScaleX(0);
  InfoPanel.Width := ScaleX(417);
  InfoPanel.Height := ScaleY(40);
  InfoPanel.BevelInner := bvRaised;
  InfoPanel.BevelOuter := bvLowered;
  InfoCaption := TNewStaticText.Create(WizardForm);
  InfoCaption.Parent := WizardForm.SelectComponentsPage;
  InfoCaption.Caption := ExpandConstant('{cm:ComponentsInfoPanel1}');
  InfoCaption.Left := ScaleX(7);
  InfoCaption.Top := InfoPanel.Top - ScaleY(6);
  InfoCaption.Font.Color := clActiveCaption;

  Info := TNewStaticText.Create(WizardForm);
  Info.Parent := InfoPanel;
  Info.AutoSize := False;
  Info.Left := ScaleX(6);
  Info.Width := ScaleX(403);
  Info.Top := ScaleY(12);
  Info.Height := ScaleY(24);
  Info.Caption := ExpandConstant('{cm:ComponentsInfoPanel2}');
  Info.WordWrap := true;

  AddDescription(1, 'Справка'); //первый параметр - это номер компонента, идет последовательно от начала записи компонентов
  AddDescription(2, 'Английская справка'); //Второй параметр - это собственно описание компонента
  AddDescription(3, 'Русская справка');
  AddDescription(4, 'Плагины');
  AddDescription(5, 'Внутреннего просмотра');
  AddDescription(6, 'Архиваторные');
  AddDescription(7, 'Системные');
  AddDescription(8, 'CanonCam');
  AddDescription(9, 'PluginManager');
  AddDescription(10, 'Registry');
  AddDescription(11, 'Services');
  AddDescription(12, 'StartupGuard');
  AddDescription(13, 'Другие');

end;
 

Shegorat

Lord of Madness
Администратор
В: Как внести значение в INI-файл в зависимости от выбранного чекбокса
О: Так
Код:
[Setup]
AppName=My Program
AppVerName=My Program 1.5
AppPublisher=My Company, Inc.
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
OutputBaseFilename=setup
Compression=lzma
SolidCompression=yes

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

[Run]
Filename: "{app}\MyProg"; Description: "{cm:LaunchProgram, MyProg}"; Flags: nowait postinstall skipifsilent

[Code]
var
IniCheckBox: TCheckBox;

procedure InitializeWizard();
begin
  IniCheckBox:= TCheckBox.Create(WizardForm);
  IniCheckBox.Left:= WizardForm.RunList.Left + 4;
  IniCheckBox.Top:= WizardForm.RunList.Top + 10;
  IniCheckBox.Width:= WizardForm.RunList.Width;
  IniCheckBox.Height:= 14
  IniCheckBox.Caption:=' Изменить язык интерфейса на русский';
  IniCheckBox.Parent:= WizardForm.FinishedPage;
end;

procedure DeinitializeSetup();
begin
  if WizardForm.CurPageID = WpFinished then
  begin
    if IniCheckBox.Checked then
      SetIniString('Setting','Language', 'RU',ExpandConstant('{app}\Language.ini'))     //Секция, подключ, значение, файл Ini
    else
      SetIniString('Setting','Language', 'EN',ExpandConstant('{app}\Language.ini'))
  end;
end;
 

Shegorat

Lord of Madness
Администратор
В: Как удалить кнопки свернуть, развернуть из окна инсталлятора?
О: Так
Код:
[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirname={pf}\MyApp

[code]
const
  GWL_STYLE = -16;

  WS_MINIMIZEBOX = $20000;
  WS_MAXIMIZEBOX = $10000;
 
function SetWindowLong(Wnd: HWnd; Index: Integer; NewLong: Longint): Longint; external 'SetWindowLongA@user32.dll stdcall';
function GetWindowLong(hWnd: HWND; nIndex: Integer): Longint; external 'GetWindowLongA@user32.dll stdcall';

procedure initializeWizard();
begin
  SetWindowLong(WizardForm.handle, GWL_STYLE, GetWindowLong(WizardForm.handle, GWL_STYLE)and(not WS_MINIMIZEBOX)and(not WS_MAXIMIZEBOX));
end;
 

Shegorat

Lord of Madness
Администратор
В: Как динамически создать батник?
О: Примерно так
Код:
[Setup]
AppName=MyApp
AppVername=MyApp
DefaultDirName={pf}\MyApp
DisableWelcomePage=True

[code]
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
  Confirm:= False;
  Cancel:= True;
end;

function InitializeSetup(): Boolean;
var List: TStringList; src, dest, bat: string; res: Integer;
begin
  src:= ExpandConstant('{src}');
  BrowseForFolder('Choose destination dir', dest, True);
  bat:= ExpandConstant('{userappdata}\exec.bat');
  List:= TStringList.Create;
  List.Add('echo off');
  List.Add('set src='+src);
  List.Add('set dest='+dest);
  List.Add('@echo SourceDir: "%src%"');
  List.Add('@echo DestinationDir: "%dest%"');
  List.Add('pause');
  List.Add('del "'+bat+'"');
  List.Add('pause');
  List.SaveToFile(bat);
  List.Free;
  Exec(bat, '', '', SW_SHOW, ewNoWait, Res);
end;
 

Shegorat

Lord of Madness
Администратор
В: Как добавить проверку свободного/необходимого места на жестком диске?
О: Так
Код:
#define NeedSize 4380
#define NeedInstallSize 7890

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

[code]
var
  TotalSpaceLabel, FreeSpaceLabel, NeedSpacelabel, InstallSpaceLabel: TLabel;
  FreeMB, TotalMB: Cardinal;

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)+' Мб' else
    if Float/1024 < 1024 then Result:= NumToStr(Float/1024)+' Гб' else
      Result:= NumToStr(Float/(1024*1024))+' Тб';
end;

procedure DirEditOnChange(Sender: TObject);
var Drive: String;
begin
  Drive:= ExtractFileDrive(WizardForm.DirEdit.Text);
  GetSpaceOnDisk(Drive, True, FreeMB, TotalMB);
  TotalSpaceLabel.Caption:= 'Всего места на диске: '+MbOrTb(TotalMB);
  FreeSpaceLabel.Caption:= 'Доступно места на диске: '+MbOrTb(FreeMB)+' ('+IntToStr(round(FreeMB*100/TotalMB))+'%)';
  InstallSpacelabel.Caption:= 'Требуется места для установки: '+MbOrTb({#NeedInstallSize});
  NeedSpaceLabel.Caption:= 'Требуется места на диске: '+MbOrTb({#NeedSize});
  WizardForm.NextButton.Enabled:= (FreeMB>{#NeedInstallSize})and(FreeMB>{#NeedSize});
end;

procedure InitializeWizard();
begin
  TotalSpaceLabel:= TLabel.Create(WizardForm);
  TotalSpaceLabel.AutoSize:= False;
  TotalSpaceLabel.SetBounds(0, 120, 300, 20);
  TotalSpaceLabel.Parent:= WizardForm.SelectDirpage;

  FreeSpaceLabel:= TLabel.Create(WizardForm);
  FreeSpaceLabel.AutoSize:= False;
  FreeSpaceLabel.SetBounds(0, 140, 300, 20);
  FreeSpaceLabel.Parent:= WizardForm.SelectDirpage;

  InstallSpacelabel:= TLabel.Create(WizardForm);
  InstallSpacelabel.AutoSize:= False;
  InstallSpacelabel.SetBounds(0, 160, 300, 20);
  InstallSpacelabel.Parent:= WizardForm.SelectDirpage;

  NeedSpaceLabel:= TLabel.Create(WizardForm);
  NeedSpaceLabel.AutoSize:= False;
  NeedSpaceLabel.SetBounds(0, 180, 300, 20);
  NeedSpaceLabel.Parent:= WizardForm.SelectDirpage;

  WizardForm.DirEdit.OnChange:=@DirEditOnChange;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID=wpSelectDir then begin
    DirEditOnChange(nil)
  end;
end;
 

Shegorat

Lord of Madness
Администратор
В: Как получить определенное значение из INI-файла?
О: Так. Здесь 2 примера
Код:
[Setup]
AppName={code:GetAppName}
AppVerName=My Program 1.5
AppPublisher=My Company, Inc.
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
OutputBaseFilename=setup

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

[code]
var
  IniValue, IniFile: String;

//Для получения значения в другую секцию
function GetAppName(IniFile: String): String;
begin
  IniFile:='G:\Name.ini'
  IniValue:= GetIniString('ModuleName', 'AppName', '', IniFile);
  Result := IniValue
end;

//Просто получение значения
procedure InitializeWizard();
begin
  IniFile:='G:\Name.ini'
  IniValue:= GetIniString('ModuleName'{Название секции}, 'AppName'{Подключ}, '', IniFile{Ini файл});
  WizardForm.WelcomeLabel2.Caption := IniValue;
end;
 

Shegorat

Lord of Madness
Администратор
Q: Как растянуть картинку на первой и последней странице?
A: Примерно так
Код:
[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirname={pf}\MyApp

[code]
var
  WelcomeLabel1, WelcomeLabel2, FinishedLabel, FinishedHeadingLabel: TLabel;
  PageNameLabel, PageDescriptionLabel: TLabel;

procedure InitializeWizard();
begin
  WizardForm.WizardBitmapImage.Width := ScaleX(497);
  WizardForm.WizardBitmapImage2.Width := ScaleX(497);

  { WelcomeLabel1 }
  WizardForm.WelcomeLabel1.Hide;
  WelcomeLabel1 := TLabel.Create(WizardForm);
  with WizardForm.WelcomeLabel1 do
  begin
    WelcomeLabel1.Parent := Parent;
    WelcomeLabel1.SetBounds(Left, Top, Width, Height);
    WelcomeLabel1.AutoSize := AutoSize;
    WelcomeLabel1.Font := Font;
    WelcomeLabel1.Font.Color := clWhite;
    WelcomeLabel1.Transparent := True;
    WelcomeLabel1.WordWrap := WordWrap;
    WelcomeLabel1.Caption := Caption;
  end;

  { WelcomeLabel2 }
  WizardForm.WelcomeLabel2.Hide;
  WelcomeLabel2 := TLabel.Create(WizardForm);
  with WizardForm.WelcomeLabel2 do
  begin
    WelcomeLabel2.Parent := Parent;
    WelcomeLabel2.SetBounds(Left, Top, Width, Height);
    WelcomeLabel2.AutoSize := AutoSize;
    WelcomeLabel2.Font := Font;
    WelcomeLabel2.Font.Color := clWhite;
    WelcomeLabel2.Transparent := True;
    WelcomeLabel2.WordWrap := WordWrap;
    WelcomeLabel2.Caption := Caption;
  end;

  WizardForm.WizardSmallBitmapImage.SetBounds(ScaleX(0), ScaleY(0), WizardForm.MainPanel.Width, WizardForm.MainPanel.Height);

  { PageNameLabel }
  WizardForm.PageNameLabel.Hide;
  PageNameLabel := TLabel.Create(WizardForm);
  with WizardForm.PageNameLabel do
  begin
    PageNameLabel.Parent := Parent;
    PageNameLabel.SetBounds(Left, Top, Width, Height);
    PageNameLabel.AutoSize := AutoSize;
    PageNameLabel.Font := Font;
    PageNameLabel.Font.Color := clWhite;
    PageNameLabel.Transparent := True;
    PageNameLabel.WordWrap := WordWrap;
  end;

  { PageDescriptionLabel }
  WizardForm.PageDescriptionLabel.Hide;
  PageDescriptionLabel:= TLabel.Create(WizardForm);
  with WizardForm.PageDescriptionLabel do
  begin
    PageDescriptionLabel.Parent := Parent;
    PageDescriptionLabel.SetBounds(Left, Top, Width, Height);
    PageDescriptionLabel.AutoSize := AutoSize;
    PageDescriptionLabel.Font := Font;
    PageDescriptionLabel.Font.Color := clWhite;
    PageDescriptionLabel.Transparent := True;
    PageDescriptionLabel.WordWrap := WordWrap;
  end;

  { FinishedHeadingLabel }
  WizardForm.FinishedHeadingLabel.Hide;
  FinishedHeadingLabel := TLabel.Create(WizardForm);
  with WizardForm.FinishedHeadingLabel do
  begin
    FinishedHeadingLabel.Parent := Parent;
    FinishedHeadingLabel.SetBounds(Left, Top, Width, Height);
    FinishedHeadingLabel.AutoSize := AutoSize;
    FinishedHeadingLabel.Font := Font;
    FinishedHeadingLabel.Font.Color := clWhite;
    FinishedHeadingLabel.Transparent := True;
    FinishedHeadingLabel.WordWrap := WordWrap;
    FinishedHeadingLabel.Caption := Caption;
  end;

  { FinishedLabel }
  WizardForm.FinishedLabel.Hide;
  FinishedLabel := TLabel.Create(WizardForm);
  with WizardForm.FinishedLabel do
  begin
    FinishedLabel.Parent := Parent;
    FinishedLabel.SetBounds(Left, Top, Width, Height);
    FinishedLabel.AutoSize := AutoSize;
    FinishedLabel.Font := Font;
    FinishedLabel.Font.Color := clWhite;
    FinishedLabel.Transparent := True;
    FinishedLabel.WordWrap := WordWrap;
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  PageNameLabel.Caption := WizardForm.PageNameLabel.Caption;
  PageDescriptionLabel.Caption := WizardForm.PageDescriptionLabel.Caption;
  FinishedLabel.Caption := WizardForm.FinishedLabel.Caption;
end;
 

Shegorat

Lord of Madness
Администратор
В: Как добавить проценты установки на страницу инсталляции?
О: Так
Код:
[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirName={pf}\MyApp

[Files]
Source: compiler:innocallback.dll; Flags: dontcopy
Source: {win}\Help\*; DestDir: {app}; Flags: external recursesubdirs

[code]
type
    TTimerProc = procedure(HandleW, Msg, idEvent, TimeSys: LongWord);

var
  PercentsTimer: LongWord;
  PercentsLabel: TLabel;
 
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';

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;

procedure DeinitializeSetup();
begin
    KillTimer(0, PercentsTimer);
end;

procedure InitializeWizard();
begin
    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;

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssInstall then
  begin
  PercentsTimer:= SetTimer(0, 0, 100, WrapTimerProc(@PercentsProc, 4));
  end;
end;
 

Shegorat

Lord of Madness
Администратор
В: Как добавить TMemo на страницу установки, в котором будут отображаться извлекаемые файлы?
О: Примерно так
Код:
[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirName={pf}\MyApp

[Files]
Source: E:\Program\Inno Setup 5.3.8 Ext\*; DestDir: {app}; BeforeInstall: AddToMemo; Flags: nocompression recursesubdirs createallsubdirs

[Code]
var
  FilesMemo: TNewMemo;

procedure AddToMemo();
var
  AFile: String;
begin
  AFile := ExpandConstant(CurrentFilename);
  if ExtractFileExt(AFile) = '' then
    FilesMemo.Lines.Add('CreateFolder: ' + RemoveBackslash(AFile))
  else
    FilesMemo.Lines.Add('Extract: ' + AFile);
end;

procedure InitializeWizard();
begin
  FilesMemo := TNewMemo.Create(WizardForm);
  FilesMemo.SetBounds(ScaleX(0), ScaleY(80), ScaleX(418), ScaleY(120));
  FilesMemo.WordWrap := False;
  FilesMemo.Parent := WizardForm.InstallingPage;
  FilesMemo.ScrollBars := ssVertical;
  FilesMemo.ReadOnly := True;
  FilesMemo.Clear;
end;
 

Shegorat

Lord of Madness
Администратор
В: Как сделать проверку на количество извлеченных файлов?
О: Так
Код:
#define CountFiles "3"

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

[code]
function GetFilesCount(Dir: String): Integer;
var
FSR: TFindRec;
FindResult: Boolean;
begin
  try
    FindResult:= FindFirst(AddBackslash(Dir)+'*.*', FSR);
    repeat
      if ((FSR.Attributes and FILE_ATTRIBUTE_DIRECTORY) = 0) then begin
        Result:= Result+1;
      end else
      if ((FSR.Attributes and FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY)and((FSR.Name<>'.')and(FSR.Name<>'..')) then begin
        Result:=GetFilesCount(AddBackslash(Dir)+FSR.Name);
      end;
      FindResult:= FindNext(FSR);
    until not FindResult
  finally
    FindClose(FSR);
  end;
end;

procedure CurStepChanged(CurStep: TSetupStep);
var Res: Integer;
begin
if CurStep = ssPostInstall then begin
  If GetFilesCount(ExpandConstant('{app}')) <{#CountFiles} then
    If MsgBox(ExpandConstant('{cm:Error}'), mbCriticalError , MB_OK) = IDOK then
      Exec(ExpandConstant('{uninstallexe}'), '/Silent', '', SW_SHOW, ewWaitUntilterminated, Res)
end;
end;

[CustomMessages]
Error=Во время распаковки были распакованы не все файлы!
 

Shegorat

Lord of Madness
Администратор
В: Как добавить свой шрифт в инсталлятор?
О: Так
Код:
#define Font "Edisson.ttf"
#define FontName "Edisson"

[Files]
Source: {#Font}; Flags: dontcopy

[code]
#ifdef UNICODE
    #define A "W"
#else
    #define A "A"
#endif

const
    FR_PRIVATE = $10;

function AddFontResource(lpszFilename: String; fl, pdv: DWORD): Integer; external 'AddFontResourceEx{#A}@gdi32.dll stdcall';
function RemoveFontResource(lpFileName: String; fl, pdv: DWORD): BOOL; external 'RemoveFontResourceEx{#A}@gdi32.dll stdcall';

procedure InitializeWizard();
begin
    if not FontExists('{#FontName}') then
    begin
        ExtractTemporaryFile('{#Font}');
        AddFontResource(ExpandConstant('{tmp}\{#Font}'), FR_PRIVATE, 0);
    end;
    WizardForm.Font.Name := '{#FontName}';
end;

procedure DeinitializeSetup();
begin
    RemoveFontResource(ExpandConstant('{tmp}\{#Font}'), FR_PRIVATE, 0);
    WizardForm.Free;
end;
 

Shegorat

Lord of Madness
Администратор
В: Как "прицепить" дополнительную форму к окну инсталлятора, чтобы при перемещении дополнительная форма двигалась вместе с окном инсталлятора?
О: Примерно так
Код:
[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirname={pf}\MyApp

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

[code]
const
  WM_MOVE = $3;

  GWL_WNDPROC = -4;
 
type
  TCallbackProc = function(h:hWnd;Msg,wParam,lParam:Longint):Longint;
 
function SetWindowLong(Wnd: HWnd; Index: Integer; NewLong: Longint): Longint; external 'SetWindowLongA@user32.dll stdcall';
function WndProcCallBack(P:TCallbackProc;ParamCount:integer):LongWord; external 'wrapcallback@files:innocallback.dll stdcall';
function CallWindowProc(lpPrevWndFunc: Longint; hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint; external 'CallWindowProcA@user32.dll stdcall';
function SetWindowPos(hWnd: HWND; hWndInsertAfter: HWND; X, Y, cx, cy: Integer; uFlags: UINT): BOOL; external 'SetWindowPos@user32.dll stdcall';

var
Form1: TForm;
OldProc: Longint;

function MyProc(h: HWND; Msg, wParam, lParam: longint): Longint;
begin
  if Msg=WM_MOVE then SetWindowPos(Form1.Handle, 0, WizardForm.Left+WizardForm.Width+5, WizardForm.Top, 0, 0, $415);
  Result:= CallWindowProc(OldProc, h, Msg, wParam, lParam);
end;

procedure InitializeWizard();
begin
  Form1:= TForm.Create(MainForm);
  Form1.SetBounds(WizardForm.Left+WizardForm.Width+5, WizardForm.Top, 100, 358);
  Form1.BorderStyle:= bsSingle;
  Form1.Show;
 
  OldProc:= SetWindowLong(WizardForm.Handle, GWL_WNDPROC, WndProcCallBack(@MyProc, 4));
end;

procedure DeinitializeSetup();
begin
  SetWindowlong(WizardForm.Handle, GWL_WNDPROC, OldProc);
end;
 

Shegorat

Lord of Madness
Администратор
В: Я использовал предыдущий пример Как теперь сделать чтобы при перемещении доп. формы двигалась и основная форма?
О: Так, данный пример на основе предыдущего примера
Код:
[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirname={pf}\MyApp

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

[code]
type
  TCallbackProc = function(h:hWnd;Msg,wParam,lParam:Longint):Longint;

const
  WM_MOVE = $3;
  WM_ACTIVATE = $6;
  WM_CLOSE = $10;
  WM_NCACTIVATE = $86;
 
  GWL_WNDPROC = -4;
 
function SetWindowLong(Wnd: HWnd; Index: Integer; NewLong: Longint): Longint; external 'SetWindowLongA@user32.dll stdcall';
function WndProcCallBack(P:TCallbackProc;ParamCount:integer):LongWord; external 'wrapcallback@files:innocallback.dll stdcall';
function CallWindowProc(lpPrevWndFunc: Longint; hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint; external 'CallWindowProcA@user32.dll stdcall';
function SetWindowPos(hWnd: HWND; hWndInsertAfter: HWND; X, Y, cx, cy: Integer; uFlags: UINT): BOOL; external 'SetWindowPos@user32.dll stdcall';

var
Form1: TForm;
OldProc, OldProc1: Longint;

function MyProc(h: HWND; Msg, wParam, lParam: longint): Longint;
begin
  if Msg=WM_MOVE then SetWindowPos(Form1.Handle, 0, WizardForm.Left+WizardForm.Width+5, WizardForm.Top, 0, 0, $415);
  Result:= CallWindowProc(OldProc, h, Msg, wParam, lParam);
  if Msg=WM_ACTIVATE then SendMessage(Form1.Handle, WM_NCACTIVATE, 1, 0);
end;

function MyProc1(h: HWND; Msg, wParam, lParam: longint): Longint;
begin
  if Msg=WM_MOVE then begin
    SetWindowPos(WizardForm.Handle, 0, Form1.Left-(WizardForm.Width+5), Form1.Top, 0, 0, $415);
  end;
  if Msg=WM_CLOSE then begin
    SendMessage(WizardForm.handle, WM_CLOSE, 0, 0);
    Exit;
  end;
  Result:= CallWindowProc(OldProc1, h, Msg, wParam, lParam);
  if Msg=WM_ACTIVATE then SendMessage(WizardForm.Handle, WM_NCACTIVATE, 1, 0);
end;


procedure InitializeWizard();
begin
  Form1:= TForm.Create(MainForm);
  Form1.SetBounds(WizardForm.Left+WizardForm.Width+5, WizardForm.Top, 160, WizardForm.Height);
  Form1.BorderStyle:= bsSingle;
  Form1.Show;

  OldProc:= SetWindowLong(WizardForm.Handle, GWL_WNDPROC, WndProcCallBack(@MyProc, 4));
  OldProc1:= SetWindowLong(Form1.Handle, GWL_WNDPROC, WndProcCallBack(@MyProc1, 4))
end;

procedure DeinitializeSetup();
begin
  SetWindowlong(WizardForm.Handle, GWL_WNDPROC, OldProc);
  SetWindowlong(Form1.Handle, GWL_WNDPROC, OldProc1);
end;
 

Shegorat

Lord of Madness
Администратор
В: Как разрешить установку продукта только на диск с файловой системой NTFS?
О: Так
Код:
[Setup]
AppName=MyApp
AppVername=MyApp
DefaultDirName={pf}\MyApp

[code]
#ifdef UNICODE
  #define A "W"
#else
  #define A "A"
#endif

function GetVolumeInformation(PathName, VolumeName: PAnsiChar; VolumeNameSize, VolumeSerialNumber, MaxComponentLength, FileSystemFlags: Longint; FileSystemName: PAnsiChar; FileSystemNameSize: Longint): Longint;
  external 'GetVolumeInformation{#A}@kernel32.dll stdcall';

function NextButtonClick(CurPageID: Integer): Boolean;
var VolumeName, FileSystemName: String;
    VolumeSerialNo, MaxComponentLength, FileSystemFlags: Longint;
begin
  Result := True;
  if CurPageID = wpSelectDir then begin
    FileSystemName:= StringOfChar(' ', 32); VolumeName:= StringOfChar(' ', 256);
    GetVolumeInformation(PAnsiChar(ExtractFileDrive(WizardForm.DirEdit.Text)+'\'), PAnsiChar(VolumeName), 255, VolumeSerialNo, MaxComponentLength, FileSystemFlags, PAnsiChar(FileSystemName), 31);
    if Pos('NTFS', FileSystemName)=0 then begin
      MsgBox('Установка данного продукта возможна только на диск с файловой системой NTFS.'#13'Пожалуйста, измените путь установки.', mbError, mb_Ok);
      Result := False ;
    end;
  end;
end;
 

moonlight

Новичок
Проверенный
В: Как запретить установку в папку с русскими буквами?
О: Вот так: (Самый быстрый вариант от VoLT)
Код:
[Setup]
AppName=MyApp
AppVername=MyApp
DefaultDirName={pf}\MyApp

[Code]
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;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  Result := True;
  if CurPageID = wpSelectDir then
  if not(IsAnsi(WizardForm.DirEdit.Text)) then
  begin
    MsgBox( 'В пути установки присуствуют русские символы'#13#13'Пожалуйста, повторите ввод.', mbError, mb_Ok);
    Result := False;
  end;
end;
 

sergey3695

Ветеран
Модератор
В: Как установить приоритет для инсталлятора?
О: Так
Код:
[Setup]
AppName=MyApp
AppVername=MyApp
DefaultDirName={pf}\MyApp

[code]

const
  NORMAL_PRIORITY_CLASS           = $00000020;
  IDLE_PRIORITY_CLASS             = $00000040;
  HIGH_PRIORITY_CLASS             = $00000080;
  REALTIME_PRIORITY_CLASS         = $00000100;

function SetPriorityClass(hProcess: THandle; dwPriorityClass: DWORD): BOOL;
  external 'SetPriorityClass@kernel32';

function GetCurrentProcess: THandle;
  external 'GetCurrentProcess@kernel32';

procedure InitializeWizard();
begin
  SetPriorityClass(GetCurrentProcess, IDLE_PRIORITY_CLASS);     //установка приоритета для инсталлятора.
end;
 

zxcvvcxz

Мимокрокодил
В: Меняем стандартный вид папки на иконку установленной программы как в меню "Пуск" так и в "пути" установки.
image.png
О: Архив со скриптом и необходимыми файлами во вложении.
 

Вложения

Сверху