PDA

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


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

Johny777
11-09-2012, 01:22
SatHan,
апдейт предыдущего кода:


#define Section_1 "Section1"
#define Section_2 "Section2"

[Setup]
AppName=Reg_Path_Demo
AppVerName=Reg_Path_Demo
DefaultDirName={pf}\Reg_Path_Demo

// для теста
//appid=Application1
appid=Application2


[Files]
Source: "File\1\*"; DestDir: "{code:Get_Path_0}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "File\2\*"; DestDir: "{code:Get_Path_1}"; Flags: ignoreversion recursesubdirs createallsubdirs


[ code]
var
Page: TInputDirWizardPage;

function Get_Path_0(Param: String): String;
begin
Result := Page.Values[0];
end;

function Get_Path_1(Param: String): String;
begin
Result := Page.Values[1];
end;

procedure InitializeWizard();
begin
Page:=CreateInputDirPage(wpWelcome,'копирование файлов', 'Укажите каталоги','',False,'NewFolder');
with Page do
begin
Add('путь 1:');
Values[0] := RemoveBackslash(ExpandConstant('{reg:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Applic ation1_is1,InstallLocation|C:}')) + '\{#Section_1}';
Add('путь 2:');
Values[1] := RemoveBackslash(ExpandConstant('{reg:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Applic ation2_is1,InstallLocation|C:}')) + '\{#Section_2}'; //
end;
end;

function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
begin
Result := 'путь 1:' + NewLine + Space + Page.Values[0] + NewLine + NewLine + 'путь 2:' + NewLine + Space + Page.Values[1];
end;

function ShouldSkipPage(PageID: Integer): Boolean;
begin
Result := PageID = wpSelectDir;
end;


Если интересно конечно »
Спасибо!
взял на заметку
мало ли может пригодится

MogilShik2007
11-09-2012, 05:27
Johny777, спасибо заработало, интересует:

enablefire(WizardForm.WelcomePage.Handle, 0, 0, bmp.Handle, 50);

у тебя стоит значение 500, эт что такое?

SatHan, там еще 2 переменных меняется
С:\Windows\Temp ))))


И еще, фон окон, можно немного сероватым сделать, скрипт есть какой нибудь простой?

SatHan
11-09-2012, 10:39
там еще 2 переменных меняется
С:\Windows\Temp )))) »Об этом в курсе. то находится в окне Системные переменные.
Они относятся к общей группе будь ты Администратор или Пользователь. я про них не стал описывать из соображений (мало ли). Нет смысла их трогать.
А Переменные среды пользователя XXX - это относится к текущей учётной записи в которой можешь добавлять, изменять и удалять (если знаешь что к чему). туда можно например добавить что то своё. скажем какую нибудь папку. к примеру жмём Создать [Переменная - 7Z] [Значение - C:\Program Files\7-Zip\] и при выполнении %7Z% перейдёт в папку C:\Program Files\7-Zip\
Да хоть Inno. Переменная - INNO, Значение - C:\Program Files\Inno Setup 5\ итог %INNO%

MogilShik2007
11-09-2012, 11:10
Я знаю, эт так к слову написал)))

SatHan, ты кстати с ReDrawText не сталкивался? А то не пойму как разноцветный текст на разных страницах делать)))

El Sanchez
11-09-2012, 13:56
мой вопрос касательно загрузки всего ini файла в переменную с последующим считыванием из этой самой переменной всё ещё более чем в силе! »
Johny777, я б забил на это дело, но если очень хочется:


type
TIniFile = array of record
Section: String; //секция
Entries: array of record //массив записей Name - Value, относящихся к секции
Name: String; //параметр
Value: String; //значение
end;
end;

