Поиск в подкаталогах Inno Setup DestDir
Я пытаюсь использовать Inno Setup для распространения файла, используемого в качестве плагина другим приложением. Если он не может найти место назначения плагина, он все равно должен установить себя в каталог Program Files, предоставляя пользователю инструкции вручную.
TLama перед TLama за предоставление некоторого кода, который использовался в аналогичной проблеме: Inno Setup находят подпапку.
В следующем сценарии изложены основные настройки, которые я надеюсь достичь, с комментарием, в котором сценарий является неполным. Я просто в голове.:-)
Как передать найденный каталог обратно
StampTargetDir
(в настоящее время просто MsgBox)Как искать во всех подкаталогах под указанным именем каталога (например, "Марки")
Как ограничить поиск всех подкаталогов (#2) только несколькими именованными подкаталогами, живущими в
{pf}
или же{localappdata}
(то есть "Adobe" и "Acrobat")Сделайте установку плагина файла под
[Files]
при условии нахождения каталога "Марки".
PS Я знаю, что поиск имеет некоторые очевидные недостатки. Однако каталог "Марки" вряд ли будет использоваться в других областях (см. № 3).
[Files]
; Install all the files in a user specified location.
Source: "C:\mydir\readme.pdf"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\mydir\stamp.pdf"; DestDir: "{app}"; Flags: ignoreversion
; If found, install the stamp file in the Adobe Acrobat or Reader Stamp directory.
Source: "C:\mydir\stamp.pdf"; DestDir: "{code:StampTargetDir}"; Flags: ignoreversion
[Tasks]
Name: pf; Description: "&All users on this computer."; GroupDescription: "Configure Acrobat stamp plug-in:"; Flags: exclusive
Name: local; Description: "&Only the current user (me)."; GroupDescription: "Configure Acrobat stamp plug-in:"; Flags: exclusive unchecked
Name: none; Description: "&Do not configure stamps (manual setup)."; GroupDescription: "Configure Acrobat stamp plug-in:"; Flags: exclusive unchecked
[Code]
function GetFirstMatchingSubfolder(const Path: string; out Folder: string): Boolean;
var
S: string;
FindRec: TFindRec;
begin
Result := False;
if FindFirst(ExpandConstant(AddBackslash(Path) + '*'), FindRec) then
try
repeat
// *** THIS DOES NOT SEARCH SUBDIRECTORIES ***
if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0) and
(FindRec.Name <> '.') and (FindRec.Name <> '..') and
(FindRec.Name = 'Stamps') then
begin
Result := True;
Folder := AddBackslash(Path) + FindRec.Name;
end;
until
not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
function StampTargetDir(Param: String): String;
begin
if IsTaskSelected('pf') then
// *** THIS NEEDS TO BE 'Stamps' DIRECTORY FOUND UNDER {pf}
Result := ExpandConstant('{app}') + '\pf'
else if IsTaskSelected('local') then
// *** THIS NEEDS TO BE 'Stamps' DIRECTORY FOUND UNDER {localappdata}
// Assuming {localappdata} is the user's Application Data Folder
// Typically C:\Documents and Settings\username\Application Data.
Result := ExpandConstant('{app}') + '\local'
else
Result := ExpandConstant('{app}') + '\none'
end;
// *** This procedure is just for testing. The results of
// GetFirstMatchingSubfolder should be used by StampTargetDir
procedure InitializeWizard;
var
S: string;
begin
// *** THIS DOES NOT LIMIT SEARCH TO {pf}\Adobe or {pf}\Acrobat *** if GetFirstMatchingSubfolder(ExpandConstant('{pf}'), S) then
MsgBox('An extra copy will go in here: ' + S, mbInformation, MB_OK);
end;
1 ответ
Пройти путь от
InitializeWizard
вStampTargetDir
, используйте глобальную переменную. Хотя я предлагаю вам лучше использоватьCurStepChanged(ssInstall)
вместоInitializeWizard
, если вам не нужен путь раньше, чем во время фактической установки.Использовать рекурсию в
GetFirstMatchingSubfolder
,Самое чистое решение - запустить
GetFirstMatchingSubfolder
несколько раз с определенными корнями (то есть дважды, для Adobe и для Acrobat)использование
Check
параметр.
Код может быть таким:
[Files]
Source: "C:\mydir\stamp.pdf"; DestDir: "{code:GetStampsFolderPath}"; \
Check: WasStampsFolderFound; Flags: ignoreversion
[Code]
const
StampsFolderName = 'Stamps';
var
StampsFolderPath: string;
function WasStampsFolderFound(): Boolean;
begin
Result := (StampsFolderPath <> '');
end;
function GetStampsFolderPath(Params: string): string;
begin
Result := StampsFolderPath;
end;
function GetFirstMatchingSubfolderRecursively(const Path: string; Name: string; out Folder: string): Boolean;
var
FindRec: TFindRec;
FolderPath: string;
begin
Result := False;
Log(Format('Searching in %s', [Path]));
if FindFirst(AddBackslash(Path) + '*', FindRec) then
try
repeat
if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0) then
begin
FolderPath := AddBackslash(Path) + FindRec.Name;
if CompareText(FindRec.Name, Name) = 0 then
begin
Result := True;
Folder := FolderPath;
Log(Format('Match: %s', [Folder]));
end
else
if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
begin
Result := GetFirstMatchingSubfolderRecursively(FolderPath, Name, Folder);
end;
end;
until Result or (not FindNext(FindRec));
finally
FindClose(FindRec);
end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
RootPath: string;
begin
Log(Format('CurStepChanged %d', [CurStep]));
if CurStep = ssInstall then
begin
if IsTaskSelected('pf') then
begin
// this should be pf32 or pf64 specifically,
// depending on where Adobe installs the applications
RootPath := ExpandConstant('{pf}\');
end
else
if IsTaskSelected('local') then
begin
RootPath := ExpandConstant('{localappdata}\');
end;
if RootPath = '' then
begin
Log(Format('No task selected, will not search for %s', [StampsFolderName]));
end
else
begin
Log(Format('Searching for %s folder under %s', [StampsFolderName, RootPath]));
if GetFirstMatchingSubfolderRecursively(RootPath + 'Adobe', StampsFolderName, StampsFolderPath) or
GetFirstMatchingSubfolderRecursively(RootPath + 'Acrobat', StampsFolderName, StampsFolderPath) then
begin
Log(Format('Found %s folder at %s', [StampsFolderName, StampsFolderPath]));
end
else
begin
Log(Format('%s folder not found anywhere', [StampsFolderName]));
end;
end;
end;
end;