Войти

Показать полную графическую версию : Скрипты Inno Setup. Помощь и советы [часть 4]


Страниц : 1 2 3 4 5 6 7 8 [9] 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

valyok666
18-11-2011, 14:32
XXXler, ну я просто хотел помочь=)

leshcat
18-11-2011, 18:15
R.i.m.s.k.y.,

Большое спасибо, проработала точно как надо :)

Еще вопрос... как тосле этого подать команду на рестарт?
Хотел реализовать через shellexec с помощью виндовского 'shutdown /r'.

Rikill
18-11-2011, 18:31
leshcat,
[setup]
AlwaysRestart=yes

leshcat
18-11-2011, 18:42
Rikill,

Нет, это не то, нужна команда shellexec или exec

R.i.m.s.k.y.
18-11-2011, 18:55
Хотел реализовать через shellexec с помощью виндовского 'shutdown /r'. »
а что мешает реализовать с помощью виндовского 'shutdown /r?

El Sanchez
18-11-2011, 19:00
а можно пример "хука на событие установки"? »
Rikill, событие отрисовки.

смысла нет использовать для такой задачи хуки, достаточно сабклассинга »
South, спасибо, различия в терминах усвоил.

Пример кода отрисовки кастомного чекбокса. Реализовал 12 состояний. В качестве изображения для чекбокса взял btnimage.bmp из примеров Restools.


[Setup]
AppName=test
AppVerName=test
CreateAppDir=false
DefaultDirName={tmp}
UsePreviousAppDir=false
UsePreviousGroup=false
AlwaysShowComponentsList=true
FlatComponentsList=false
UsePreviousSetupType=false
UsePreviousTasks=false
UsePreviousUserInfo=false
DisableStartupPrompt=true
Uninstallable=false
AllowNoIcons=yes
BitmapResource=btn:{app}\btnimage.bmp

