Написание скрипта для инсталлятора

  • Автор темы Автор темы Kindly
  • Дата начала Дата начала
Статус
Закрыто для дальнейших ответов.
Составил скрипт в котором компоненты выбираются не на странице wpSelectComponents, а на созданной мной странице. Но с таким скриптом файлы находятся не в инсталляторе, а открыто лежат на диске и если их много, то и скрипт будет просто огромный. Как сделать, чтобы исключить из скрипта функцию CurStepChanged и устанавливаемые языковые файлы находились бы в секции [Files] и запаковывались в инсталлятор, как это сделано при выборе компонентов. При выборе 1-й опции, в папку {app} распаковывались бы только файлы русской версии, а при выборе второй - файлы английской версии.

Код:
[Code]
var
LangPage: TInputOptionWizardPage;
ResultCode: Boolean;

procedure InitializeWizard();
begin
 LangPage:=CreateInputOptionPage(wpWelcome, 'Выберите версию программы', 'Какая версия программы должна быть установлена?', 'Программа установит следующую версию "MyProgram" на ваш компьютер.' #13#10#13#10 'Нажмите «Далее», чтобы продолжить. Для выбора версии программы выберите один из следующих пунктов:', True, False);
 LangPage.Add('Русская версия');
 LangPage.Add('Английская версия');
 LangPage.Values[0]:=True;
 LangPage.Values[1]:=False;
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep=ssPostInstall then
begin
 If LangPage.Values[0]=True then
 begin
  If FileExists(ExpandConstant('{src}')+'\Rus\file.txt') then
    begin
    ResultCode:=True;
    FileCopy(ExpandConstant('{src}')+'\Rus\file.txt', ExpandConstant('{app}')+'\file.txt', False);
    end else begin
    ResultCode:=False;
    end
  end
 If LangPage.Values[1]=True then
 begin
  If FileExists(ExpandConstant('{src}')+'\Eng\file.txt') then
    begin
    ResultCode:=True;
    FileCopy(ExpandConstant('{src}')+'\Eng\file.txt', ExpandConstant('{app}')+'\file.txt', False);
    end else begin
    ResultCode:=False;
    end
  end
end
end;

[Files]
;Файлов русской и английской версии в этой секции нет.

И еще вопрос: можно-ли сделать, чтобы вместо WizardSmallBitmapImage отобаражалась иконка инсталлятора, аналогично тому, как это сделано в деинсталляторе.
И последний вопрос (не про Inno Setup) - что вообще значит приставка Guest_, появившаяся перед моим ником.
 
очень захотелось "убить" MessageBox, предупреждающий об удалении файлов перед деинсталляцией, а именно "Are you sure you want to completely remove %1 and all of its components?"... Как сделать так, чтобы подтвержения на удаление не требовалось (соответственно и окно требования подтвержения не появлялось)?

Во время принятия душа меня осенило! Конечно же есть такая возможность. Достаточно вспомнить, если кто делал инсталляторы в NSIS, то там нет готового деинсталлятора как в Inno Setup и скрипт для Uninstall.exe пишется с нуля с подробным перечислением его функций. Поэтому в деинсталлятор можно запихнуть страницу приветствия, лицензионное соглашение и т.д. А что если попробовать написать инсталлятор в Inno Setup, коорый бы при запуске не устанавливал, а удалял файлы, также подробно перечислить в нем (в секции InstallDelete или Code), что ему следует удалить и кинуть его в папку с программой.
Кстати, я видел лицензионные американские игры - хотя бы к примеру Diablo 2. В них реализован как раз такой принцип: программу-инсталлятор и программу-деинсталлятор они пишут не в редакторах, а сами (хотя бы на С++).

Вот примерно такой скрипт для setup.exe:

Код:
[Setup]
AppName=MyProgram
AppVerName=MyProgram
Compression=lzma/max
DefaultDirName={pf}\MyProgram
Uninstallable=no

[Files]
; Готовый-файл деинсталлятор:
Source: "Uninstall.exe"; DestDir: "{app}"; Flags: ignoreversion overwritereadonly

[Registry]
; Также сюда можно добавить многие другие значения
Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\MyProgram"; ValueType: string; ValueName: "DisplayIcon"; ValueData: "{app}\MyProgram.exe"
Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\MyProgram"; ValueType: string; ValueName: "DisplayName"; ValueData: "MyProgram"
Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\MyProgram"; ValueType: dword; ValueName: "NoModify"; ValueData: "1"
Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\MyProgram"; ValueType: dword; ValueName: "NoRepair"; ValueData: "1"
Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\MyProgram"; ValueType: string; ValueName: "UninstallString"; ValueData: "{app}\Uninstall.exe"

Когда сам обробую свою теорию, проверю, чтобы все идеально работало, то выложу скрипт для Uninstall.exe.
 
Как сделать, чтобы исключить из скрипта функцию CurStepChanged и устанавливаемые языковые файлы находились бы в секции [Files] и запаковывались в инсталлятор, как это сделано при выборе компонентов. При выборе 1-й опции, в папку {app} распаковывались бы только файлы русской версии, а при выборе второй - файлы английской версии.

Хм, Snake, зачем это надо - установка по отдельности, уже проще два инсталлера сделать. Как я понял, необходимо включить все файлы в инсталлятор, так? А затем, чтобы при выборе желаемой версии устанавливались соответствующие файлы. Я в таких случаях делаю очень просто:

[Files]
Components: rus; Source: "C:\Rus\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs

;Кнопки переключателя (1-ый способ)
[Components]
Name: "eng"; Description: "Английская версия"; Flags: exclusive
Name: "rus"; Description: "Русская версия"; Flags: exclusive

[Types]
Name: "custom"; Description: "Выборочная установка"; Flags: iscustom


;Выпадающий список (2-ой способ, секция [Files] аналогична)
[Components]
Name: "eng"; Description: "Английская версия"; Types: eng
Name: "rus"; Description: "Русская версия"; Types: rus

[Types]
Name: "rus"; Description: "Русская версия"
Name: "eng"; Description: "Английская версия"

Отмечаем "Английская версия" - устанавливается английская, отмечаем "Русская версия" - устанавливаются русифицированные файлы поверх английских, по любому требуемый эффект гарантирован.
 
Хм, Snake, зачем это надо - установка по отдельности, уже проще два инсталлера сделать.

Просто я делал инсталлятор с импортом фуккции из user32.dll и созданием рисунка на MainForm. И с таким скриптом выбираемые копноненты и тип установки не отображаются - на странице просто пустые поля. Из-за чего такой глюк я не знаю.
 
Дошло, как сделать выбор языка программы через RadioButton. Вот скрипт:

Код:
[Setup]
AppName=Need for Speed Underground
DefaultDirName={pf}\Electronic Arts\NfS Underground

[Code]
var
RussianBtn, EnglishBtn: TRadioButton;
ResultCode: Boolean;

procedure CreateTheWizardPages;
var
LangPage: TWizardPage;
begin
LangPage:=CreateCustomPage(wpWelcome, 'Выберите версию программы', 'Какая версия программы должна быть установлена?');
 RussianBtn:=TRadioButton.Create(LangPage);
 RussianBtn.Top:=ScaleY(30);
 RussianBtn.Width:=LangPage.SurfaceWidth;
 RussianBtn.Height:=ScaleY(17);
 RussianBtn.Caption:='Русская версия';
 RussianBtn.Checked:=GetPreviousData('NfSRussian', '1') = '1';
 RussianBtn.Parent:=LangPage.Surface;

 EnglishBtn:=TRadioButton.Create(LangPage);
 EnglishBtn.Top:=RussianBtn.Top + ScaleY(30);
 EnglishBtn.Width:=LangPage.SurfaceWidth;
 EnglishBtn.Height:=ScaleY(17);
 EnglishBtn.Caption:='Английская версия';
 EnglishBtn.Checked:=GetPreviousData('NsSEnglish', '0') = '1';
 EnglishBtn.Parent:=LangPage.Surface;
end;

procedure InitializeWizard();
begin
CreateTheWizardPages;
end;

procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
SetPreviousData(PreviousDataKey, 'NfSRussian', IntToStr(Ord(RussianBtn.Checked)));
SetPreviousData(PreviousDataKey, 'NsSEnglish', IntToStr(Ord(EnglishBtn.Checked)));
end;

function Russian: Boolean;
begin
Result:=RussianBtn.Checked;
end;

function English: Boolean;
begin
Result:=EnglishBtn.Checked;
end;

[Files]
Source: "file.lng"; DestDir: "{app}\Languages"; Check: Russian; Flags: ignoreversion overwritereadonly
Source: "file.lng"; DestDir: "{app}\Languages"; Check: English; Flags: ignoreversion overwritereadonly
 
Подскажите пожалуйста, как можно прописать в реестор примерно такую строку: Root: HKLM; Subkey: "Software\game"; ValueType: String; ValueName: Product GUID; ValueData: "{782DDB70-3DF4-4366-00BF-E3767BCD173B}"; Дело в том что в таком виде выдаётся ошибка, из-за того в фигурных скобках указываются константы, и как же мне прописать в реестор строку с фигурными скобками ?.
 
чё-то я не вовремя написал, может пригодиться:
вообщето есть сырцы . Do you speak English?


Между прочим на Си.
 
Для Expeditor:
Если необходимо ввести значение с фигурными скобками, то нужно писать вначале две фиг. скобки. Тогда значение не будет восприниматься как константа.

Код:
[Registry]
Root: HKLM; Subkey: "Software\game"; ValueType: String; ValueName: Product GUID; ValueData: "{{782DDB70-3DF4-4366-00BF-E3767BCD173B}"
 
Вопрос по реестру:
Например, чтобы зарегистрировать "одним махом" TYBELIB нужно поставить флаг "regtybelib", но вот как можно было бы "выдрать" все необходимые регистрационные данные из *.OCX, вызвав, может быть какую-нибудь функцию. Например, я все время вычисляю программкой какие данные вносятся в реестр при регистрации компонентов, и затем вручную все пишу в скрипт. Если заглянуть в сам компонент, можно также увидеть секцию ресурсов с находящимися регистрационными данными. Вот к примеру в нем прописаны следующие данные:
HKLM\SOFTWARE\Classes\CLSID\{23233-4244-43434-343434434-34354}
HKLM\SOFTWARE\Classes\nmnm.activator.1
и т.д.
Доступные флаги не могут выдрать данную информацию из ACTIVE.X компонента, или я конкретно невнимателен.
Так возможен ли вариант полной регистрации активного компонента, вызывая необходимую функцию из системных библиотек?
 
Guest_Snake_*
Огромное спасибо, очень помог!!!
С новым годом !!!
 
Раньше было как-то... Хочу проиграть трекерную музу при запуске инсталлятора Inno Setup. Реально, поддерживаются два звуковых формата, которые проигрываются через системную winmm.dll - это wave и mid. Например, чтобы проигрывать повторно wave файл, следует дописать в скрипте следующее:

[Files]
Source: "C:\sound.wav"; DestDir: "{tmp}"; Flags: dontcopy

Код:
function sndPlaySound(lpszSoundName: string; uFlags: cardinal):integer;
external 'sndPlaySoundA@winmm.dll stdcall';

procedure InitializeWizard();
begin
ExtractTemporaryFile(ExpandConstant('sound.wav'));
sndPlaySound(ExpandConstant('{tmp}\sound.wav'), $0001 or $0008);
end;

Всего-то.
Вот dll с примерами для проигрывания трекерной музыки:
[url="un4seen.com/files/bassmod20.zip"]http://un4seen.com/files/bassmod20.zip[/url]
Ну вот я и не знаю, как правильно расписать эти строки, плюс как правильно указать параметры для зацикленного воспроизведения непосредственно при вызове функции для проигрывания. Подскажете?
 
Попробуй поизменять скрипт. У меня что-то не очень получилось:

Код:
[Code]
#ifdef ISSI_PlayWave
{***** Block PlayWave Start}
function sndPlaySound(lpszSoundName: string; uFlags: cardinal):integer;
 external 'sndPlaySoundA@winmm.dll stdcall';
function InitializeWizard_PlayWave(): Boolean;
var cFilename,cExternal,cLoop,S: String; bExt: Boolean;
begin
Result:=false;
cFileName:=GetOutOf('File:','{#ISSI_PlayWave}','');
cExternal:=Uppercase(GetOutOf('External:','{#ISSI_PlayWave}',''));
cLoop:=Uppercase(GetOutOf('Loop:','{#ISSI_PlayWave}',''));
bExt:=false;  
if (pos('YES',cExternal)>0) or 
  (pos('TRUE',cExternal)>0) or 
  (pos('1',cExternal)>0) then bExt:=true;
if bExt then begin
  if fileexists(ExpandConstant('{src}\'+cFileName)) then begin
   if lowercase(cLoop)='on' then
     sndPlaySound(ExpandConstant('{src}\'+cFileName), $00020000 or $0001 or $0008)
   else sndPlaySound(ExpandConstant('{src}\'+cFileName), $00020000 or $0001 or $0000);     
   Result := True;
  end;
end else begin
  ExtractTemporaryFile(ExtractFileName(cFileName));
  if LoadStringFromFile(ExpandConstant('{tmp}')+'\'+ExtractFileName(cFileName), S)
   if lowercase(cLoop)='on'then
     sndPlaySound(ExpandConstant('{tmp}\'+ExtractFileName(cFileName)), $00020000 or $0001 or $0008)
   else sndPlaySound(ExpandConstant('{tmp}\'+ExtractFileName(cFileName)), $00020000 or $0001 or $0000);
   Result:=true;
  end;
end;
end;
procedure ISSI_DeintializeWave;
begin
sndPlaySound('',0);
end;
{***** Block PlayWave end}
#endif

Можно как-нибудь фон шрифта, который по умолчанию белый, сделать прозрачным?
 
Guest_snake_*,
Попробуй поизменять скрипт. У меня что-то не очень получилось:
что-то слишком муторно + ISSI :) , да и не это мне надо. Вроде нашелся человек, который взялся за мою проблему, как решит, так код и кину...
 
<!--QuoteBegin-Kindly+11:11:2005, 08:07 -->
<span class="vbquote">(Kindly @ 11:11:2005, 08:07 )</span><!--QuoteEBegin-->Но вот хотелось бы знать, существует ли способ "подогнать" выполнение установки под другие углы без изменения расположения при изменении разрешения экрана?[/quote]
Для ответа на вопрос возьму несколько модифицированый скрипт Guest_Snake_*.
Правда мой способ будет работать только если на задний фон выводится картинка.

Код:
procedure InitializeWizard();
var
BackgroundBitmapImage: TBitmapImage;
s:string;
begin
WizardForm.CancelButton.BringToFront;
s:=ExpandConstant('{src}')+'\setup.bmp';
MainForm.borderstyle:=bsnone;
BackgroundBitmapImage := TBitmapImage.Create(MainForm);
BackgroundBitmapImage.Bitmap.LoadFromFile(s);
BackgroundBitmapImage.Left := 0;
BackgroundBitmapImage.Top := 0;
BackgroundBitmapImage.Width:=MainForm.ClientWidth;
BackgroundBitmapImage.Height:=MainForm.ClientHeight;
BackgroundBitmapImage.Parent := MainForm;
BackgroundBitmapImage.Stretch:=True;
end;

procedure CurPageChanged(CurPageID: Integer);
var i:integer;
begin
i:=WizardForm.ProgressGauge.max;
if CurPageID=wpInstalling then
begin
WizardForm.MainPanel.Visible:=False;
WizardForm.Bevel1.Visible:=False;
WizardForm.Width:=ScaleX(400);
WizardForm.Height:=ScaleY(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(154);
WizardForm.CancelButton.Top:=ScaleY(88);

{Выводит в нижнем правом углу}  
WizardForm.Left:=ScaleX(MainForm.Width-420);  
WizardForm.Top:=ScaleY(MainForm.Height-170);   

{Выводит в нижнем левом углу (как в DooM 3)} 
//WizardForm.Left:=ScaleX(MainForm.Left+20);  
//WizardForm.Top:=ScaleY(MainForm.Height-170);

{Выводит снизу по центру экрана} 
//WizardForm.Position:=poScreenCenter;
//WizardForm.Top:=ScaleY(MainForm.Height-170);
end
if CurPageID=wpFinished then
begin
WizardForm.Width:=502;
WizardForm.Height:=392;
WizardForm.Position:=poScreenCenter;
end
end;

Всё отлично работает при любых разрешениях экрана.
 
Expeditor, спасибо, все работает. Только странно, что только при вставленном изображении...
 
Kindly
спасибо, все работает. Только странно, что только при вставленном изображении...

Извиняюсь, конечно картинка тут непричом, я вообще-то имел ввиду, что если будет задний фон(WindowVisible=yes), разумеется можно и без картинки, это я чего-то стормозил.

Кстати немного не в тему , но я вспомнил одну замечательную программку которая называется Regshot v1.7.2 , с помощью неё можно зделать снимок реестра до установки какой-либо проги и после установки , а потом сравнить оба снимка и соответственно засечь чего там изменилось, удобней просто не бывает,рекомендую.
Вот ссылка:
 
У меня опять проблема, хочу внести в реестор строку примерно такого вида:
Root: HKLM; Subkey: "Software\game\command"; ValueType: String; ValueData: "{app}\file.exe /FXSLOAD="%1"", а inno setup ругается и не хочет признавать кавычки внутри своих кавычек, как с этим бороться ?
 
Вопрос не в тему. При запуске программы в папке установки появляются всякие сохранения, профили, логи и при деинсталляции требуется их удалить. Помогите мне со скриптом на Delphi. При запуске программы вылетает сообщение с вопросом, удалять или нет файлы. При нажатии Нет программа закрывается, а принажатии Да - происходит удаление папок и файлов. Как сдетать чтобы программа удаляла не конкретный файл "filename.txt", а удаляла бы все вложенные папки(пустые и с файлами) и файлы, независимо от их имени и расширения.

Код:
program ISUninstaller;

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ShellAPI, StdCtrls, XPMan;

var
FileName, Msg, MsgTitle: string;

begin
with Application do
begin
 FileName := 'filename.txt';
 MsgTitle := 'Подтвердите удаление файлов';
 Msg := 'Нажмите «Да», если вы хотите удалить все файлы из папки игры (в том числе и сохранения игры), или нажмите «Нет», если хотите оставить файлы, которые не были установлены вместе с игрой.' + #13#10#13#10 + 'Вы хотите удалить все файлы из папки игры?';
 If MessageBox(PChar(Msg), PChar(MsgTitle), MB_ICONQUESTION or MB_YesNo) = IDYes then
 DeleteFile(PChar(FileName))
 else
 Exit;
end;
end.
 
Guest
разумеется можно и без картинки, это я чего-то стормозил.
Ну а как тогда без картинки? :D
А RegShoot-ом уже давно пользуюсь - рульный сканер реестра + измененных и добавляемых в систему файлов.
Expeditor, пробуй так:
"{app}\file.exe /FXSLOAD=""%1"""
А вообще я руководство по программированию составил, уже третья финальная версия, там куча примеров, в том числе и отсюда, скоро выложу.
Хочу проиграть трекерную музу при запуске инсталлятора Inno Setup.
Помогли мне :D
Код:
; -=wWw.BioCyborG.NarOd.rU=-
; Этот скрипт демонстрирует, как добавить в инсталлятор фоновую музыку в формате *.xm
; Для воспроизведения треков используется MiniFMOD.dll от coban2k (http://www.cobans.net)
; В примере используется трек Letting Go (с) Jeroen Tel, 1997
; Библиотеку MiniFMOD.dll можно взять здесь: http://biocyborg.narod.ru/rev/minifmod.zip

[Setup]
AppName=Демонстрация использования MiniFMOD.dll
AppVerName=Демонстрация использования MiniFMOD.dll by BioCyborG
DefaultDirName={pf}\My Program
DisableProgramGroupPage=yes
UninstallDisplayIcon={app}\prog.exe

[Files]
Source: "prog.exe"; DestDir: "{app}";
Source: "MiniFMOD.dll"; DestDir: "{tmp}"; Flags:dontcopy
Source: "JT_LETGO.XM"; DestDir: "{tmp}"; Flags:dontcopy

[Code]
const
MB_ICONINFORMATION = $40;
 // определяем процедуры и функции
function SongLoadFromFile(FileName: PChar): Integer;
external 'SongLoadFromFile@files:minifmod.dll cdecl delayload';

procedure SongPlay(hMod: Integer);
external 'SongPlay@files:minifmod.dll cdecl delayload';

 //при запуске инсталлятора выполняем вот этот код:
procedure InitializeWizard();
var
hMod: Integer;
Name1: string;
begin
ExtractTemporaryFile(ExpandConstant('MiniFMOD.dll'));  //извлекаем во временную папку MiniFMOD.dll
ExtractTemporaryFile(ExpandConstant('JT_LETGO.XM'));  //извлекаем во временную папку музыкальный файл
Name1:=ExpandConstant('{tmp}\JT_LETGO.XM');       //определяем путь, где находится музыкальный файл
hMod := SongLoadFromFile(PChar(Name1));         //загружаем музыкальный файл
SongPlay(hMod);                     //запускаем воспроизведение музыки
end;
Да, чуть не забыл. MiniFMOD умеет воспроизводить только XM файлы (Fast Trecker). Чтобы использовать в инсталляциях mod и s3m нужно их сконвертировать в формат Fast Trecker с помощью программы MODPLUG TRACKER: (открываем файл и сохраняем с расширением XM)
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!