Войти

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


Страниц : 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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

PerfectLove
17-01-2014, 06:00
Исправленный пример в моем предыдущем посте »
Все супер. Пришлось добавить ещё одно "end" после FindClose чтобы заработало. Спасибо огромное.
Есть ещё такой вопрос. Планирую перекинуть некоторые файлы на сервак. На данный момент файл или папка устанавливается только если выбран нужен компонент.
Встречал скрипт как закачивать файл с нета но я никак не могу связать с компонентами. Нужно так чтобы если компонент выбран происходила загрузка файла. Если возможно; файлы в .zip можно будет розпаковать?. Спс.

novahudonoser
17-01-2014, 09:03
С этим кодом все в порядке. Просто вы компилируете на стандартной версии Inno. Установите расширенную версию от китайских собратьев, она есть в шапке соседней темы http://forum.oszone.net/showthread.php?p=1201499# , и проблема исчерпает себя. »
поставил рекомендуемую сборку, всё выполнил по инструкции из той шапки http://clip2net.com/s/6C14gJ
запустил злощастный код, вылезло следующее: http://clip2net.com/s/6C13Ab
дважды переставил и ANSI и UNICODE попробовал, что ж за беда то такая....

saurn
17-01-2014, 09:14
Есть ещё такой вопрос. Планирую перекинуть некоторые файлы на сервак. На данный момент файл или папка устанавливается только если выбран нужен компонент.
Встречал скрипт как закачивать файл с нета но я никак не могу связать с компонентами. Нужно так чтобы если компонент выбран происходила загрузка файла. Если возможно; файлы в .zip можно будет розпаковать?. Спс. »
Было несколько примеров по теме в этой ветке форума.

