搜索Inno Setup DestDir的子目录
我正在尝试使用Inno Setup分发另一个应用程序用作插件的文件。如果找不到插件的目标位置,它仍应将其自身安装到Program Files目录中,为用户提供手动说明。
I am attempting to use Inno Setup to distribute a file used as a plug-in by another application. If it cannot find the plug-in destination, it should still install itself into the Program Files directory, providing the user with manual instructions.
退出Tlama 提供了类似问题中使用的一些代码: Inno Setup查找子文件夹。
Hats off to Tlama for providing some code that was used in a similar problem: Inno Setup find subfolder.
跟随脚本列出了我希望实现的基本设置,并在脚本不完整的地方加了注释。我只是在头上。 :-)
The follow script lays out the basic setup I am hoping to achieve, with comment where the script is incomplete. I'm just in over my head. :-)
-
如何将找到的目录传递回
StampTargetDir
(当前仅是一个MsgBox)
How to pass the found directory back to
StampTargetDir
(currently just a MsgBox)
如何在指定目录名称(例如邮票)下搜索所有子目录
How to search all subdirectories under the specified directory name (i.e. 'Stamps')
如何将所有子目录(#2)的搜索限制为仅存在于 {pf}
或 {localappdata}
(即 Adobe和 Acrobat)
How to limit the search of all subdirectories (#2) to just a few named subdirectories living in {pf}
or {localappdata}
(i.e. "Adobe" and "Acrobat")
在 [文件] 以找到邮票目录为条件。
Make the file plug-in installation under [Files]
conditional on finding the 'Stamps' directory.
PS我知道搜索有一些明显的缺点。但是, Stamps目录不太可能在其他区域中使用(请参阅#3)。
P.S. I know searching has some obvious disadvantages. However the "Stamps" directory is unlikely to be used in other areas (see #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;
-
到将路径从
InitializeWizard
传递到StampTargetDir
,请使用全局变量。尽管我建议您最好使用CurStepChanged(ssInstall)
代替InitializeWizard
,除非您需要比实际安装更早的路径
To pass the path from
InitializeWizard
toStampTargetDir
, use a global variable. Though I suggest you better useCurStepChanged(ssInstall)
instead ofInitializeWizard
, unless you need the path earlier than during the actual installation.
在 GetFirstMatchingSubfolder
中使用递归。
最干净的解决方案是使用特定的根目录多次运行 GetFirstMatchingSubfolder
(即两次,对于Adobe和Acrobat)
The cleanest solution is to run GetFirstMatchingSubfolder
multiple times with specific roots (i.e. twice, for Adobe and for Acrobat)
使用 检查
参数。
代码可以像这样:
[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;