function ParseIniFile(const Filename: String): TIniFile;
var
iFile: TArrayOfString;
i: Integer;
begin
if not FileExists(Filename) then Exit;
SetArrayLength(Result, 0);
LoadStringsFromFile(Filename, iFile);
for i := 0 to GetArrayLength(iFile)-1 do
begin
//для всех непустых строк, исключая комментарии
if (iFile[i] <> '') and (Copy(iFile[i], 1, 1) <> ';') then
begin
//если строка является секцией...
if (Pos('[', iFile[i]) = 1) and (Pos(']', iFile[i]) = Length(iFile[i])) then
begin
//...пишем в результат имя секции...
SetArrayLength(Result, GetArrayLength(Result)+1);
Result[GetArrayLength(Result)-1].Section := Copy(iFile[i], 2, Length(iFile[i])-2);
end
else
begin
//...иначе пишем пару параметр/значение
SetArrayLength(Result[GetArrayLength(Result)-1].Entries, GetArrayLength(Result[GetArrayLength(Result)-1].Entries)+1);
Result[GetArrayLength(Result)-1].Entries[GetArrayLength(Result[GetArrayLength(Result)-1].Entries)-1].Name := Trim(Copy(iFile[i], 1, Pos('=', iFile[i])-1));
Result[GetArrayLength(Result)-1].Entries[GetArrayLength(Result[GetArrayLength(Result)-1].Entries)-1].Value := Trim(Copy(iFile[i], Pos('=', iFile[i])+1, Length(iFile[i])));
end;
end;
end;
end;

procedure InitializeWizard();
var
iFile: TIniFile;
i, j: Integer;
res: String;
begin
iFile := ParseIniFile('c:\boot.ini');
for i := 0 to GetArrayLength(iFile)-1 do
begin
res := res + '[' + iFile[i].Section + ']' + #13#10;
for j := 0 to GetArrayLength(iFile[i].Entries)-1 do
res := res + iFile[i].Entries[j].Name + '=' + iFile[i].Entries[j].Value + #13#10;
end;
MsgBox(res, mbInformation, MB_OK);
end;

Johny777
11-09-2012, 14:26
El Sanchez,
Спасибо тебе большое за труды! :)

Но неужели "загрузка всего ини в переменную..." не даст почувствовать особую разницу скорости обработки между считыванием строк из переменной и многократным обращением к файлу?

и извиняюсь за тупой вопрос
как теперь считывать значения?

так не работает

iFile := ParseIniFile('C:\setup\Selfish.ini');
...
No_Quit_Dialog := (GetIniString('Constructor', 'Quit_Dialog_Off', '', res) = '1');

неужели он перестал быть ини и теперь нужно искать строку Quit_Dialog_Off=1 целиком

R.i.m.s.k.y.
11-09-2012, 14:43
Но неужели "загрузка всего ини в переменную..." не даст почувствовать особую разницу скорости обработки между считыванием строк из переменной и многократным обращением к файлу? »
Дисковый кэш нивелирует разницу
ИМХО

El Sanchez
11-09-2012, 14:43
Но неужели "загрузка всего ини в переменную..." не даст почувствовать особую разницу скорости обработки между считыванием строк из переменной и многократным обращением к файлу? »
Johny777, тесты покажут. Например, миллион раз прочитать какое либо значение из ini-файла стандартными средствами и пропарсить файл и миллион раз обратиться к какому-либо члену структуры, засечь время, сравнить.

R.i.m.s.k.y.
11-09-2012, 14:45
SatHan, можно еще прописать все эти пути в переменную %PATH%
Но темпы желательно переносить в папки 8.3, без пробелов и русских букв. Как системные темпы, так и пользовательские.
Во избежание.

El Sanchez
11-09-2012, 15:34
как теперь считывать значения? »
неужели он перестал быть ини и теперь нужно искать строку Quit_Dialog_Off=1 целиком »
Johny777, раз это теперь массив записей, то обращение по индексу. Смотри мой пример внимательней, в конце после отработки ParseIniFile идет обращение к элементам массива. Каждый i-ый элемент iFile содержит запись, состоящей из поля Section и поля Entries - массива записей, содержащих 2 поля - Name и Value. Обращение к i-ой секции - iFile[i].Section, к j-ому параметру i-ой секции - iFile[i].Entries[j].Name, к значению j-ого параметра i-ой секции - iFile[i].Entries[j].Value.

