PDA

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


Страниц : 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

ivan_rolos
08-04-2022, 19:57
Та я вроде не играю в Павлика Морозова.
четко сказал что нужно в инсталляторе прочитать свойство файла (Описание файла).

Vanadiy777
08-04-2022, 20:55
четко сказал что нужно в инсталляторе прочитать свойство файла (Описание файла). »
ivan_rolos, сценарий инсталлятора дайте, может вместе что и придумаем...
Ну, или сами дальше тогда...

Flix
08-04-2022, 21:33
Как можно прочитать свойства файла? »
Вот так (http://forum.oszone.net/post-1643761-1146.html).

Vanadiy777
30-05-2022, 15:19
Коллеги, всем доброго времени суток!

Подскажите пожалуйста, есть ли решение, как заменить иконку в MsgBox вместо mbError, mbInformation, и т.д. на свою, другую иконку, которая будет браться из системных файлов Windows?

Заранее, спасибо.

iglezz
31-05-2022, 15:30
Vanadiy777,
В WinAPI есть функция MessageBoxIndirect, которая позволяет использовать произвольный значок.
Здесь на форуме есть её реализация (ссылка (http://forum.oszone.net/post-2217348.html#post2217348)), но неполная -- требуется небольшой допилинг для загрузки своего значка.

Vanadiy777
31-05-2022, 18:06
iglezz, спасибо, буду изучать...
Правда не уверен, что получится, для меня сложновато...

iglezz
31-05-2022, 20:19
Vanadiy777,
Поковырял тот образец, удалось в MessageBoxIndirect отобразить значок из 32/64-бит PE-файла (dll/exe/icl).
ico использовать нельзя.

Пример смогу выложить позже, т.к. код ещё причесать надо.

Vanadiy777
31-05-2022, 20:57
Пример смогу выложить позже, т.к. код ещё причесать надо. »
iglezz, буду Вам очень признателен, если поможете, т.к. сам, видимо, не разберусь...

Мне надо взять два разных значка из одной системной dll, и в зависимости от события вывести этот значок в MsgBox.

iglezz
01-06-2022, 14:40
В итоге получилать такая матрёшка...

Функция MsgBoxEx (на базе MessageBoxIndirect) может служить полной заменой стандартному MsgBox.

MsgBoxEx('Сообщение', 'Заголовок', 0, ЗНАЧОК, ФЛАГИ) - стандартный значок
MsgBoxEx('Сообщение', 'Заголовок', '', ЗНАЧОК, ФЛАГИ) - значок из установщика
MsgBoxEx('Сообщение', 'Заголовок', 'ФАЙЛ', ЗНАЧОК, ФЛАГИ) - значок из 32/64-бит PE-файла (exe/dll/icl/...)

В константах IDI_SHIELD и IDI_APPLICATION два новых значка.

ЗНАЧОК задаётся константой MB_ICON*, IDI_* либо числом, либо 'строкой' ('MAINICON').

Если файл со значком открыть не удаётся, то устанавливается значок IDI_APPLICATION

Коды возврата, флаги, стандартные значки MB_ICON* соответствуют стандартному месседжбоксу.
#define APPNAME "MessageBoxIndirect test"

[Setup]
AppName={#APPNAME}
AppVersion=0.1
DisableWelcomePage=yes
DefaultDirName={tmp}\{#APPNAME}
OutputDir=.
OutputBaseFilename={#APPNAME}
PrivilegesRequired=lowest


[code]
#include 'WinAPI_MessageBoxIndirect.pas'

procedure initializeWizard();
var
dllname: String;
ret: Integer;
begin
// Standard icons:
MsgBox('std mbInformation', mbInformation, MB_OK);
MsgBoxEx('ex IDI_INFORMATION', '{#APPNAME}', 0, IDI_INFORMATION, MB_OK);
MsgBox('std mbConfirmation', mbConfirmation, MB_OK);
MsgBoxEx('ex IDI_QUESTION', '{#APPNAME}', 0, IDI_QUESTION, MB_OK);
MsgBox('std mbError', mbError, MB_OK);
MsgBoxEx('ex IDI_EXCLAMATION', '{#APPNAME}', 0, IDI_EXCLAMATION, MB_OK);
MsgBox('std mbCriticalError', mbCriticalError, MB_OK);
MsgBoxEx('ex IDI_ERROR', '{#APPNAME}', 0, IDI_ERROR, MB_OK);
MsgBoxEx('ex IDI_SHIELD', '{#APPNAME}', 0, IDI_SHIELD, MB_OK);
MsgBoxEx('ex IDI_APPLICATION', '{#APPNAME}', 0, IDI_APPLICATION, MB_OK);

// Icon from installer
MsgBoxEx('Installer icon', '{#APPNAME}', '', 'MAINICON', MB_OK)

// Icon from exe/dll file
dllname := 'C:\Program Files\Totalcmd\TOTALCMD.EXE'
MsgBoxEx('app icon (text)'#10'from'#10+dllname, '{#APPNAME}', dllname, 'MAINICON', MB_OK)
MsgBoxEx('app icon (num)'#10'from'#10+dllname, '{#APPNAME}', dllname, 6, MB_OK)

// Icon from exe/dll file. failed to load.
MsgBoxEx('LoadLibrary error', '{#APPNAME}', 'x:\notexist', 'MAINICON', MB_OK)

// Return code test loop
dllname := 'C:\Windows\SysWOW64\shell32.dll'
while true do
begin
ret := MsgBoxEx('icon from'#10+dllname, '{#APPNAME}', dllname, 337, MB_YESNOCANCEL or MB_DEFBUTTON2);

case ret of
IDYES:
ret := MsgBoxEx('YES'#10#10'Continue?', '{#APPNAME}', dllname, 16802, MB_YESNO);
IDNO:
ret := MsgBoxEx('NO'#10#10'Continue?', '{#APPNAME}', dllname, 240, MB_YESNO);
IDCANCEL:
ret := MsgBoxEx('CANCEL'#10#10'Continue?', '{#APPNAME}', dllname, 142, MB_YESNO);
end;
if ret = IDNO then break;
end;


Abort;
end;
#ifndef WinAPI_MessageBoxIndirect__pas
#define WinAPI_MessageBoxIndirect__pas


#include 'WinAPI.pas'
#include 'WinAPILoader.pas'

const
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
MB_CANCELTRYCONTINUE = $00000006;

MB_ICONERROR = $00000010;
MB_ICONSTOP = MB_ICONERROR;
MB_ICONHAND = MB_ICONERROR;
MB_ICONQUESTION = $00000020;
MB_ICONWARNING = $00000030;
MB_ICONEXCLAMATION = MB_ICONWARNING;
MB_ICONINFORMATION = $00000040;
MB_ICONASTERISK = MB_ICONINFORMATION;
MB_USERICON = $00000080;

// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadiconw
IDI_APPLICATION = 32512;
IDI_INFORMATION = 32516;
IDI_ASTERISK = IDI_INFORMATION;
IDI_ERROR = 32513;
IDI_HAND = IDI_ERROR;
IDI_WARNING = 32515;
IDI_EXCLAMATION = IDI_WARNING;
IDI_QUESTION = 32514;
IDI_SHIELD = 32518;

IDTRYAGAIN = 10;
IDCONTINUE = 11;

type

// MSGBOXPARAMSW structure
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msgboxparamsw
// lpszIcon - string type
_WinAPI_tagMSGBOXPARAMS_S = record
cbSize: UINT;
hwndOwner: HWND;
hInstance: HINST;
lpszText: String;
lpszCaption: String;
dwStyle: DWORD;
lpszIcon: String;
dwContextHelpId: DWORD_PTR;
lpfnMsgBoxCallback: Pointer;
dwLanguageId: DWORD;
end;
// lpszIcon - numeric type
_WinAPI_tagMSGBOXPARAMS_N = record
cbSize: UINT;
hwndOwner: HWND;
hInstance: HINST;
lpszText: String;
lpszCaption: String;
dwStyle: DWORD;
lpszIcon: DWORD;
dwContextHelpId: DWORD_PTR;
lpfnMsgBoxCallback: Pointer;
dwLanguageId: DWORD;
end;


// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxindirectw
function _WinAPI_MessageBoxIndirect_S(const MsgBoxParams: _WinAPI_tagMSGBOXPARAMS_S): Integer; external 'MessageBoxIndirectW@user32.dll stdcall';

function _WinAPI_MessageBoxIndirect_N(const MsgBoxParams: _WinAPI_tagMSGBOXPARAMS_N): Integer; external 'MessageBoxIndirectW@user32.dll stdcall';




function MsgBoxExNI(
const Text: String;
const Caption: String;
const hInstance: HINST;
const IconNumber: DWORD;
const Flags: DWORD
): Integer;
var
mp: _WinAPI_tagMSGBOXPARAMS_N;
begin
mp.cbSize := SizeOf(mp);
mp.hInstance := hInstance;
mp.lpszText := Text;
mp.lpszCaption := Caption;

if (IconNumber < IDI_APPLICATION) and (hInstance = 0) then
mp.dwStyle := Flags or IconNumber
else
begin
mp.dwStyle := Flags or MB_USERICON;
mp.lpszIcon := IconNumber;
end;

Result := _WinAPI_MessageBoxIndirect_N(mp);
end;


function MsgBoxExSI(
const Text: String;
const Caption: String;
const hInstance: HINST;
const IconName: String;
const Flags: DWORD
): Integer;
var
mp: _WinAPI_tagMSGBOXPARAMS_S;
begin
mp.cbSize := SizeOf(mp);
mp.hInstance := hInstance;
mp.lpszText := Text;
mp.lpszCaption := Caption;
mp.dwStyle := Flags or MB_USERICON;
mp.lpszIcon := IconName;

Result := _WinAPI_MessageBoxIndirect_S(mp);
end;

(* function MsgBoxEx


Text: `Messagebox text`

Caption: `Messagebox caption`

IconSource: 0 -- standard icons: MB_ICON*, IDI_*
: '' -- load icon from INSTALLER_EXE
: 'FILE' -- load icon from FILE

IconID: MB_ICON*, IDI_* -- if IconSource = 0
: <icon name/number> if IconSource = '*'

Flags: MB_OK, MB_OKCANCEL, MB_ABORTRETRYIGNORE, MB_YESNOCANCEL, MB_YESNO,
MB_RETRYCANCEL, MB_CANCELTRYCONTINUE,
MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3, MB_SETFOREGROUND


Return: IDOK, IDCANCEL, IDABORT, IDRETRY, IDIGNORE, IDYES, IDNO, IDTRYAGAIN, IDCONTINUE
*)
function MsgBoxEx(
const Text: String;
const Caption: String;
const IconSource: Variant;
const IconID: Variant;
const Flags: DWORD
): Integer;
var
hInstance: HINST;
UsedIconID: Variant;
begin
hInstance := 0;
UsedIconID := IconID;

if VarType(IconSource) <> varInteger then
begin
if IconSource = '' then
hInstance := _WinAPI_GetModuleHandle('')
else
hInstance := _WinAPI_LoadLibraryEx(IconSource, 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE);

if hInstance = 0 then
UsedIconID := IDI_APPLICATION // fallback to 'defaulticon'
end;

if VarType(UsedIconID) = varInteger then
Result := MsgBoxExNI(Text, Caption, hInstance, UsedIconID, Flags)
else
Result := MsgBoxExSI(Text, Caption, hInstance, UsedIconID, Flags);

if (hInstance > 0) and (IconSource <> '') then _WinAPI_FreeLibrary(hInstance);
end;


#endif
#ifndef WinAPILoader__pas
#define WinAPILoader__pas


#include 'WinAPI.pas'

const
LOAD_LIBRARY_AS_IMAGE_RESOURCE = $20;
LOAD_LIBRARY_AS_DATAFILE = $2;

// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw
function _WinAPI_LoadLibraryEx(const lpLibFileName: String; const Zero: Integer; const dwFlags: DWORD): HINST; external 'LoadLibraryExW@Kernel32.dll stdcall';

// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary
function _WinAPI_FreeLibrary(const hLibModule: HINST): Boolean; external 'FreeLibrary@Kernel32.dll stdcall';

// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlew
function _WinAPI_GetModuleHandle(const ModuleName: String): HINST; external 'GetModuleHandleW@Kernel32.dll stdcall';


#endif
#ifndef WinAPI__pas
#define WinAPI__pas


type
Pointer = Longint;

HINST = THandle;


#endif

Пришлось использовать две разные структуры и функции, т.к. мне непонятно как можно числовое значение преобразовать в LPCWSTR.

Vanadiy777
08-06-2022, 00:26
iglezz,
Пример собрал, прикрутил все подключаемые модули. Все отрабатывает как надо.
Попробовал прикрутить к своему скрипту - отрабатывает окно MsgBoxEx, т.е. выскакивает второе окошко, но, ни заголовок окна, ни значок в окне не отображаются.
При этом все флаги отрабатывают. Т.е., функционал весь и работоспособность сохраняются.

Возможно, возникает конфликт с моим, имеющемся кодом...
Буду разбираться...

iglezz, Вам, от всей души, огромное спасибо за предоставленный материал и примеры!

Vanadiy777
10-06-2022, 15:28
iglezz,
Разобрался в чем у меня была ошибка.
Все получилось и замечательно работает!
ico/icl использовать нельзя. »
Свою icl можно тоже использовать, заменив расширение на dll, у меня в таком варианте тоже заработало.

Еще раз - сердечное спасибо Вам! :Beer:

iglezz
10-06-2022, 16:06
Vanadiy777,
По .icl я ошибся, давно с ними дела не имел.
В общем, icl - это просто исполняемый файл с ресурсами Icon внутри.
32/64-бит PE-файлы (https://en.wikipedia.org/wiki/Portable_Executable) можно использовать, старинные 16-бит NE-файлы (https://en.wikipedia.org/wiki/New_Executable) -- нельзя.
Переименовывать необязательно.

ЗЫ Свои посты выше обновил с учётом этой информации

ZVSRus
11-06-2022, 14:26
iglezz
Есть ли в вашем примере возможность менять размер иконки, например с 32х32 на 48х48 или 64х64

iglezz
11-06-2022, 14:29
ZVSRus,
Нет, такое не предусмотрено.

ZVSRus
11-06-2022, 14:40
iglezz
ОК. Всё понял. А жаль.

Vanadiy777
11-06-2022, 14:53
iglezz,
проверил с .icl не изменяя расширение, тоже все нормально отработало.
icl собирал в ArtIcons.

Спасибо Вам, добрый человек!

serg5
05-07-2022, 18:48
Скрипт для двух .exe в одном инсталляторе.
Чтобы можно было выбирать какую программу устанавливать.
Может кто подскажет ?

Vanadiy777
05-07-2022, 22:50
serg5,
[Setup]
AppName=My Prog
AppVerName=My Prog
AppVersion=1.5
DefaultDirName={tmp}
OutputBaseFilename=My Setup
Uninstallable=no
DisableProgramGroupPage=True
DisableDirPage=True
DisableReadyPage=True
DisableReadyMemo=True
DisableFinishedPage=True
ShowLanguageDialog=Auto

[Languages]
Name: EN; MessagesFile: compiler:Default.isl
Name: RU; MessagesFile: compiler:Languages\Russian.isl

[Tasks]
Name: "MyProg1"; Description: "Моя программа 1"; Flags: unchecked;
Name: "MyProg2"; Description: "Моя программа 2"; Flags: unchecked;

[Files]
Source: MyProg1.exe; DestDir: {app}; Flags: ignoreversion; Tasks: MyProg1;
Source: MyProg2.exe; DestDir: {app}; Flags: ignoreversion; Tasks: MyProg2;


[Run]
Filename: "{app}\MyProg1.exe.exe"; Parameters: "Сюда добавляете ключи для установки программы"; Flags: waituntilterminated; Tasks: MyProg1;
Filename: "{app}\MyProg2.exe.exe"; Parameters: "Сюда добавляете ключи для установки программы"; Flags: waituntilterminated; Tasks: MyProg2;

serg5
06-07-2022, 11:49
Вот простейший пример: »

Если нужны разные пути для установки ?
В "setup" прописывается только один путь..

Vanadiy777
06-07-2022, 12:16
В "setup" прописывается только один путь.. »
serg5,
ну так правильно, прописана временная папка. Оттуда уже запускается установщик той программы, которую Вы выбрали для установки.
Или не это было нужно?
Скрипт для двух .exe в одном инсталляторе.
Чтобы можно было выбирать какую программу устанавливать. »




© OSzone.net 2001-2012