запустил злощастный код, вылезло следующее »
Несовпадение параметров в файле сообщений. Что-то сделали не так. Вероятнее всего, он у вас от другой версии. Попробуйте версию, которой я пользуюсь is551e.7z (http://rghost.ru/51713629). Замените файлами из архива содержимое папки Inno Setup 5, и попробуйте последний пример из этого поста http://forum.oszone.net/post-2290655-1860.html

novahudonoser
17-01-2014, 09:21
saurn, крутяк!
скопировал из твоего архива Default.isl и всё заработало.
Огромное спасибо за помощь.

novahudonoser
17-01-2014, 09:54
как на этапе установки MsgBox присвоить свой title текст?

а то сейчас там одно не информативное слово "Установка" http://clip2net.com/s/6C1B8x

function InitializeSetup(): Boolean;
begin
Result := not IsProcessRunning('calc.exe');
if not Result then MsgBox('Программа сейчас в работе'+ Chr(10)+'Закройте приложение выбрав пункт меню "Закрыть программу"'+ Chr(10)+'И повторите установку обновления.', mbError, MB_OK);
end;

saurn
17-01-2014, 10:02
как на этапе установки MsgBox присвоить свой title текст? »
Использовать системные MessageBox или форму MsgBoxEx из расширенной версии от китайцев:
MsgBoxEx(Application.Handle, 'Текст сообщения.', 'Заголовок формы', MB_YESNO or MB_ICONWARNING, 0, 0);
Системные MessageBox (http://forum.oszone.net/post-2217135-1111.html)
Расширенный вариант от Johny777 (http://forum.oszone.net/post-2217348-1113.html)

novahudonoser
17-01-2014, 11:36
а кто ещё подскажет как на этапе деинсталяции завершить процесс?
я пробовал пример из Inno Faq 1.4.chm используя ISTask.dll но она не робит, точней не находит процесс и деинсталяции проходит в нормальном режиме[Files]
Source: ISTask.dll; DestDir: {app}; Flags: ignoreversion
// функции используемые при деинсталляции
// RunTask@{app}\ISTask.dll - название функции (в данном случае, если программа работает)
// и путь dll'ки где она расположена...

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('calc.exe', False) then
begin
// прячем форму
UninstallProgressForm.Visible:= False;
if MsgBox('Программа calc.exe используется. Закрыть и продолжить удаление?', mbConfirmation, MB_YESNO) = IDYES then
begin
KillTask('calc.exe');
UnloadDll(ExpandConstant('{app}\ISTask.dll'));
// показываем форму
UninstallProgressForm.Visible:= True;
end
else
begin
MsgBox('Завершите работу calc.exe, затем снова запустите программу удаления.', mbInformation, MB_OK);
UnloadDll(ExpandConstant('{app}\ISTask.dll'));
Abort;
end;
end;
end;

saurn
17-01-2014, 11:50
а кто ещё подскажет как на этапе деинсталяции завершить процесс? »
По тому же принципу, только выполнять завершение процесса следует в теле InitializeUninstall или на шаге usUninstall
#ifndef IS_ENHANCED
#error Enhanced edition of Inno Setup (restools) is required to compile this script
#endif


[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
OutputDir=.


[Code]
#define A = (Defined UNICODE) ? "W" : "A"


const
TH32CS_SNAPPROCESS = $2;
INVALID_HANDLE_VALUE = -1;
PROCESS_TERMINATE = $1;
PROCESS_CREATE_THREAD = $2;
PROCESS_VM_OPERATION = $8;
PROCESS_VM_READ = $10;
PROCESS_VM_WRITE = $20;
PROCESS_QUERY_INFORMATION = $400;
SYNCHRONIZE = $100000;
MEM_COMMIT = $1000;
MEM_RESERVE = $2000;
PAGE_EXECUTE_READWRITE = $40;
TOKEN_QUERY = $8;
TOKEN_ADJUST_PRIVILEGES = $20;
SE_PRIVILEGE_ENABLED = $2;
MAX_PATH = 260;
TA_FAILED = 0;
TA_SUCCESS_CLEAN = 1;
TA_SUCCESS_KILL = 2;
WM_CLOSE = $10;
WAIT_OBJECT_0 = $0;
WAIT_TIMEOUT = $102;


type
TPROCESSENTRY32 = record
dwSize, cntUsage, th32ProcessID: DWORD;
th32DefaultHeapID: Longint;
th32ModuleID, cntThreads, th32ParentProcessID: DWORD;
pcPriClassBase: Longint;
dwFlags: DWORD;
szExeFile: array [0..259] of Char;
end;

LUID = record
LowPart: DWORD;
HighPart: Longint;
end;

LUID_AND_ATTRIBUTES = record
Luid: LUID;
Attributes: DWORD;
end;

TOKEN_PRIVILEGES = record
PrivilegeCount: DWORD;
Privileges: array [0..0] of LUID_AND_ATTRIBUTES;
end;


function CreateToolhelp32Snapshot(dwFlags, th32ProcessID: DWORD): THandle; external 'CreateToolhelp32Snapshot@kernel32.dll stdcall';
#ifdef UNICODE
function Process32First(hSnapshot: THandle; var lppe: TPROCESSENTRY32): Boolean; external 'Process32First{#A}@kernel32.dll stdcall';
function Process32Next(hSnapshot: THandle; var lppe: TPROCESSENTRY32): Boolean; external 'Process32Next{#A}@kernel32.dll stdcall';
#else
function Process32First(hSnapshot: THandle; var lppe: TPROCESSENTRY32): Boolean; external 'Process32First@kernel32.dll stdcall';
function Process32Next(hSnapshot: THandle; var lppe: TPROCESSENTRY32): Boolean; external 'Process32Next@kernel32.dll stdcall';
#endif
function OpenProcess(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; external 'OpenProcess@kernel32.dll stdcall';
function OpenProcessToken(ProcessHandle: THandle; DesiredAccess: DWORD; var TokenHandle: THandle): BOOL; external 'OpenProcessToken@advapi32.dll stdcall';
function GetCurrentProcess(): THandle; external 'GetCurrentProcess@kernel32.dll stdcall';
function LookupPrivilegeValue(lpSystemName, lpName: String; var lpLuid: LUID): BOOL; external 'LookupPrivilegeValue{#A}@advapi32.dll stdcall';
function AdjustTokenPrivileges(TokenHandle: THandle; DisableAllPrivileges: BOOL; NewState: TOKEN_PRIVILEGES; BufferLength: DWORD; var PreviousState: TOKEN_PRIVILEGES; var ReturnLength: Longint): BOOL; external 'AdjustTokenPrivileges@advapi32.dll stdcall';
function CloseHandle(hObject: THandle): BOOL; external 'CloseHandle@kernel32.dll stdcall';
function GetProcessImageFileName(hProcess: THandle; var lpImageFileName: Char; nSize: DWORD): DWORD; external 'GetProcessImageFileName{#A}@psapi.dll stdcall';
function QueryDosDevice(lpDeviceName: String; var lpTargetPath: Char; ucchMax: DWORD): DWORD; external 'QueryDosDevice{#A}@kernel32.dll stdcall';
function EnumWindows(lpEnumFunc, lParam: Longint): BOOL; external 'EnumWindows@user32.dll stdcall';
function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; external 'WaitForSingleObject@kernel32.dll stdcall';
function GetProcAddress(hModule: THandle; lpProcName: String): Longint; external 'GetProcAddress@kernel32.dll stdcall';
function GetModuleHandle(lpModuleName: String): THandle; external 'GetModuleHandle{#A}@kernel32.dll stdcall';
function VirtualAllocEx(hProcess: THandle; lpAddress, dwSize: Longint; flAllocationType, flProtect: DWORD): Longint; external 'VirtualAllocEx@kernel32.dll stdcall';
function WriteProcessMemory(hProcess: THandle; lpBaseAddress, lpBuffer, nSize: Longint; var lpNumberOfBytesWritten: Longint): BOOL; external 'WriteProcessMemory@kernel32.dll stdcall';
function CreateRemoteThread(hProcess: THandle; lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; external 'CreateRemoteThread@kernel32.dll stdcall';
function TerminateProcess(hProcess: THandle; uExitCode: UINT): BOOL; external 'TerminateProcess@kernel32.dll stdcall';
function GetWindowThreadProcessId(hWnd: HWND; var lpdwProcessId: DWORD): DWORD; external 'GetWindowThreadProcessId@user32.dll stdcall';
function GetLogicalDrives: DWord; external 'GetLogicalDrives@kernel32.dll stdcall';


function CharArrayToString(aChar: array of Char): String;
begin
Result := '';
while aChar[Length(Result)] <> #0 do Insert(aChar[Length(Result)], Result, Length(Result)+1);
end;


function EnumWindowsProc(hwnd: HWND; lParam: Longint): BOOL;
var
dwID: DWORD;
begin
GetWindowThreadProcessId(hwnd, dwID);
if dwID = lParam then PostMessage(hwnd, WM_CLOSE, 0, 0);
Result := True;
end;


function TerminateApp(const szProcess: String; dwTimeout: DWORD): DWORD;
var
hProcessSnap, hProc, hToken, hThread, lpProcName: THandle;
pe32: TPROCESSENTRY32;
aBuf: array [0..259] of Char;
szFileName, szDeviceName: String;
tkp: TOKEN_PRIVILEGES;
SeDebugNameValue: LUID;
i, lpMemory, ret: Longint;
lpThreadId, dwDrives: DWORD;
begin
hProcessSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if hProcessSnap = INVALID_HANDLE_VALUE then Exit;
try
pe32.dwSize := SizeOf(pe32);
if not Process32First(hProcessSnap, pe32) then Exit;
while Process32Next(hProcessSnap, pe32) do
begin
if CompareText(CharArrayToString(pe32.szExeFile), ExtractFileName(szProcess)) <> 0 then Continue;
hProc := OpenProcess(PROCESS_TERMINATE or PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE or PROCESS_QUERY_INFORMATION or SYNCHRONIZE, False, pe32.th32ProcessID);
if hProc = TA_FAILED then
begin
if not OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then Exit;
if not LookupPrivilegeValue('', 'SeDebugPrivilege', SeDebugNameValue) then Exit;
try
tkp.PrivilegeCount := 1;
tkp.Privileges[0].Luid := SeDebugNameValue;
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
if not AdjustTokenPrivileges(hToken, False, tkp, SizeOf(tkp), tkp, ret) then Exit;
hProc := OpenProcess(PROCESS_TERMINATE or PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE or PROCESS_QUERY_INFORMATION or SYNCHRONIZE, False, pe32.th32ProcessID);
if hProc = TA_FAILED then Exit;
finally
tkp.Privileges[0].Attributes := 0;
AdjustTokenPrivileges(hToken, False, tkp, SizeOf(tkp), tkp, ret);
CloseHandle(hToken);
end;
end;
if CompareText(szProcess, ExtractFileName(szProcess)) <> 0 then
begin
GetProcessImageFileName(hProc, aBuf[0], SizeOf(aBuf));
szFileName := CharArrayToString(aBuf);
dwDrives := GetLogicalDrives();
for i := 2 to 25 do if dwDrives and (1 shl i) <> 0 then
begin
QueryDosDevice(Format('%s:', [Chr(Ord('A') + i)]), aBuf[0], SizeOf(aBuf));
szDeviceName := CharArrayToString(aBuf);
if Pos(szDeviceName, szFileName) = 0 then Continue;
StringChangeEx(szFileName, szDeviceName, Format('%s:', [Chr(Ord('A') + i)]), True);
if CompareText(szProcess, szFileName) = 0 then Break;
end;
if CompareText(szProcess, szFileName) <> 0 then
begin
CloseHandle(hProc);
Continue;
end;
end;
try
EnumWindows(CallbackAddr('EnumWindowsProc'), pe32.th32ProcessID);
case WaitForSingleObject(hProc, dwTimeout) of
WAIT_OBJECT_0: Result := TA_SUCCESS_CLEAN;
WAIT_TIMEOUT: try
lpProcName := GetProcAddress(GetModuleHandle('kernel32.dll'), 'ExitProcess');
if lpProcName = 0 then Exit;
lpMemory := VirtualAllocEx(hProc, 0, SizeOf(lpProcName), MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if not WriteProcessMemory(hProc, lpMemory, lpProcName, SizeOf(lpProcName), ret) then Exit;
hThread := CreateRemoteThread(hProc, 0, 0, lpMemory, 0, 0, lpThreadId);
if hThread > 0 then
case WaitForSingleObject(hThread, dwTimeout) of
WAIT_OBJECT_0: Result := TA_SUCCESS_CLEAN;
WAIT_TIMEOUT: if TerminateProcess(hProc, 0) then Result := TA_SUCCESS_KILL;
end;
finally
CloseHandle(hThread);
end;
end;
finally
CloseHandle(hProc);
if CompareText(szProcess, ExtractFileName(szProcess)) <> 0 then Exit;
end;
end;
finally
CloseHandle(hProcessSnap);
end;
end;


function IsProcessRunning(FileName: String): Boolean;
var
objSWbemLocator, objSWbemServices: Variant;
begin
try
objSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
except
ShowExceptionMessage;
Exit;
end;

objSWbemServices := objSWbemLocator.ConnectServer();
objSWbemServices.Security_.ImpersonationLevel := 3;
Result := (objSWbemServices.ExecQuery('SELECT * FROM Win32_Process WHERE Name="' + FileName + '"').Count > 0);
end;


function InitializeUninstall(): Boolean;
var
pName: String;
begin
pName := 'calc.exe';

Result := not IsProcessRunning(pName);
if not Result then
begin
TerminateApp(pName, 5000);
Result := True;
end;
end;

vint56
17-01-2014, 14:10
novahudonoser ISTask.dll работает только в ansi в unicode не работает

Mailchik
17-01-2014, 19:08
ISTaskU.dll (http://rghost.ru/51722458)
Как-то давно скомпилил ISTask.dll от Genri для юникодовой Inno Setup.
Большой размер, из-за использования Delphi XE3.
[Setup]
AppName=My Application
AppVersion=1.5
DefaultDirName={pf}\My Application

[Files]
Source: "ISTaskU.dll"; Flags: dontcopy;

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

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

function InitializeSetup(): Boolean;
begin
If RunTask('aimp3.exe', false) then begin
if MsgBox('Закрыть AIMP?', mbError, mb_YesNo) = idYes then begin
KillTask('aimp3.exe');
Result := True;
end else
Exit;
end;
Result := True;
end;

novahudonoser
18-01-2014, 01:27
ребят, есть ещё одна задача которую мне не осилить, помогите плиз!
надо перед установкой проверять наличие REG_SZ ключа в реестре
путь к ключу HKEY_LOCAL_MACHINE\SOFTWARE\TimeCalculator http://clip2net.com/s/6CtciX
если ключ есть то:
> не показывать http://clip2net.com/s/6Ct3EB данную страницу, а путь для установки брать из ключа path и продолжать установку
если ключа нет то:
> продолжать установку в штатном режиме (со страницей выбора пути)

saurn
18-01-2014, 05:07
надо перед установкой проверять наличие REG_SZ ключа в реестре »
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={code:GetInstallDir}
OutputDir=.


[Code]
function GetInstallDir(const Default: String): String;
begin
RegQueryStringValue(HKLM, 'SOFTWARE\TimeCalculator', 'path', Result);
if Result <> '' then RemoveBackslash(Result) else Result := ExpandConstant('{pf}\My Program');
end;


function ShouldSkipPage(PageID: Integer): Boolean;
begin
case PageID of
wpSelectDir: Result := RegValueExists(HKLM, 'SOFTWARE\TimeCalculator', 'path');
end;
end;

novahudonoser
18-01-2014, 10:05
при отсутствии ключа выдает http://clip2net.com/s/6Cxvf0

saurn
18-01-2014, 10:08
при отсутствии ключа выдает »
Потому что запускаете отладку в режиме деинсталяции. Скрипт проверен, и он тут ни причем.

novahudonoser
18-01-2014, 10:22
ой, тупанул )
спасибо большое мил человек, всё работает!


ещё вопросы, если позволите:
1. как удалить тот ключ при деинсталяции

2. как вывести строковый Label на последней странице в котором была бы информация о используемом пути
а то в случае пропуска страницы с выбором пути - юзеру остаётся догадываться куда прога установилась

saurn
18-01-2014, 10:50
как удалить тот ключ при деинсталяции »
[Registry]
Root: HKLM; Subkey: SOFTWARE\TimeCalculator; Flags: dontcreatekey uninsdeletekey;

как вывести строковый Label на последней странице в котором была бы информация о используемом пути
а то в случае пропуска страницы с выбором пути - юзеру остаётся догадываться куда прога установилась »
Тут необязательно что-то изобретать - путь установки будет отображен в ReadyMemo на странице готовности.

novahudonoser
18-01-2014, 11:05
Тут необязательно что-то изобретать - путь установки будет отображен в ReadyMemo на странице готовности. »
я эту страницу не показываю изначально DisableReadyPage=yes
но впринципе её можно показать когда путь берётся из реестра, вопрос только как )

saurn
18-01-2014, 11:26
вопрос только как ) »
Например так:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={code:GetInstallDir}
OutputDir=.


[Code]
function GetInstallDir(const Default: String): String;
begin
RegQueryStringValue(HKLM, 'SOFTWARE\TimeCalculator', 'path', Result);
if Result <> '' then RemoveBackslash(Result) else Result := ExpandConstant('{pf}\My Program');
end;


function ShouldSkipPage(PageID: Integer): Boolean;
var
ValueExists: Boolean;
begin
ValueExists := RegValueExists(HKLM, 'SOFTWARE\TimeCalculator', 'path');

case PageID of
wpSelectDir: Result := ValueExists;
wpReady: Result := not ValueExists;
end;
end;

novahudonoser
18-01-2014, 11:41
по Вашему примеру в обоих случаях (с ключом и без) ReadyPage не отображается
поясню что хотелось:
когда программа устанавливается впервые (ключа в реестре нет)
то ReadyPage не показываем, поскольку пользователю будет предложено самому выбрать путь к программе
а при последующих установках апдейтов - ключ в реестре уже будет, следовательно путь пользователю выбирать предлагаться не будет
вот в этом случае можно и показать ReadyPage чтобы напомнить ему куда апдейт установился.

saurn
18-01-2014, 11:47
novahudonoser, так вы DisableReadyPage=yes из секции Setup уберите




© OSzone.net 2001-2012