тесты покажут. Например, миллион раз »
Потестил, на моей машине обращение к элементам массива примерно в 120 раз быстрее.

Aleksoid1978
11-09-2012, 15:51
Всем привет. На днях нашел тут код как Закрепить значок на панели задач в Win7. Все получилось, кроме одного - при наличии на панели уже такого ярлыка - создается ярлык типа MPC-BE(2).lnk;

Вот сам код

const
installer_mutex = 'mpcbe_setup_mutex';
LOAD_LIBRARY_AS_DATAFILE = $2;

function LoadLibraryEx(lpFileName: String; hFile: THandle; dwFlags: DWORD): THandle; external 'LoadLibraryExW@kernel32.dll stdcall';
function LoadString(hInstance: THandle; uID: SmallInt; var lpBuffer: Char; nBufferMax: Integer): Integer; external 'LoadStringW@user32.dll stdcall';

// thank for code to "El Sanchez" from forum.oszone.net
procedure PinToTaskbar(Filename: String; IsPin: Boolean);
var
hInst: THandle;
buf: array [0..255] of char;
i, Res: Integer;
strVerb: String;
objShell, colVerbs: Variant;
begin
if not FileExists(Filename) then Exit;
if IsPin then Res := 5386 else Res := 5387;
begin
hInst := LoadLibraryEx(ExpandConstant('{sys}\shell32.dll'), 0, LOAD_LIBRARY_AS_DATAFILE);
if hInst <> 0 then
try
for i := 0 to LoadString(hInst, Res, buf[0], 255)-1 do strVerb := strVerb + Buf[i];
try
objShell := CreateOleObject('Shell.Application');
except
ShowExceptionMessage;
Exit;
end;
colVerbs := objShell.Namespace(ExtractFileDir(Filename)).ParseName(ExtractFileName(Filename)).Verbs;
for i := colVerbs.Count downto 1 do if colVerbs.Item[i].Name = strVerb then
begin
colVerbs.Item[i].DoIt;
Break;
end;
finally
FreeDLL(hInst);
end;
end;
end;

вот вызов

if IsTaskSelected('pintotaskbar') then begin
PinToTaskbar(ExpandConstant('{app}\{#mpcbe_exe}'), True);
end;


Получается что задать вручную имя ярлыка в этом случае я немогу. Подскажите гуру Inno :)

SatHan
11-09-2012, 16:01
пути в переменную %PATH% »Спасибо что напомнили. Как раз интересовал вопрос по этому поводу.

Системные переменные
Переменная - Path, значение - %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem
появилась необходимость к значению %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem добавить C:\Program Files\Progs
В идеале при установке должно получится так
%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\Program Files\Progs
как это сделать через инно?
в секции [setup] нашёл ChangesEnvironment=true только мне это мало о чём говорит.

El Sanchez
11-09-2012, 17:42
появилась необходимость к значению %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem добавить C:\Program Files\Progs
В идеале при установке должно получится так
%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\Program Files\Progs
как это сделать через инно? »
SatHan, можно, конечно, и в секции Registry это сделать:

Root: HKLM; Subkey: SYSTEM\CurrentControlSet\Control\Session Manager\Environment; ValueType: expandsz; ValueName: Path; ValueData: {olddata};{app}; Flags: noerror

Но нужно еще проверять наличие вносимого значения, чтобы второй (и больше) раз не вносить одно и тоже, а также удалить значение при деинсталляции. Поэтому лучше свою процедуру накидать. Например:


procedure ManagePathVariable(Variable: String; IsAddVariable: Boolean); //Variable - добавляемое значение; IsAddVariable - флаг добавить/удалить значение
var
Path: String;
begin
if RegQueryStringValue(HKLM, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', Path) then
begin
if IsAddVariable then
if Pos(Lowercase(Variable), Lowercase(Path)) = 0 then
RegWriteExpandStringValue(HKLM, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', Path + ';' + Variable);
if not IsAddVariable then
if Pos(Lowercase(Variable), Lowercase(Path)) > 0 then
begin
StringChangeEx(Path, ';' + Variable, '', True);
RegWriteExpandStringValue(HKLM, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', Path);
end;
end;
end;

//пример вызова
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then ManagePathVariable('%ORACLE_HOME%', True);
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usPostUninstall then ManagePathVariable('%ORACLE_HOME%', False);
end;



в секции [setup] нашёл ChangesEnvironment=true только мне это мало о чём говорит. »
SatHan, разумеется, нужна эта директива

MogilShik2007
11-09-2012, 18:01
Господа, может просветите)))
При работе с ReDrawText как в скрипте прописать, чтоб работало на разных страницах, а не на одной?
Или на одной, но в разных местах...

Или как по другому цвет нужных слов на разных страницах менять?

Johny777
11-09-2012, 18:43
El Sanchez,
блин
чуть мозг себе не спалил нафиг :)
но допер таки как использовать


procedure InitializeWizard();
var
iFile: TIniFile;
i, j: Integer;
res: String;
begin
iFile := ParseIniFile('C:\setup\Selfish.ini');
for i := 0 to GetArrayLength(iFile)-1 do
begin
res := res + '[' + iFile[i].Section + ']' + #13#10;
for j := 0 to GetArrayLength(iFile[i].Entries)-1 do
res := res + iFile[i].Entries[j].Name + '=' + iFile[i].Entries[j].Value + #13#10;
end;
MsgBox(res, mbInformation, MB_OK);


//// первая 2-ка - номер секции (отсчёт от нуля) вторая 2-ка - номер ключа секциии(отсчёт от нуля)
Variable := iFile[2].Entries[2].Value = '1' /// отсчёт от нуля
if Variable = True then MsgBox('ок', mbInformation, MB_OK);
end;

скажи только пожалуйста как получить индекс ключа и секции по имени оных?

на моей машине обращение к элементам массива примерно в 120 раз быстрее. »
Здраво!
конечно смысла считывать из одной секции значение одного ключа - слишком, но для длинных ini этот код себя 120 раз оправдает

=============================================================

Получается что задать вручную имя ярлыка в этом случае я немогу. »
что ты имеешь в виду под именем?
на панели задач ярлыки - только иконки
если ты имеешь в виду имя файла, то файл(вместе с путём к нему) к которому ты хочешь протянуть ярлык указывается в первом входном параметре функции PinToTaskbar