[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl

[code]
type
TPaintStruct = record
hdc: Longint;
fErase: BOOL;
rcPaint: TRect;
fRestore: BOOL;
fIncUpdate: BOOL;
rgbReserved: array [0..31] of byte;
end;

TCheckBoxArray = array of record
Control: TWinControl;
PrevWndProc: Longint;
end;

const
BM_GETCHECK = $F0;
BM_GETSTATE = $F2;
BST_UNCHECKED = $0;
BST_CHECKED = $1;
BST_INDETERMINATE = $2;
BST_FOCUS = $8;
BST_HOT = $200;
BST_PUSHED = $4;
CN_CTLCOLORSTATIC = $BD38;
WM_PAINT = $F;
COLOR_GRAYTEXT = 17;
COLOR_BTNTEXT = 18;

var
btn: TBitmapImage;
ControlArray: TCheckBoxArray;

function GetWindowLong(hWnd: HWND; nIndex: Integer): Longint; external 'GetWindowLongA@user32.dll stdcall';
function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: Longint): Longint; external 'SetWindowLongA@user32.dll stdcall';
function CallWindowProc(lpPrevWndFunc: Longint; hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint; external 'CallWindowProcA@user32.dll stdcall';
function BeginPaint(hWnd: HWND; var lpPaint: TPaintStruct): Longint; external 'BeginPaint@user32.dll stdcall';
function EndPaint(hWnd: HWND; const lpPaint: TPaintStruct): Boolean; external 'EndPaint@user32.dll stdcall';
function InvalidateRect(hWnd: HWND; lpRect: Longint; bErase: Boolean): Boolean; external 'InvalidateRect@user32.dll stdcall';
function GdiTransparentBlt(hdcDest: Longint; xoriginDest, yoriginDest, wDest, hDest: Integer; hdcSrc: Longint; xoriginSrc, yoriginSrc, wSrc, hSrc: Integer; crTransparent: UINT): Boolean; external 'GdiTransparentBlt@gdi32.dll stdcall';
function DrawText(hDC: Longint; lpchText: PAnsiChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; external 'DrawTextA@user32.dll stdcall';
function SetTextColor(hdc: Longint; crColor: DWORD): DWORD; external 'SetTextColor@gdi32.dll stdcall';
function SetBkMode(hdc: Longint; iBkMode: Integer): Integer; external 'SetBkMode@gdi32.dll stdcall';
function SelectObject(hdc: Longint; hgdiobj: Longint): LongWord; external 'SelectObject@gdi32.dll stdcall';
function GetSysColor(nIndex: Integer): DWORD; external 'GetSysColor@user32.dll stdcall';


function WndProc(hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint;
var
i, id: Integer;
ps: TPaintStruct;
rs: TRect;
begin
Result := 0;
i := GetWindowLong(hWnd, -21);
case Msg of
CN_CTLCOLORSTATIC: InvalidateRect(hWnd, 0, False);
WM_PAINT: begin
InvalidateRect(hWnd, 0, True);
BeginPaint(hWnd, ps);
case SendMessage(hWnd, BM_GETSTATE, 0, 0) of
BST_UNCHECKED + BST_FOCUS: id := 9;
BST_CHECKED + BST_FOCUS: id := 13;
BST_INDETERMINATE + BST_FOCUS: id := 17;

BST_UNCHECKED + BST_HOT: id := 10;
BST_CHECKED + BST_HOT: id := 14;
BST_INDETERMINATE + BST_HOT: id := 18;

BST_UNCHECKED + BST_FOCUS + BST_HOT: id := 10;
BST_CHECKED + BST_FOCUS + BST_HOT: id := 14;
BST_INDETERMINATE + BST_FOCUS + BST_HOT: id := 18;

BST_UNCHECKED + BST_FOCUS + BST_HOT + 100: id := 11;
BST_CHECKED + BST_FOCUS + BST_HOT + 100: id := 15;
BST_INDETERMINATE + BST_FOCUS + BST_HOT + 100: id := 19;

BST_UNCHECKED + BST_FOCUS + BST_HOT + 100 - BST_PUSHED: id := 11;
BST_CHECKED + BST_FOCUS + BST_HOT + 100 - BST_PUSHED: id := 15;
BST_INDETERMINATE + BST_FOCUS + BST_HOT + 100 - BST_PUSHED: id := 19;

BST_UNCHECKED: id := 9;
BST_CHECKED: id := 13;
BST_INDETERMINATE: id := 17;
end;
if not TNewCheckBox(ControlArray[i].Control).Enabled then
case SendMessage(hWnd, BM_GETCHECK, 0, 0) of
BST_UNCHECKED: id := 12;
BST_CHECKED: id := 16;
BST_INDETERMINATE: id := 20;
end;
GdiTransparentBlt(ps.hdc, 0, 0, ps.rcPaint.Bottom, ps.rcPaint.Bottom, btn.Bitmap.Canvas.Handle, id*btn.Bitmap.Height, 0, btn.Bitmap.Height, btn.Bitmap.Height, clFuchsia);
SelectObject(ps.hdc, TNewCheckBox(ControlArray[i].Control).Font.Handle);
SetBkMode(ps.hdc, 1);
if TNewCheckBox(ControlArray[i].Control).Enabled then
SetTextColor(ps.hdc, GetSysColor(COLOR_BTNTEXT)) //ãëîáàëüíûé öâåò òåêñòà ÷åêáîêñà
else
SetTextColor(ps.hdc, GetSysColor(COLOR_GRAYTEXT));
rs.Left := ps.rcPaint.Bottom;
rs.Top := (ps.rcPaint.Bottom - TNewCheckBox(ControlArray[i].Control).Font.Size) div 4; //ïîäãîíêà ïî âåðòèêàëè, íåîïòèìàëüíî
rs.Right := ps.rcPaint.Right - rs.Left;
rs.Bottom := ps.rcPaint.Bottom;
DrawText(ps.hdc, TNewCheckBox(ControlArray[i].Control).Caption, Length(TNewCheckBox(ControlArray[i].Control).Caption), rs, 0);
EndPaint(hWnd, ps);
end;
else Result := CallWindowProc(ControlArray[i].PrevWndProc, hWnd, Msg, wParam, lParam);
end;
end;

procedure SetOwnerDrawCheckBox(Ctrl: TWinControl);
var
i: Integer;
begin
if Assigned(Ctrl) then
begin
for i := 0 to Ctrl.ControlCount-1 do if Ctrl.Controls[i] is TWinControl then
begin
if (Ctrl.Controls[i] is TNewCheckBox) then
begin
SetArrayLength(ControlArray, GetArrayLength(ControlArray)+1);
ControlArray[GetArrayLength(ControlArray)-1].Control := TWinControl(Ctrl.Controls[i]);
ControlArray[GetArrayLength(ControlArray)-1].PrevWndProc := SetWindowLong(TWinControl(Ctrl.Controls[i]).Handle, -4, CallbackAddr('WndProc'));
SetWindowLong(TWinControl(Ctrl.Controls[i]).Handle, -21, GetArrayLength(ControlArray)-1);
end;
if TWinControl(Ctrl.Controls[i]).ControlCount > 0 then SetOwnerDrawCheckBox(TWinControl(Ctrl.Controls[i]));
end;
end;
if not Assigned(Ctrl) then
begin
for i := 0 to GetArrayLength(ControlArray)-1 do SetWindowLong(ControlArray[i].Control.Handle, -4, ControlArray[i].PrevWndProc);
SetArrayLength(ControlArray, 0);
end;
end;


procedure InitializeWizard();
begin
with WizardForm do
begin
OuterNotebook.Hide;
NoIconsCheck.Parent := WizardForm;
NoIconsCheck.Left := 100;
//NoIconsCheck.Height := 24;
NoIconsCheck.Show;
NoIconsCheck.AllowGrayed := True;
//NoIconsCheck.Enabled := False;
btn := TBitmapImage.Create(WizardForm);
btn.Bitmap.LoadFromResourceName(HInstance, '_IS_BTN');
end;
SetOwnerDrawCheckBox(WizardForm);
end;

procedure DeinitializeSetup();
begin
SetOwnerDrawCheckBox(nil);
end;



upd
Доработал еще 9 состояний чекбокса

Devils Night
19-11-2011, 06:42
Еще вопрос... как тосле этого подать команду на рестарт? »Если так например?

[Run]
Filename: shutdown; Parameters: /r /t 10; Flags: runhidden

R.i.m.s.k.y.
19-11-2011, 07:16
Если так например »
а разве не надо указывать полностью имя?
[Run]
Filename: shutdown.exe; Parameters: /r /t 10; Flags: runhidden

Devils Night
19-11-2011, 08:52
а разве не надо указывать полностью имя? »у меня так отработало нормально,
пример из батника брал, там не каких exe не было, в оригинале вообще вот так было
shutdown -r -t 1 -c

OxFFEEDD
19-11-2011, 10:54
Всех приветствую.

Ищу варианты решения одной задачки, по этому решил задать вопросы здесь.

Интересует создание инсталлятора программы FlylinkDC++ для локальной сети, а в частности, сможет-ли движок Inno Setup проделать такой финт:
1. показать пользователю поле ввода для ника;
2. отобразить выпадающий список с ip адресами сетевых интерфейсов, существующих на данный момент в системе;
3. по результатам пользовательского ввода модифицировать файл настроек Flylink'а.

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

Devils Night
19-11-2011, 11:05
Интересует создание инсталлятора программы FlylinkDC++ для локальной сети
Самому писать инсталлятор пока лень »Мда, и лень тему полистать, уже был такой вопрос, valyok666 давал ответ, вот здесь (http://forum.oszone.net/post-1762502.html#post1762502)

OxFFEEDD
19-11-2011, 11:23
Спасибо.
Реестр мне не подходит по определённым причинам. Интересует возможность модификации файла настроек DCPlusPlus.xml во время установки.

Devils Night
19-11-2011, 12:19
Интересует возможность модификации файла настроек DCPlusPlus.xml во время установки. »Подозреваю что нибудь этакое (http://forum.oszone.net/post-1780264.html#post1780264), только ввод в окне инсталятора или что то в этом (http://ddd-dc.ru/) духе. Самого такое интересует.

OxFFEEDD
19-11-2011, 12:36
Извиняюсь за глупые вопросы, времени нехватает на вдумчивое чтение доков по Inno, но функции, вроде DeleteIniEntry являются API вызовами или это скриптовые обёртки? Если это Native API, то можно извратиться в моём случае и воспользоваться MSXML для доступа к данным DCPlusPlus.xml. Но это изврат получается )).

В итоге если хорошо подумать, то остаётся единственный вариант, написать программку, которая делает замену строк по шаблонам и вызывать её с аргументами - строками для замены (ник, ip, каталог), а после установки удалять её, что-бы не искушала пользователей. Так же сделать и при получении списка ip-адресов из системы (я надеюсь Inno Setup позволяет получать вывод вызываемых программ или ошибаюсь?).

R.i.m.s.k.y.
19-11-2011, 13:14
OxFFEEDD,
вот тебе, старче, скрипты инно для работы с XML

OxFFEEDD
19-11-2011, 15:57
Универсальная библиотечка... спасибо. Теперь есть точка опоры, с которой можно начинать!
Осталось реализовать задуманное. Всем удачи!

PS
Кстати, если особо не заморачиваться на формате xml, то можно в файле настроек, предварительно прописав строковые шаблоны типа %nick%, %ip%, %dowload_dir% в соотв. теги, заменить шаблоны на значения, полученные от пользователя с помощью функции StringChangeEx, как вариант.

Devils Night
19-11-2011, 20:27
Как совместить эти два кода?

[Files]
Source: ISTask.dll; DestDir: {app}; Flags: dontcopy

[ Code]
function KillTask(ExeFileName: string): Integer;
external 'KillTask@files:ISTask.dll stdcall delayload';

function RunTask(FileName: string; bFullpath: Boolean): Boolean;
external 'RunTask@files:ISTask.dll stdcall delayload';

//**************************************************//
function InitializeSetup(): Boolean;
begin
If RunTask('winamp.exe', false) then
begin
if MsgBox('Программа Winamp используется. Закрыть и продолжить установку?', mbInformation, mb_YesNo) = idYes then
begin
KillTask('winamp.exe');
Result:= True;
end else
Exit;
end;
Result:=True;
end;


[Files]
Source: ISTask.dll; DestDir: {app}; Flags: ignoreversion

[ Code]
function RunTask(FileName: string; bFullpath: Boolean): Boolean;
external 'RunTask@{app}\ISTask.dll stdcall delayload uninstallonly';
function KillTask(ExeFileName: string): Integer;
external 'KillTask@{app}\ISTask.dll stdcall delayload uninstallonly';

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usUninstall then
if RunTask('winamp.exe', False) then
begin
// прячем форму
UninstallProgressForm.Visible:= False;
if MsgBox('Программа winamp.exe используется. Закрыть и продолжить удаление?', mbConfirmation, MB_YESNO) = IDYES then
begin
KillTask('winamp.exe');
UnloadDll(ExpandConstant('{app}\ISTask.dll'));
// показываем форму
UninstallProgressForm.Visible:= True;
end
else
begin
MsgBox('Завершите работу winamp.exe, затем снова запустите программу удаления.', mbInformation, MB_OK);
UnloadDll(ExpandConstant('{app}\ISTask.dll'));
Abort;
end;
end;
end;

Rikill
20-11-2011, 00:57
Devils Night,

function KillTasks(ExeFileName: string): Integer;
external 'KillTask@files:ISTask.dll stdcall delayload';

function RunTasks(FileName: string; bFullpath: Boolean): Boolean;
external 'RunTask@files:ISTask.dll stdcall delayload';

function RunTask(FileName: string; bFullpath: Boolean): Boolean;
external 'RunTask@{app}\ISTask.dll stdcall delayload uninstallonly';

function KillTask(ExeFileName: string): Integer;
external 'KillTask@{app}\ISTask.dll stdcall delayload uninstallonly';

//**************************************************//
function InitializeSetup(): Boolean;
begin
If RunTasks('Winamp.exe', false) then
begin
if MsgBox('Программа Winamp используется. Закрыть и продолжить установку?', mbInformation, mb_YesNo) = idYes then
begin
KillTasks('Winamp.exe');
Result:= True;
end else
Exit;
end;
Result:=True;
end;


procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usUninstall then
if RunTask('Winamp.exe', False) then
begin
// прячем форму
UninstallProgressForm.Visible:= False;
if MsgBox('Программа winamp.exe используется. Закрыть и продолжить удаление?', mbConfirmation, MB_YESNO) = IDYES then
begin
KillTask('Winamp.exe');
UnloadDll(ExpandConstant('{app}\ISTask.dll'));
// показываем форму
UninstallProgressForm.Visible:= True;
end
else
begin
MsgBox('Завершите работу winamp.exe, затем снова запустите программу удаления.', mbInformation, MB_OK);
UnloadDll(ExpandConstant('{app}\ISTask.dll'));
Abort;
end;
end;
end;

Aplle
20-11-2011, 20:49
Всем Здрасте. Кто может поделиться скриптом для который используеться в этом уроке http://rutracker.org/forum/viewtopic.php?t=2729289 или вобщем скрипт с поддержкой вставки изображения, музыки и разархивации FreeArc для версии 5

Belial4444
21-11-2011, 09:47
Здравствуйте, у меня новая проблема появилась, надеюсь Вы подскажите. Суть проблемы: у меня 2 компонента в установке, первый это файлы игры, 2 это эмулятор для игры, файлы игры запиханы в архив 7з, который лежит рядом с установщиком и извлекается если отмечен 1 компонент, проблема заключается в том, что эмулятор из 2 компонента устанавливается до того, как разархивируются файлы игры, думаю это происходит так потому что инно сетап считает 1 компонент пустым так как там к нему не подключены файлы через секцию [Files] , а просто есть команда на распаковку архива, то есть инно сетап обрабатывает 1 компонент, считает его пустым и распаковывает 2 компонент, а мне нужно чтобы распаковывал только когда извлечется архив. Спасибо за внимание.




© OSzone.net 2001-2012