В: Как определить, инсталятор запущен на CD - DVD или на HDD. О: Мой вариант:
Code
[Setup] AppName=1 AppVerName=2 DefaultDirName=.
[Code] function GetDriveType( lpRootPathName: PAnsiChar ): UINT; external 'GetDriveTypeA@kernel32.dll stdcall';
function DriveIsCDROM( FileName: string ): boolean; var s: string; i: integer; begin s := ExtractFileDrive( FileName ); if ( s = '' ) then s := ExtractFileDrive( ExpandFileName( FileName ) ); i := GetDriveType( PChar( s ) ); //0-Unknown, 1-NoDrive, 2-Floppy, 3-Fixed, 4-Network, 5-CDROM, 6-RAM Result := ( i = 5 ); end;
function AppInCD:boolean; begin RESULT:=DriveIsCDROM( ParamStr( 0 ) ); end;
procedure InitializeWizard(); begin if AppInCD then MsgBox( 'На CD-DVD' , mbInformation, MB_OK ) else MsgBox( 'На HDD' , mbInformation, MB_OK ) end;
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;
[code] procedure AddToPATH(s: String); var b: string; begin if RegQueryStringValue(HKCU, 'Environment', 'Path', b) then begin if Pos(Ansilowercase(S), AnsiLowercase(b))>0 then Exit; if b[Length(b)]<>';' then b:=b+';'; b:=b+s; RegWriteStringValue(HKCU, 'Environment', 'Path', b); end; end;
procedure RemoveFromPATH(s: String); var b: string; k: Integer; begin if RegQueryStringValue(HKCU, 'Environment', 'Path', b) then begin k:=Pos(Ansilowercase(S), AnsiLowercase(b)); if k=0 then Exit; Delete(b, k, Length(s)); while Pos(';;', b)>0 do StringChange(b, ';;', ';'); RegWriteStringValue(HKCU, 'Environment', 'Path', b); end; end;
//Пример использования procedure CurStepChanged(CurStep: TSetupStep); begin if CurStep=ssPostInstall then AddtoPath(ExpandConstant('{app}')); end;
procedure CurUninstallStepChanged(CurStep: TUninstallStep); begin if CurStep=usUninstall then RemoveFromPath(ExpandConstant('{app}')) end;
В: Как добавить описание к компонентам. О: Вот пример без использования различных dll
Code
[Setup] AppName=My Program AppVerName=My Program 1.5 DefaultDirName={pf}\My Program DefaultGroupName=My Program ComponentsListTVStyle=true
[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;
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;
Как много дел считались невозможными, пока они не были осуществлены. (Гай Плиний Секунд) Не занимаюсь подключением FreeArc/ISDone к чужим скриптам.
Дата: Понедельник, 28.03.2011, 08:09 | Сообщение # 4
Админ
Администратор
Сообщений: 76
Статус: Offline
В: Как определить версию файла: О: Например так:
Code
[Code] #ifdef UNICODE #define A "W" #else #define A "A" #endif function GetFileVersionInfoSize(lptstrFilename: String; lpdwHandle: Integer): Integer; external 'GetFileVersionInfoSize{#A}@version.dll stdcall delayload';
function GetFileVersionInfo(lptstrFilename: String; dwHandle, dwLen: Integer; var lpData: Byte): Boolean; external 'GetFileVersionInfo{#A}@version.dll stdcall delayload';
function VerQueryValue(var pBlock: Byte; lpSubBlock: String; var lplpBuffer: DWord; var puLen: Integer): Boolean; external 'VerQueryValue{#A}@version.dll stdcall delayload';
function GetFileVerInfo(FileName, VerName: String): String; //VerName: //Comments, LegalCopyright, CompanyName, FileDescription, FileVersion, ProductVersion, //InternalName, LegalTrademarks, OriginalFilename, ProductName, PrivateBuild, SpecialBuild var dwLen, puLen, i: Integer; lpFileVerInfo: array of Byte; lplpBufferCP, lplpBufferVN: DWord; LangCodepage: String; begin Result := ''; if FileExists(FileName) then begin dwLen := GetFileVersionInfoSize(FileName, 0); if dwLen > 0 then begin SetArrayLength(lpFileVerInfo, dwLen); if GetFileVersionInfo(FileName, 0, dwLen, lpFileVerInfo[0]) then begin if VerQueryValue(lpFileVerInfo[0], '\VarFileInfo\Translation', lplpBufferCP, puLen) then begin LangCodepage := Format('%.2x%.2x%.2x%.2x', [lpFileVerInfo[(dwLen div 2)-5], lpFileVerInfo[(dwLen div 2)-6], lpFileVerInfo[(dwLen div 2)-3], lpFileVerInfo[(dwLen div 2)-4]]); if VerQueryValue(lpFileVerInfo[0], Format('\%s\%s\%s', ['StringFileInfo', LangCodepage, VerName]), lplpBufferVN, puLen) then begin i := (dwLen div 2) + lplpBufferVN - lplpBufferCP - 6; repeat if lpFileVerInfo[i] <> 0 then begin SetLength(Result, Length(Result)+1); Result[Length(Result)] := Chr(lpFileVerInfo[i]); end; i := i + 1; #ifdef UNICODE until i > (dwLen div 2) + lplpBufferVN - lplpBufferCP - 8 + puLen; #else until lpFileVerInfo[i] = 0; #endif end; end; end; end; end; end;
В: Как сделать минимизацию инсталла на странице инсталляции в левый нижний угол с корректным отображением на любом мониторе с отключенным задним фоном О: Например так:
В: Как из setup.exe извлечь секцию [СОDЕ]? Как или чем можно открыть или распаковать CompiledCode.bin чтоб прочесть секцию [СОDЕ]? О: Извлечь CompiledCode.bin из инсталлятора можно программой InnoUnPacker. Но он будет в псевдоассемблерном виде, так что исходный код не восстановить таким путем. А так просматривай форумы, грызи гранит науки, впитывай знание и со временем красивые инсталы будешь писать своими ручонками. Многие вещи кажутся изысканными пока они происходят не с вами
Сообщение отредактировал Black_angel - Четверг, 21.04.2011, 05:18
В: А как сделать такое: запускаешь инсталлятор, он проверяет установленна ли программа, если нет, то всё как обычно, если да-то он предлагает либо удалить старое, либо запустить программу. О:
Code
#define Name "My Program" #define exe "My Program.exe"
procedure ReadEntries; begin RegQueryStringValue(HKLM, 'SOFTWARE\{#Name}', 'Path', AppDir); end;
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean); begin Confirm:= False; end;
procedure Uninstall(Sender: TObject); begin unins:='unins000.exe'; ReadEntries; if not (FileExists(AddBackslash(AppDir) + unins)) then MsgBox('Невозможно запустить деинсталляцию программы ' + ExpandConstant('{#Name}') + ', т.к. исполняемый файл деинсталляции unins000.exe не найден.', mbCriticalError, MB_OK or MB_DEFBUTTON1) else Exec(AddBackslash(AppDir) + unins, '', ExtractFilePath(AddBackslash(AppDir) + unins), SW_SHOW, ewNoWait, ResultCode); WizardForm.Close; end;
procedure RunProgramm(Sender: TObject); begin run:='{#exe}'; ReadEntries; if (FileExists(AddBackslash(AppDir) + run)) then Exec(AddBackslash(AppDir) + run, '', ExtractFilePath(AddBackslash(AppDir) + run), SW_SHOW, ewNoWait, ResultCode); WizardForm.Close; end;
procedure NewForm; begin ReadEntries; if (RegValueExists(HKLM, 'SOFTWARE\{#Name}', 'Path')) and (FileExists(ExpandConstant(AppDir)+'\{#exe}')) then begin with WizardForm do begin ClientWidth := ScaleX(395); ClientHeight := ScaleY(120); Bevel.Hide; InnerNotebook.Hide; OuterNotebook.Hide; BorderStyle:= bsDialog; Center; with CancelButton do begin Left := WizardForm.CancelButton.Left -100; Top := WizardForm.ClientHeight - CancelButton.Height - ScaleY(10); BringToFront; end; UninsButton:= TButton.Create(WizardForm); with UninsButton do begin Left := WizardForm.NextButton.Left -100; Top := WizardForm.ClientHeight - NextButton.Height - ScaleY(10); Width:= WizardForm.NextButton.Width; Parent:= WizardForm; Caption:= 'Удалить'; OnClick := @Uninstall; BringToFront; end; RunButton:= TButton.Create(WizardForm); with RunButton do begin Left := WizardForm.BackButton.Left -110; Top := WizardForm.ClientHeight - BackButton.Height - ScaleY(10); Width:= WizardForm.BackButton.Width; Parent:= WizardForm; Caption:= 'Запустить'; OnClick := @RunProgramm; BringToFront; end; MyLabel:= TLabel.Create(WizardForm); with MyLabel do begin SetBounds(10,10,380,80); AutoSize:=False; WordWrap:=True; Font.Color:=$000000; Font.Style:=[fsBold]; Font.Size:=10; Parent:=WizardForm; Transparent:=True; Caption:= 'Программа ' + ExpandConstant('{#Name}') + ' уже установлена на Ваш компьютер.' +#13#13+ 'Выберите нужное действие.'; end; end; end; end;
[Code_] procedure InitializeWizard(); begin if ActiveLanguage = 'russian' then begin if not FileExists(ExpandConstant('{tmp}\WizModernImage-IS.bmp')) then ExtractTemporaryFile('WizModernImage-IS.bmp'); WizardForm.WizardBitmapImage.Bitmap.LoadFromFile(ExpandConstant('{tmp}\WizModernImage-IS.bmp')); end; end;
В: Как скрыть страницы инсталлятора? О: Все страницы скрыть невозможно - с версии 5.3.9 одна страница перед установкой показывается в любом случае. Для сокрытия страниц служит функция ShouldSkipPage:
Code
function ShouldSkipPage(PageID: Integer): Boolean; begin if (PageID = wpWelcome)or(PageID =wpReady) then Result:= True; end;
Дата: Воскресенье, 24.04.2011, 09:06 | Сообщение # 11
Местный гуру
Администратор
Сообщений: 150
Статус: Offline
В: Как "прицепить" дополнительную форму к окну инсталятора, чтобы при перетаскивании основной формы она двигалась вместе с ней? О: Нужно перехватывать оконную процедуру основной формы, и при перемещении основной формы перемещать дополнительную. Вот код
Дата: Воскресенье, 24.04.2011, 09:12 | Сообщение # 12
Местный гуру
Администратор
Сообщений: 150
Статус: Offline
В: Я использовал предыдущий пример, а как теперь сделать чтобы при перетаскивании доп. формы двигалась и основная форма? О: Данный код на основе предыдущего примера
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;