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

  • Автор темы Kindly
  • Дата начала
Статус
Закрыто для дальнейших ответов.
G

Guest_Snake_*

Составил скрипт в котором компоненты выбираются не на странице 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_, появившаяся перед моим ником.
 
G

Guest_Snake_*

очень захотелось "убить" 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.
 
K

Kindly

Как сделать, чтобы исключить из скрипта функцию 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: "Английская версия"

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

Guest_Snake_*

Хм, Snake, зачем это надо - установка по отдельности, уже проще два инсталлера сделать.

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

Guest_Snake_*

Дошло, как сделать выбор языка программы через 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
 
E

Expeditor

Подскажите пожалуйста, как можно прописать в реестор примерно такую строку: Root: HKLM; Subkey: "Software\game"; ValueType: String; ValueName: Product GUID; ValueData: "{782DDB70-3DF4-4366-00BF-E3767BCD173B}"; Дело в том что в таком виде выдаётся ошибка, из-за того в фигурных скобках указываются константы, и как же мне прописать в реестор строку с фигурными скобками ?.
 
H

Hetman

чё-то я не вовремя написал, может пригодиться:
вообщето есть сырцы . Do you speak English?


Между прочим на Си.
 
G

Guest_Snake_*

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

Код:
[Registry]
Root: HKLM; Subkey: "Software\game"; ValueType: String; ValueName: Product GUID; ValueData: "{{782DDB70-3DF4-4366-00BF-E3767BCD173B}"
 
K

Kindly

Вопрос по реестру:
Например, чтобы зарегистрировать "одним махом" TYBELIB нужно поставить флаг "regtybelib", но вот как можно было бы "выдрать" все необходимые регистрационные данные из *.OCX, вызвав, может быть какую-нибудь функцию. Например, я все время вычисляю программкой какие данные вносятся в реестр при регистрации компонентов, и затем вручную все пишу в скрипт. Если заглянуть в сам компонент, можно также увидеть секцию ресурсов с находящимися регистрационными данными. Вот к примеру в нем прописаны следующие данные:
HKLM\SOFTWARE\Classes\CLSID\{23233-4244-43434-343434434-34354}
HKLM\SOFTWARE\Classes\nmnm.activator.1
и т.д.
Доступные флаги не могут выдрать данную информацию из ACTIVE.X компонента, или я конкретно невнимателен.
Так возможен ли вариант полной регистрации активного компонента, вызывая необходимую функцию из системных библиотек?
 
E

Expeditor

Guest_Snake_*
Огромное спасибо, очень помог!!!
С новым годом !!!
 
K

Kindly

Раньше было как-то... Хочу проиграть трекерную музу при запуске инсталлятора 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]
Ну вот я и не знаю, как правильно расписать эти строки, плюс как правильно указать параметры для зацикленного воспроизведения непосредственно при вызове функции для проигрывания. Подскажете?
 
G

Guest_snake_*

Попробуй поизменять скрипт. У меня что-то не очень получилось:

Код:
[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

Можно как-нибудь фон шрифта, который по умолчанию белый, сделать прозрачным?
 
K

Kindly

Guest_snake_*,
Попробуй поизменять скрипт. У меня что-то не очень получилось:
что-то слишком муторно + ISSI :) , да и не это мне надо. Вроде нашелся человек, который взялся за мою проблему, как решит, так код и кину...
 
E

Expeditor

<!--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;

Всё отлично работает при любых разрешениях экрана.
 
K

Kindly

Expeditor, спасибо, все работает. Только странно, что только при вставленном изображении...
 
G

Guest

Kindly
спасибо, все работает. Только странно, что только при вставленном изображении...

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

Кстати немного не в тему , но я вспомнил одну замечательную программку которая называется Regshot v1.7.2 , с помощью неё можно зделать снимок реестра до установки какой-либо проги и после установки , а потом сравнить оба снимка и соответственно засечь чего там изменилось, удобней просто не бывает,рекомендую.
Вот ссылка:
 
E

Expeditor

У меня опять проблема, хочу внести в реестор строку примерно такого вида:
Root: HKLM; Subkey: "Software\game\command"; ValueType: String; ValueData: "{app}\file.exe /FXSLOAD="%1"", а inno setup ругается и не хочет признавать кавычки внутри своих кавычек, как с этим бороться ?
 
G

Guest_Snake_*

Вопрос не в тему. При запуске программы в папке установки появляются всякие сохранения, профили, логи и при деинсталляции требуется их удалить. Помогите мне со скриптом на 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.
 
K

Kindly

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)
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

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