R.i.m.s.k.y.
11-09-2012, 18:48
El Sanchez, SatHan, я тоже поначалу так пробовал, полная фигня получается
Теперь делаю через стороннюю утилитку pathman (http://sendfile.su/668116)
[Run]
Filename: {app}\PATHMAN.EXE; Parameters: " /as ""{app}"""; Flags: runhidden waituntilterminated

[UninstallRun]
Filename: {app}\PATHMAN.EXE; Parameters: " /rs ""{app}\"""; Flags: runhidden waituntilterminated

El Sanchez
11-09-2012, 23:14
скажи только пожалуйста как получить индекс ключа и секции по имени оных? »
Johny777, перебором элементов массив(ов)а. Ты, пока не исправил свой пост, использовал функцию IndexOf класса TStrings. С его использованием код можно упростить, ведь в арсенале TStrings есть все необходимое для обработки строк типа name=value:


type
TIniFile = array of record
Section: String;
Entries: TStringList;
end;

function ParseIniFile(const Filename: String): TIniFile;
var
iFile: TArrayOfString;
i: Integer;
begin
if not FileExists(Filename) then Exit;
SetArrayLength(Result, 0);
LoadStringsFromFile(Filename, iFile);
for i := 0 to GetArrayLength(iFile)-1 do
begin
//для всех непустых строк, исключая комментарии
if (iFile[i] <> '') and (Copy(iFile[i], 1, 1) <> ';') then
begin
//если строка является секцией...
if (Pos('[', iFile[i]) = 1) and (Pos(']', iFile[i]) = Length(iFile[i])) then
begin
//...пишем в результат имя секции...
SetArrayLength(Result, GetArrayLength(Result)+1);
Result[GetArrayLength(Result)-1].Section := Copy(iFile[i], 2, Length(iFile[i])-2);
end
else
begin
//...иначе пишем пару параметр/значение
if TObject(Result[GetArrayLength(Result)-1].Entries) = nil then
Result[GetArrayLength(Result)-1].Entries := TStringList.Create;
Result[GetArrayLength(Result)-1].Entries.Append(iFile[i]);
end;
end;
end;
end;

//своя функция для чтения значений параметров из секций
function GetIniValue(const Section, Key, Default: String; iFile: TIniFile): String;
var
i, j: Integer;
begin
Result := Default;
for i := 0 to GetArrayLength(iFile)-1 do if CompareText(iFile[i].Section, Section) = 0 then
begin
for j := 0 to iFile[i].Entries.Count-1 do if CompareText(iFile[i].Entries.Names[j], Key) = 0 then
begin
Result := iFile[i].Entries.Values[Key];
Break;
end;
Break;
end;
end;

procedure InitializeWizard();
var
iFile: TIniFile;
i: Integer;
res: String;
begin
//парсим ini-файл
iFile := ParseIniFile('d:\Program Files (x86)\Inno Setup 5\projects\johny777\test.ini');

//пример 1 - выводим на экран содержимое ini-файла, используя созданную переменную iFile
for i := 0 to GetArrayLength(iFile)-1 do
res := res + '[' + iFile[i].Section + ']' + #13#10 + iFile[i].Entries.Text;
MsgBox(res, mbInformation, MB_OK);

//пример 2 - выводим на экран значение параметра name34 секции section2, используя созданную переменную iFile и свою функцию GetIniValue
MsgBox(GetIniValue('section2', 'name34', '', iFile), mbInformation, MB_OK);
end;



я тоже поначалу так пробовал, полная фигня получается
Теперь делаю через стороннюю утилитку pathman »
R.i.m.s.k.y., например? Это вполне нормальный способ, вышеназванная утилита делает то же самое.

Johny777
12-09-2012, 01:22
Ты, пока не исправил свой пост, использовал функцию IndexOf класса TStrings »
да
пока не подумал, что не подходит тк у тебя свой тип - TIniFile и что нужна самописная функция поиска индекса
Оказалось в правильном направлении подумал (радует :) )

ReDrawText не сталкивался? А то не пойму как разноцветный текст на разных страницах делать »
а в чём собственно говоря проблема?
ты же судя по коду уже сделал разноцветный текст на первой странице
вот держи
у меня есть другой пример отрисовки текста http://sendfile.su/668402
попробуй с ним
используй функцию
function WriteText(s: string; Left, Top, Right: integer; Parent: TWinControl): TLabelString;
.............название(твой текст; слева, сверху, ширина; родитель(например WizardForm.WelcomePage):

у тебя стоит значение 500, эт что такое? »
кажись интенсивность огня
поиграйся с настройкой - узнаешь

вот держи набор китайских библиотек с примерами http://sendfile.su/668398

Aleksoid1978
12-09-2012, 01:58
Johny777, что ты имеешь в виду под именем?
на панели задач ярлыки - только иконки
если ты имеешь в виду имя файла, то файл(вместе с путём к нему) к которому ты хочешь протянуть ярлык указывается в первом входном параметре функции PinToTaskbar »

Я говорил про имя создаваемого ярлыка.

Johny777
12-09-2012, 02:14
Я говорил про имя создаваемого ярлыка. »
я не совсем догоняю
смотри скрин

http://img802.imageshack.us/img802/8297/28605916.png (http://imageshack.us/photo/my-images/802/28605916.png/)

у значков в панели задач (куда функция El Sanchez-а их закрепляет) нет имени




© OSzone.net 2001-2012