;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Это iss-скрипт по умолчанию ;; ;; для скармливания IssBuilder. ;; ;; ;; ;; Copyright (C) 2007 Gipat Group ;; ;; Распространяется на условиях ;; ;; LGPL v2.1 ;; ;; ;; ;; www.gipatgroup.org ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;К работе над данным файлом приложили руки, ноги.... короче аффтары: ;; 1) Sagrer (sagrer@yandex.ru) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Файл для сборки GGBuildTools [Setup] InternalCompressLevel=ultra OutputBaseFilename=GGBuildTools_0_0_0_0 SolidCompression=true Compression=lzma/ultra OutputDir=.\ SourceDir=.\ VersionInfoVersion=0.0.0.0 VersionInfoTextVersion=GGBuildTools 0.0.0.0 VersionInfoCompany=Gipat Group VersionInfoDescription=GGBuildTools 0.0.0.0 ShowLanguageDialog=no AppName={code:ConstAppName} AppVerName=GGBuildTools 1.0.1.40 DefaultDirName={code:ConstInstallPath} UsePreviousAppDir=false DefaultGroupName={code:ConstDeveloperName}\{code:ConstAppName}\ DisableStartupPrompt=true FlatComponentsList=true AppendDefaultDirName=false UsePreviousSetupType=false AppCopyright=Copyright © 2007 Gipat Group RestartIfNeededByRun=false WizardImageFile=compiler:wizmodernimage-is.bmp WizardSmallImageFile=compiler:wizmodernsmallimage-is.bmp VersionInfoCopyright=Copyright © 2007 Gipat Group LicenseFile=GG_opened_EI-editor-utility_license.txt InfoBeforeFile=ChangeLog.txt [_ISTool] UseAbsolutePaths=false [Languages] Name: Russian; MessagesFile: compiler:Languages\Russian.isl Name: English; MessagesFile: compiler:Default.isl [Components] Name: CurrVersion_Main; Description: Основные файлы полной версии; Flags: fixed; Check: CheckDoNewInstall; Types: StandardInstall Name: AlwaysInstall; Description: Обязательные файлы; Flags: fixed; Types: StandardInstall [Icons] Name: {group}\readme.txt; Filename: {app}\readme.txt; Components: CurrVersion_Main Name: {group}\Деинсталлировать; Filename: {uninstallexe}; Components: CurrVersion_Main [Types] Name: StandardInstall; Description: Обыкновенная установка; Languages: [Run] Filename: {app}\Installer.exe; Parameters: -s; WorkingDir: {app}; StatusMsg: Running application's Installer.exe; Components: AlwaysInstall; Flags: runhidden [Registry] Root: HKCU; Subkey: Software\{code:ConstDeveloperName}\{code:ConstAppName}\; Flags: createvalueifdoesntexist uninsdeletekey; Components: AlwaysInstall [Code] const AppName = 'GGBuildTools'; //Типа имя апликашона AppVer = '0.0.0.0'; NoFullInstall = false; //Запрет\разрешение полной установки NoUpdate = true; //Запрет\разрешение апдейта UpdateFrom = '0.0.0.0;0.0.0.1'; //Версии, с которых можно обновлять. DeveloperName = 'Gipat Group'; //Имя девелопера - часть пути в реестре. var InstallPath, CurrentVer : string; DoNewInstall, DoUpdate : boolean; Function Parse (Str, Separator : string; Var Parsed : string) : string; var I, StrLength : integer; begin //Функа для парсинга строк. Кривая, но как умею :(. I := 0; StrLength := Length(Str); if StrLength > 0 then begin Parsed := ''; repeat I := I+1; If Str[I] <> Separator then begin //Если сепаратор не встретился - запомнить символ. Parsed := Parsed+Str[I]; end; until (I = StrLength) or (Str[I] = Separator); Result := Str; Delete(Result,1,I); end else begin Parsed := Str; Result := ''; end; end; Function IsNumericStr (Str : string) : boolean; var I, StrLength : integer; FindedChar : boolean; begin //А эта функа должна определять, состоит ли строка только из цифр. Result := true; //Умолчальный результат. StrLength := Length(Str); If StrLength > 0 then begin //Если в строке чета есть то можно приступать. For I := 1 to StrLength do begin FindedChar := true; If Str[I] = '1' then FindedChar := false; //Достаточно выполнится 1 проверке - и чар будет не найден :) If Str[I] = '2' then FindedChar := false; If Str[I] = '3' then FindedChar := false; If Str[I] = '4' then FindedChar := false; If Str[I] = '5' then FindedChar := false; If Str[I] = '6' then FindedChar := false; If Str[I] = '7' then FindedChar := false; If Str[I] = '8' then FindedChar := false; If Str[I] = '9' then FindedChar := false; If Str[I] = '0' then FindedChar := false; //И если был обнаружен символ-не цифра - обломить все нафиг. If FindedChar = true then Result := false; end; end else begin Result := false; //Типа строка пустая. end; end; Function IsVersionStr (Str : string) : boolean; var I, StrLength : integer; FindedChar, WasPoint : boolean; begin //А эта функа должна определять, состоит ли строка только из цифр. Result := true; //Умолчальный результат. StrLength := Length(Str); If StrLength > 0 then begin //Если в строке чета есть то можно приступать. WasPoint := false; For I := 1 to StrLength do begin FindedChar := true; If Str[I] = '1' then begin FindedChar := false; WasPoint := false; end; If Str[I] = '2' then begin FindedChar := false; WasPoint := false; end; If Str[I] = '3' then begin FindedChar := false; WasPoint := false; end; If Str[I] = '4' then begin FindedChar := false; WasPoint := false; end; If Str[I] = '5' then begin FindedChar := false; WasPoint := false; end; If Str[I] = '6' then begin FindedChar := false; WasPoint := false; end; If Str[I] = '7' then begin FindedChar := false; WasPoint := false; end; If Str[I] = '8' then begin FindedChar := false; WasPoint := false; end; If Str[I] = '9' then begin FindedChar := false; WasPoint := false; end; If Str[I] = '0' then begin FindedChar := false; WasPoint := false; end; If Str[I] = '.' then begin FindedChar := false; If WasPoint = true then begin //Если до этого уже была точка - то аблооом. FindedChar := true; end; WasPoint := true; end; //И если был обнаружен символ-не цифра и не точка - обломить все нафиг. If FindedChar = true then Result := false; end; end else begin Result := false; //Типа строка пустая. end; end; Function IsNewVersion(InstalledVer, CurrentVer : string) : boolean; var CurrVerLevels, I, InstalledVerLevels, MaxLevel : integer; TempStr, TempStr2, InstalledVerTemp, CurrentVerTemp : string; begin //Функа должна проверять, является ли ентот инсталл более новой версией. Result := false; //Типа умолчальное значение. InstalledVerTemp := InstalledVer; CurrentVerTemp := CurrentVer; If (IsVersionStr(InstalledVer) = true) and (IsVersionStr(CurrentVer) = true) then begin //Только если в обоих строках - версии. //Для начала - посмотреть сколько уровней версии в текущей версии. TempStr := CurrentVerTemp; CurrVerLevels := 1; //Есть как минимум 1 уровень. repeat If Pos('.',TempStr) <> 0 then begin CurrVerLevels := CurrVerLevels + 1; //Есть минимум еще 1 уровень. TempStr := Parse(TempStr,'.',TempStr2); end; until Pos('.',TempStr) = 0; //И в проинсталенной. TempStr := InstalledVerTemp; InstalledVerLevels := 1; //Есть как минимум 1 уровень. repeat If Pos('.',TempStr) <> 0 then begin InstalledVerLevels := InstalledVerLevels + 1; //Есть минимум еще 1 уровень. TempStr := Parse(TempStr,'.',TempStr2); end; until Pos('.',TempStr) = 0; //Теперь вычислить максимальный уровень. If CurrVerLevels > InstalledVerLevels then begin MaxLevel := CurrVerLevels; end else begin MaxLevel := InstalledVerLevels; end; //Теперь - к той версии что самая малоуровневая - добавить нулей. If CurrVerLevels < MaxLevel then begin For I := 1 to MaxLevel - CurrVerLevels do begin CurrentVerTemp := CurrentVerTemp+'.0'; end; end; If InstalledVerLevels < MaxLevel then begin For I := 1 to MaxLevel - InstalledVerLevels do begin InstalledVerTemp := InstalledVerTemp+'.0'; end; end; //Ну а теперь - собсно сравнение наконецто. I := 0; repeat I := I+1; InstalledVerTemp := Parse(InstalledVerTemp,'.',TempStr); CurrentVerTemp := Parse(CurrentVerTemp,'.',TempStr2); If StrToInt(TempStr2) > StrToInt(TempStr) then Result := true; until (I = MaxLevel) or (Result = true); end; end; Function VersionIsUpdatable(Version : string) : boolean; //Проверить - есть ли эта версия в списке версий пригодных для обновления var ParsedStr, CheckableVer : string; begin //Инициализация Result := false; //Собсно проверяем. ParsedStr := UpdateFrom; repeat ParsedStr := Parse(ParsedStr,';',CheckableVer); if CheckableVer <> '' then begin if CheckableVer = Version then begin //Ага, нашли, есть оно в списке. Result := true; end; end; until (ParsedStr = '') or (Result = true); end; Function InitializeSetup() : boolean; var AllOk, TempBool : boolean; TempStr, TempVersionsStr, CheckableVer : string; ResultCode : integer; begin //Ну типа, скрипт! :)))) //MsgBox('Старт установки',mbError,MB_OK); AllOk := true; //Типа индикатор того что все в порядке. DoNewInstall := false; DoUpdate := false; CurrentVer := ''; //Есть ли запись в реестре? If RegValueExists(HKEY_CURRENT_USER,'Software\'+DeveloperName+'\'+AppName,'ver') = true then begin //Если уже стоит какая-то версия //Смотрим - не та же самая ли эта версия которая в пакете? //Получить номер текущей версии. RegQueryStringValue(HKEY_CURRENT_USER,'Software\'+DeveloperName+'\'+AppName,'ver',TempStr); if TempStr = AppVer then begin //Та же версия. Спрашиваем у юзверя - продолжать ли установку? if MsgBox('Версия, содержащаяся в данном пакете ('+AppVer+') судя по всему уже установлена. Если вы продолжите установку - то по-видимому потребуется деинсталлировать уже установленную версию. Продолжить установку?',mbConfirmation,MB_YESNO) = IDNO then begin //Юзверь отказался продолжать установку. AllOk := false; end; end; If (NoUpdate = false) and (AllOk = true) then begin //Если апдейт разрешен //И проверить - входит ли эта версия в список апдейтабельных версий. TempVersionsStr := UpdateFrom; TempBool := false; //Индикатор - подходит ли версия для апдейта. repeat TempVersionsStr := Parse(TempVersionsStr,';',CheckableVer); if CheckableVer <> '' then begin if CheckableVer = TempStr then begin //Подходит. TempBool := true; end; end; until (TempVersionsStr = '') or (TempBool = true); if TempBool = true then begin //Если подходит - разрешаем апдейт. DoUpdate := true; //Разрешить апдейт. RegQueryStringValue(HKEY_CURRENT_USER,'Software\'+DeveloperName+'\'+AppName,'path',TempStr); InstallPath := TempStr; CurrentVer := CheckableVer; end else begin //Версия апдейту не подлежит. Можно разве что предварительно запустить деинсталлер уже установленной //версии. Это будет сделано ниже. end; end else begin //Уже стоит какая-то версия, но апдейт запрещен. //В таком случае, опять же, будет предложено запустить деинсталляцию после чего //продолжить по сценарию новой установки. end; end; //Нужен ли сценарий полной установки? If (AllOk = true) and ((RegValueExists(HKEY_CURRENT_USER,'Software\'+DeveloperName+'\'+AppName,'ver') = false) or (DoUpdate = false)) and (NoFullInstall = false) then begin //Вроде нужно. DoNewInstall := true; //Посмотрим - нужно ли избавиться от старой версии проги? if RegValueExists(HKEY_CURRENT_USER,'Software\'+DeveloperName+'\'+AppName,'ver') = true then begin //О как. Запись в реестре есть, а апдейт оказывается не запущен. Значит установленная версия апдейту //не подлежит. Тут все зависит от того, существует ли директория с прогой на венте, а также //есть ли там экзейник деинсталлёра. Для начала проверим наличие директории с прогой. RegQueryStringValue(HKEY_CURRENT_USER,'Software\'+DeveloperName+'\'+AppName,'path',TempStr); If DirExists(TempStr) = true then begin //О как. Есть такое дело. //Теперь попробуем нарыть в реестре путь к деинсталлеру. TempStr := ''; if RegValueExists(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\'+AppName+'_is1','UninstallString') = true then begin //Выдернуть путь из реестра. RegQueryStringValue(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\'+AppName+'_is1','UninstallString',TempStr); //Если нужно - убрать '"' по краям. TempStr := RemoveQuotes(TempStr); end; //Собсно проверяем - существует ли экзейник деинсталлера. if FileExists(TempStr) = true then begin //Файлег существует и надо предложить его запустить. if MsgBox('Обнаружена уже установленная версия. Чтобы установить данную версию - надо деинсталлировать уже установленную. Деинсталлятор обнаружен. Запустить деинсталлятор?',mbConfirmation,MB_YESNO) = IDYES then begin //Усе ок, юзверь запустил деинсталляцию. Exec(TempStr,'','',SW_SHOW,ewWaitUntilTerminated,ResultCode); //И "поспать" 5 секунд чтобы файлеги успели удалиться. Sleep(5000); //Если файлик деинсталлера до сих пор на месте - вывести окошк с кнопкой чтоб юзверь сам нажмал на него //когда деинсталл завершится. Ибо там всякое бывает, отследить момент реального завершения деинсталла сложно. if FileExists(TempStr) = true then begin MsgBox('По завершению деинсталляции - нажмите кнопку ОК. НЕ НАЖИМАЙТЕ кнопку Ок до завершения деинсталляции!!!',mbError,MB_OK); end; //Деинсталл завершена Проверить, так ли это... if FileExists(TempStr) = false then begin //Можно запускать нормальную установку. Оставляем все как есть, оно само пойдет по стандартному //сценарию. end else begin MsgBox('Деинсталляция не выполнена по неизвестной причине. Выполните деинсталляцию вручную, либо вручную удалите каталог '+ExtractFilePath(TempStr)+' после чего запустите эту установку заново.',mbError,MB_OK); DoNewInstall := false; end; end else begin //Юзверь отказался выполнять деинсталляцию. //Отмена установки. MsgBox('Деинсталляция не выполнена. Выполните деинсталляцию вручную, либо вручную удалите каталог '+ExtractFilePath(TempStr)+' после чего запустите эту установку заново.',mbError,MB_OK); DoNewInstall := false; end; end else begin //Файлега не существует, таким образом остается только спросить у юзверя - продолжать ли //установку невзирая на возможные глюканы. //Надо еще выдрать каталог с прогой. RegQueryStringValue(HKEY_CURRENT_USER,'Software\'+DeveloperName+'\'+AppName,'path',TempStr); if MsgBox('Обнаружена уже установленная версия, но деинсталлятор отсутствует. Рекомендуется прекратить установку и вручную удалить каталог '+TempStr+' после чего запустить эту установку заново. Но вы все-же можете и продолжить процесс установки (это может привести к ошибкам). Продолжить установку?',mbConfirmation,MB_YESNO) = IDYES then begin //Юзверь таки решил продолжать установку... Не делаем ничего - оно дальше пойдет по нормальному сценарию. end else begin //Юзверь отменил установку. DoNewInstall := false; end; end; end else begin //Нету проги на венте. А это значит что запись в реестре - по-видимому не более чем запись в реестре, //а значит можно безболезненно действовать по обычному сценарию для новой установки. end; end; //Запуск установки по стандартному сценарию. If DoNewInstall = true then begin //Получить путь для инсталляции. if RegValueExists(HKEY_CURRENT_USER,'Software\'+DeveloperName+'\'+AppName,'path') = true then begin //Если в реестре сохранилась запись о пути - воспользуемся ей. RegQueryStringValue(HKEY_CURRENT_USER,'Software\'+DeveloperName+'\'+AppName,'path',InstallPath); end else begin //Не удалось добыть такой информации - кидаем в ProgramFiles. InstallPath := AddBackslash(ExpandConstant('{pf}'))+'\'+DeveloperName+'\'+AppName; end; DoNewInstall:= true; end else begin //По пути был какой-то облом. AllOk := false; end; end else begin //Нельзя ставиться с нуля. В принципе. Если апдейт не запущен - значит инсталлер не нашел такую версию, //которую он может обновить. if (DoUpdate = false) and (AllOk = true) then begin MsgBox('Инсталлятору не удалось найти на компьютере версий, которые он мог бы обновить. О том, какие версии в принципе могут быть обновлены - см. по имени файла пакета. Данный пакет не предназначен для установки с нуля, им можно только обновить одну из определенных уже установленных версий - поэтому установка отменена.',mbError,MB_OK); AllOk := false; end; end; If AllOk = true then begin //Можно начинать установку. Result := true; end else begin //Облом с установкой. Вот так вот :(. //MsgBox('Установка отменена :(',mbError,MB_OK); Result := false; end; end; Function ConstInstallPath(Default : string) : string; begin Result := InstallPath; end; Function ConstAppVer(Default : string) : string; begin Result := AppVer; end; Function ConstAppName(Default : string) : string; begin Result := AppName; end; Function ConstUninstallExe(Default : string) : string; begin Result := ''; if RegValueExists(HKEY_LOCAL_MACHINE,'\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'+AppName+'_is1','UninstallString') = true then begin RegQueryStringValue(HKEY_LOCAL_MACHINE,'\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'+AppName+'_is1','UninstallString',Result); Result := RemoveQuotes(Result); end; end; Function ConstAppVerName(Default : string) : string; begin Result := AppName+' '+AppVer; end; Function ConstDeveloperName(Default : string) : string; begin Result := DeveloperName; end; Function CheckDoNewInstall() : boolean; begin Result := DoNewInstall; end; Function CheckDoUpdate() : boolean; begin Result := DoUpdate; end; //Function CheckUpdate_0_0_0_1() : boolean; ////Функция-екзампл - по которой будет собсно проверяться - запускать ли апдейт именно с этой версии. //begin // Result := VersionIsUpdatable('0.0.0.1'); //end; Function ShouldSkipPage(CurPage: Integer) : boolean; begin //Разные пропуски разных "страниц". Result := false; //MsgBox(IntToStr(CurPage),mbError,MB_OK); If DoUpdate = true then begin //MsgBox('It is update!',mbError,MB_OK); //Если это апдейт If CurPage = 2 then begin //Если это страница лицензии - то показывать не нужно - оно было принято при прошлой установке. Result := true; end; If CurPage = 6 then begin //Если это страница выбора пути. If DirExists(InstallPath) = true then begin //Если папка уже существует //То можно окно выбора пути не показывать. Result := true; end; end; If CurPage = 7 then begin //Если это страница выбора типа установки - он в этом случае всегда "обновление". Result := true; end; If CurPage = 8 then begin //Если это страница выбора папки в меню Пуск Result := true; end; end; If DoNewInstall = true then begin //Если это новая установка. If CurPage = 7 then begin //Если это страница выбора типа установки - он в этом случае всегда "полная". Result := true; end; end; end; [UninstallRun] Filename: {app}\UnInstaller.exe; Parameters: -s; WorkingDir: {app}; StatusMsg: Running application's Installer.exe; Components: AlwaysInstall; Flags: runhidden