• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

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

    Запись на курс до 25 апреля. Получить промодоступ ...

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

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

zubr

Вот код решающий оба ваших вопроса:
Код:
function InitializeSetup(): Boolean;
var
res:Integer;
s, ResultStr:string;
begin
ExtractTemporaryFile(music.mp3');
s:=ExpandConstant('{tmp}')+'\music.mp3';
ShellExec('play', s, '', '', SW_HIDE, ewNoWait, res);
If RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\My Program_is1', 'UninstallString', ResultStr) then
begin
If ResultStr<>'' then
begin
 ResultStr:=RemoveQuotes(ResultStr);
 If MsgBox('Программа My Program уже установлена, удалить ее?', mbInformation, MB_OKCANCEL)=IDOK then
 InstExec(ResultStr, '', '', True, False, SW_SHOW, res)
 else
 begin
 Result:=False;
 exit;
 end;
end;
end;
Result:=True;
end;
 
K

Kindly

Получилось, но всё равно немного переделал под пятую версию:

function InitializeSetup(): Boolean;
var
res:Integer;
ResultCode: Integer;
s, ResultStr:string;
begin
ExtractTemporaryFile('Temp_Program.exe');
s:=ExpandConstant('{tmp}')+'\Temp_Program.exe';
Exec(s, '', '', SW_SHOWMINIMIZED, ewNOWait, res);
Result:=True;
begin
If RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Restorator 2005_is1', 'UninstallString', ResultStr)
then
begin
If ResultStr<>''
then
begin
ResultStr:=RemoveQuotes(ResultStr);
If MsgBox('Программа My Program уже установлена, удалить ее?', mbInformation, MB_OKCANCEL)=IDOK
then
if not Exec(ResultStr, '', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode)
then
MsgBox('Ошибка удаления. ' #13#13 '' + SysErrorMessage(ResultCode) + '.' #13#13 'Вероятно, деинсталлятор был перемещен, удален или переименован.', mbError, MB_OK);
end;
end;
end;
end;

Вопрос следующий: как закрыть (или завершить процесс) программу, запущенную из временной папки перед завершением установки, используя средства Inno Setup? Это ведь лучше через процедуру DeInitializeSetup делать?
У меня после успешного решения данного вопроса сразу отпадает потребность воспроизведения *.xm и *.mod, т.к. уже найден конвертер этих файлов в EXE. На данный момент это последнее, что меня интересует. Поможете?
 
Z

zubr

Вопрос следующий: как закрыть (или завершить процесс) программу, запущенную из временной папки перед завершением установки, используя средства Inno Setup?
Если программка Temp_Program.exe не консольная, то можно передать ей сообщение WM_CLOSE, иначе проблема сложнее, средствами InnoSetup не получится.
Код:
procedure DeInitializeSetup();
var
h:Longint;
begin
h:=FindWindowByClassName('WMPlayerApp');
If h<>0 then
SendMessage(h, 16, 0, 0);
end;
Здесь 'WMPlayerApp' класс окна закрываемого приложения, чтобы его определить можно воспользоваться программой VIEWWIND.
 
K

Kindly

Спасибо, очень интересно. Я вот не знаю даже: сама программка Temp_Program.exe не консольная, т.е. обычное Win32 приложение, которое напоминает классический интерфейс Winamp-а, но она создана консольным "Досовским" приложением, поэтому я теряюсь в точном ответе, т.к. не знаю, может ли считаться программа Win32, если она была создана Досовским/консольным приложением. Но судя по всем признакам (проверка PE анализаторами) - программка не консольная.
Получается, что дело остаётся "за малым". Какую-то программу VIEWWIND я нашёл через поисковик, но что-то сомневаюсь, что она может определить класс окна приложения. Сама по себе она консольная и даже не имеет описания, как ей пользоваться, даже не запускается через командную строку (возможно, это исходники:D. Поэтому я прошу Вас очень, - укажите, пожалуйста, ссылку, по которой можно скачать данную программу.
 
Z

zubr

В вашем случае, если при проигрывании звукового файла, вы закрываете программку Temp_Program.exe и проигрывание прекращается, то все должно получиться.
Программу ViewWindow отправил вам на Email.
 
K

Kindly

Спасибо большое. Очень хорошая программка.
 
K

Kindly

Всё получилось, только есть один момент:

Код

procedure DeInitializeSetup();
var
h:Longint;
begin
h:=FindWindowByClassName('XM-EXE-WINDOW');
If h<>0 then
SendMessage(h, 16, 0, 0);
begin
MsgBox('Работа мастера завершена.', mbInformation, MB_OK);
end;
end;

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

И ещё один, думаю, понравится:).
Есть такая директива AppMutex. Эта директива используется для предотвращения установки новой версии программы, если программа выполняется в данный момент, и удаления запущенного в данный момент приложения. В ней нужно указать ограничители. Если ограничители присутствуют, инсталятор/деинсталятор выдаст сообщение: "[Setup или Uninstall] обнаружил, что [AppName] выполняется. Пожалуйста, завершите работу приложения, а потом нажмите ОК для продолжения или Cancel для отмены". Но для этого нужно добавление в программу/инсталлятор соответствующего кода. Например, вот код на Delphi:

CreateMutex(nil, False, 'MyProgramsMutexName');

А в секции Setup после этого прописать следующее:

AppMutex=MyProgramsMutexName

Вот только не знаю как расписать код для создания Mutex.
Если Вам не сложно, напишите, пожалуйста, примерчик.
 
Z

zubr

Вопрос: можно ли заставить выгружаться временные файлы (в данном случае) при выходе инсталлятора без соответствующего сообщения, например, сделать задержку?
Попробуйте вместо функции MsgBox поставить функцию Sleep(500) - здесь аргумент 500 количество милисекунд задержки.
Есть такая директива AppMutex. Эта директива используется для предотвращения установки новой версии программы, если программа выполняется в данный момент, и удаления запущенного в данный момент приложения.
Есть смысл использовать данную директиву, если вы делаете инсталлятор для своей программы, в которой вы можете установить мутекс, как в Help написано CreateMutex(nil, False, 'MyProgramsMutexName'). В вашем случае так не получится, но можно исхитриться по другому, все через тот же класс окна:
Код:
function InitializeSetup(): Boolean;
var
h:Longint;
begin
Result:=True;
h:=FindWindowByClassName('ClassWindowInstallProg');//ClassWindowInstallProg - класс окна программы, которую вы устанавливаете
If h<>0 then
begin
//здесь вы можете выдать сообщение, что открыта программа
SendMessage(h, 16, 0, 0);//закрытие программы
//можно не закрывать программу, а выдать сообщение и закрыть инсталлятор
Result:=False;//закрытие инсталлятора
end;
end;
 
K

Kindly

Спасибо большое. Думаю, разберусь с этим и всё будет правильно работать.
Zubr, а Вы настоящий Гуру в написании скрипта для инсталлятора (да и не только, наверное:).
 
K

Kindly

У меня созрел вопрос "косметического" характера:
Видел инсталляторы (Inno Setup), в которых в фоновое окно вставлено изображение, причём отличающееся от изображения, которое на панели мастера.
Я только знаю, как вывести в фоновое окно изображение мастера:
procedure InitializeWizard();
var
BackgroundBitmapImage: TBitmapImage;
begin
CreateTheWizardPages;
BackgroundBitmapImage := TBitmapImage.Create(MainForm);
BackgroundBitmapImage.Left := 50;
BackgroundBitmapImage.Top := 100;
BackgroundBitmapImage.AutoSize := True;
BackgroundBitmapImage.Bitmap := WizardForm.WizardBitmapImage.Bitmap;
BackgroundBitmapImage.Parent := MainForm;
end;
А как вывести внешнее изображение не знаю. Может Вы сталкивались с такой ситуацией?
И ещё один: при установке на панели выбора папки установки отображается количество требуемого дискового пространства. Как сделать, чтобы чуть выше отображалась информация о доступном пространстве на выбранном диске?
 
Z

zubr

Видел инсталляторы (Inno Setup), в которых в фоновое окно вставлено изображение, причём отличающееся от изображения, которое на панели мастера.
Вы уверены, что это было сделано в InnoSetup? В InnoSetup (4-ая версия) я такой возможности не нашел.
при установке на панели выбора папки установки отображается количество требуемого дискового пространства. Как сделать, чтобы чуть выше отображалась информация о доступном пространстве на выбранном диске?
Не знаю, никогда не сталкивался с этим вопросом. Будет время посмотрю.
 
Z

zubr

В InnoSetup (4-ая версия) я такой возможности не нашел.
Извиняюсь, есть такая возможность.
Код:
[Setup]
WindowVisible=yes

[Files]
Source: "MyImage.bmp"; Flags: dontcopy

[code]
procedure InitializeWizard();
var
BackgroundBitmapImage: TBitmapImage;
BackgroundBitmapText: TNewStaticText;
s:string;
bitmap:TBitmap;
begin
ExtractTemporaryFile(MyImage.bmp');
s:=ExpandConstant('{tmp}')+'\MyImage.bmp';
BackgroundBitmapImage := TBitmapImage.Create(MainForm);
BackgroundBitmapImage.AutoSize := True;
BackgroundBitmapImage.Bitmap.LoadFromFile(s);
BackgroundBitmapImage.Left := 50;
BackgroundBitmapImage.Top := 100;
BackgroundBitmapImage.Parent := MainForm;
 BackgroundBitmapText := TNewStaticText.Create(MainForm);
BackgroundBitmapText.Caption := 'TBitmapImage';
BackgroundBitmapText.Left := BackGroundBitmapImage.Left;
BackgroundBitmapText.Top := BackGroundBitmapImage.Top +  BackGroundBitmapImage.Height + 8;
BackgroundBitmapText.Parent := MainForm;
end;
Здесь MyImage.bmp - внешнее изображение.
при установке на панели выбора папки установки отображается количество требуемого дискового пространства. Как сделать, чтобы чуть выше отображалась информация о доступном пространстве на выбранном диске?
Сделать можно, но очень гиморно.
 
K

Kindly

Спасибо большое. Я уже хотел в доказательство Вам скриншоты на мыло выслать ;). А со вторым вопросом напрягать Вас не буду.
 
K

Kindly

Хорошо. А как можно замостить фоновую картинку так, чтобы при любом изменении разрешения экрана она оставалась растянутой до краёв, чтобы не выходила за пределы фонового окна и чтобы меньше его не была? В виденных мной инсталляторах именно так и было. Я 2 часа промучался, но так и не достиг требуемого результата.
 
Z

zubr

Я 2 часа промучался, но так и не достиг требуемого результата.
Ну 2 часа это не много, бывает приходится мучиться 2 дня, а то и 2 недели :)
Вот код решающий ваш вопрос:
Код:
procedure InitializeWizard();
var
BackgroundBitmapImage: TBitmapImage;
s:string;
bitmap:TBitmap;
begin
ExtractTemporaryFile(MyImage.bmp');
s:=ExpandConstant('{tmp}')+'\MyImage.bmp';
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;
 
S

Sn

Здраствуйте. Я в Inno Setup начал делать инсталляторы недавно и программировать на Delphi и Pascal не умею. Благодаря этому форуму научился делать фоновые рисунки. А можно ли сделать титульное название приложения поверх фонового рисунка или вообще убрать его (если это возможно). Помогите мне сделать два таких скрипта. :( Заранее спасибо.
 
Z

zubr

Создайте свой фоновый рисунок с названием или без и растяните его на весь экран. Как это делать смотрите на 2 ответа выше.
 
S

Sn

Хотелось бы вообще удалить титульную надпись и не вспоминать о ней. Ну да черт с ней - сделал уже крутейший (по крайней мере для меня :) ) инсталлятор для игрухи. У меня немного другой вопрос. Схимичил тут небольшой скриптик:
Код:
[Code]
function CheckSerial(Serial: String): Boolean;
begin
If (Serial='4422-93598-8995') or
 (Serial='8474-05768-1841')then
 Result:=True
else
begin
 Result:=False;
end;
end;
Таким способом мождо делать количество серийников в коде хоть до посинения. А возможно ли, чтобы инсталлятор проверял не какое-то конкретное число или буквы, а проверял бы введенный серийник по соответствующей маске (к примеру такой: '####-#####-#****', где #-цифры, а *-буквы и т.д.). Ну или что-то похожее. И сразу тут второй вопрос - как сделать шифрование инсталлятора. А то скачал с сайта файл ISCrypt.dll, а как его использовать не знаю. Спасибо!
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

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