在 Inno Setup 中验证目录路径
Validate directory path in Inno Setup
如果您输入无效路径或空路径,Inno Setup 将给出此错误:
我需要创建一个函数来为我执行此操作。目前我正在使用 DirExists
函数,但我认为它没有涵盖我正在寻找的内容。
Inno Setup 所做的验证相对复杂。检查 ValidateCustomDirEdit
函数的源代码以了解它的作用。
下面是翻译成 Pascal Script 的默认 Inno Setup 设置 (AllowUNCPath=yes
, AllowRootDirectory=no
, AllowNetworkDrive=yes
) 代码的非常等价物。请注意,它可能无法与 MBCS 一起正常工作。
procedure TidyUpDirName(var Path: String);
var
Prefix: string;
Prev: string;
begin
StringChangeEx(Path, '/', '\', True);
repeat
Prev := Path;
Path := Trim(Path);
Prefix := '';
if Copy(Path, 1, 2) = '\' then
begin
Prefix := '\';
Path := Copy(Path, 3, Length(Path) - 2);
end;
StringChangeEx(Path, '\', '\', True);
Path := Prefix + Path;
Path := RemoveBackslashUnlessRoot(Path);
until Prev = Path;
end;
function ValidatePath(Path: string): Boolean;
var
I, P: Integer;
S, S2: string;
begin
TidyUpDirName(Path);
Result := False;
if Length(Path) > 240 then Exit;
if Copy(Path, 1, 2) <> '\' then
begin
if (Length(Path) < 4) or
(Uppercase(Path[1])[1] < 'A') or (Uppercase(Path[1])[1] > 'Z') or
(Path[2] <> ':')
or (Path[3] <> '\') then Exit;
end
else
begin
if Pos('\', Copy(Path, 3, Length(Path) - 2)) = 0 then Exit;
end;
for I := 1 to Length(Path) do
begin
if Path[I] <= #31 then Exit;
if (Path[I] = ' ') and
((I = Length(Path)) or (Path[I + 1] = '\')) then Exit;
end;
S := Path;
while Length(S) > 0 do
begin
P := Pos('\', S);
if P > 0 then
begin
S2 := Copy(S, 1, P - 1);
S := Copy(S, P + 1, Length(S) - P);
end
else
begin
S2 := S;
S := '';
end;
S2 := Trim(S2);
if (Length(S2) > 0) and (S2 = StringOfChar('.', Length(S2))) then Exit;
end;
for I := 3 to Length(Path) do
begin
if Pos(Path[I], '/:*?"<>|') > 0 then Exit;
end;
Result := True;
end;
测试:
procedure DoTest(Path: string; Expected: Boolean);
var
Actual: Boolean;
M: string;
begin
Actual := ValidatePath(Path);
M := Format('Path: "%s"; Result: %d; Expected: %d', [
Path, Integer(Actual), Integer(Expected)]);
Log(M);
if Actual <> Expected then RaiseException(M);
end;
procedure Test;
begin
DoTest('C:\path', True);
DoTest('\server\path', True);
DoTest('c:\path', True);
DoTest('C:/path', True);
DoTest('//server/path', True);
DoTest('C:\path ', True);
DoTest(' C:\path ', True);
DoTest('C:\path', True);
DoTest('\server\path', True);
DoTest('C:', False);
DoTest('C:\', False);
DoTest('1:\path', False);
DoTest('|:\path', False);
DoTest('C;\path', False);
DoTest('C:|path\sub', False);
DoTest('\server', False);
DoTest('C:\pa'#27'th', False);
DoTest('C:\path \sub', False);
DoTest('C:\path\sub \sub', False);
DoTest('C:\.', False);
DoTest('C:\..\sub', False);
DoTest('C:\path\.\sub', False);
DoTest('C:\path\ .\sub', False);
DoTest('C:\path\.. \sub', False);
DoTest('C:\path\su:b', False);
DoTest('C:\pa?th\sub', False);
end;
Inno Setup 额外测试驱动器是否存在:
DirExists(ExtractFileDrive(Path))
如果您希望自己的路径编辑框具有与标准 Select 目录页面相同的验证,请使用 CreateInputDirPage
/TInputDirWizardPage
,而不是完全自定义的页面。 TInputDirWizardPage
为您进行验证。
或者您可以调用隐藏的 TInputDirWizardPage
来进行验证。
如果您输入无效路径或空路径,Inno Setup 将给出此错误:
我需要创建一个函数来为我执行此操作。目前我正在使用 DirExists
函数,但我认为它没有涵盖我正在寻找的内容。
Inno Setup 所做的验证相对复杂。检查 ValidateCustomDirEdit
函数的源代码以了解它的作用。
下面是翻译成 Pascal Script 的默认 Inno Setup 设置 (AllowUNCPath=yes
, AllowRootDirectory=no
, AllowNetworkDrive=yes
) 代码的非常等价物。请注意,它可能无法与 MBCS 一起正常工作。
procedure TidyUpDirName(var Path: String);
var
Prefix: string;
Prev: string;
begin
StringChangeEx(Path, '/', '\', True);
repeat
Prev := Path;
Path := Trim(Path);
Prefix := '';
if Copy(Path, 1, 2) = '\' then
begin
Prefix := '\';
Path := Copy(Path, 3, Length(Path) - 2);
end;
StringChangeEx(Path, '\', '\', True);
Path := Prefix + Path;
Path := RemoveBackslashUnlessRoot(Path);
until Prev = Path;
end;
function ValidatePath(Path: string): Boolean;
var
I, P: Integer;
S, S2: string;
begin
TidyUpDirName(Path);
Result := False;
if Length(Path) > 240 then Exit;
if Copy(Path, 1, 2) <> '\' then
begin
if (Length(Path) < 4) or
(Uppercase(Path[1])[1] < 'A') or (Uppercase(Path[1])[1] > 'Z') or
(Path[2] <> ':')
or (Path[3] <> '\') then Exit;
end
else
begin
if Pos('\', Copy(Path, 3, Length(Path) - 2)) = 0 then Exit;
end;
for I := 1 to Length(Path) do
begin
if Path[I] <= #31 then Exit;
if (Path[I] = ' ') and
((I = Length(Path)) or (Path[I + 1] = '\')) then Exit;
end;
S := Path;
while Length(S) > 0 do
begin
P := Pos('\', S);
if P > 0 then
begin
S2 := Copy(S, 1, P - 1);
S := Copy(S, P + 1, Length(S) - P);
end
else
begin
S2 := S;
S := '';
end;
S2 := Trim(S2);
if (Length(S2) > 0) and (S2 = StringOfChar('.', Length(S2))) then Exit;
end;
for I := 3 to Length(Path) do
begin
if Pos(Path[I], '/:*?"<>|') > 0 then Exit;
end;
Result := True;
end;
测试:
procedure DoTest(Path: string; Expected: Boolean);
var
Actual: Boolean;
M: string;
begin
Actual := ValidatePath(Path);
M := Format('Path: "%s"; Result: %d; Expected: %d', [
Path, Integer(Actual), Integer(Expected)]);
Log(M);
if Actual <> Expected then RaiseException(M);
end;
procedure Test;
begin
DoTest('C:\path', True);
DoTest('\server\path', True);
DoTest('c:\path', True);
DoTest('C:/path', True);
DoTest('//server/path', True);
DoTest('C:\path ', True);
DoTest(' C:\path ', True);
DoTest('C:\path', True);
DoTest('\server\path', True);
DoTest('C:', False);
DoTest('C:\', False);
DoTest('1:\path', False);
DoTest('|:\path', False);
DoTest('C;\path', False);
DoTest('C:|path\sub', False);
DoTest('\server', False);
DoTest('C:\pa'#27'th', False);
DoTest('C:\path \sub', False);
DoTest('C:\path\sub \sub', False);
DoTest('C:\.', False);
DoTest('C:\..\sub', False);
DoTest('C:\path\.\sub', False);
DoTest('C:\path\ .\sub', False);
DoTest('C:\path\.. \sub', False);
DoTest('C:\path\su:b', False);
DoTest('C:\pa?th\sub', False);
end;
Inno Setup 额外测试驱动器是否存在:
DirExists(ExtractFileDrive(Path))
如果您希望自己的路径编辑框具有与标准 Select 目录页面相同的验证,请使用 CreateInputDirPage
/TInputDirWizardPage
,而不是完全自定义的页面。 TInputDirWizardPage
为您进行验证。
或者您可以调用隐藏的 TInputDirWizardPage
来进行验证。