Сравнение путей в Inno Setup

#path #compare #inno-setup #pascalscript

#путь #Сравнить #inno-setup #pascalscript

Вопрос:

Есть ли встроенный способ сравнения двух строк, представляющих пути в Inno Setup Pascal? Если не с помощью одной функции, то, возможно, с помощью некоторой нормализации пути.

Наивное сравнение строк, очевидно, некорректно, даже если мы игнорируем регистр с SameText() (согласно правилам Windows).

Как минимум, корректное сравнение должно

  • Трактуют и / как идентичные
  • Игнорируйте несколько разделителей, например \ (используйте их как один, как ОС)
  • Игнорировать конечные разделители (для правильного сравнения путей к каталогам, для чего это в основном необходимо)
  • Разрешать пути ( foo..bar равные bar , по крайней мере, если foo они существуют)
  • и т.д. (правила хорошо известны)
  • Не требуется, чтобы пути действительно существовали в файловой системе.

Разрешение абсолютных и относительных путей является бонусом, но для этого требуется указать текущий путь. Возможно, CWD — это нормально, но я не уверен, что Inno в любом случае принимает относительные пути установки.

Это, должно быть, довольно распространенная задача для установщика, но я удивлен, что не нашел простого, но правильного решения…

Ответ №1:

Объединить ExpandFileName , AddBackslash и SameText :

 function SamePath(P1, P2: string): Boolean;
begin
  P1 := AddBackslash(ExpandFileName(P1));
  P2 := AddBackslash(ExpandFileName(P2));
  Result := SameText(P1, P2);
end;
 

The ExpandFileName :

  • Преобразует / в .
  • Нормализует последовательность любых косых черт до одной обратной косой черты (за исключением ведущих обратных косых черт в UNC-путях).
  • Разрешает относительные пути.

AddBackslash Заботится об игнорировании конечных разделителей.


Тесты:

 procedure TestSamePath(P: string);
begin
  if not SamePath(P, 'C:mypathMyProg.exe') then
    RaiseException('Test failed: '   P);
end;

function InitializeSetup(): Boolean;
begin
  TestSamePath('C:mypathMyProg.exe');
  TestSamePath('C:mypathMYPROG.exe');
  TestSamePath('C:mypath\MyProg.exe');
  TestSamePath('C:/my/path/MyProg.exe');
  TestSamePath('C:my/path//MyProg.exe');
  TestSamePath('C:mypathMyProg.exe');
  TestSamePath('C:my..mypathMyProg.exe');

  SetCurrentDir('C:');
  TestSamePath('mypathMyProg.exe');
  TestSamePath('mypathMyProg.exe');

  SetCurrentDir('C:my');
  TestSamePath('pathMyProg.exe');
  TestSamePath('.pathMyProg.exe');
  Result := True;
end;
 

Комментарии:

1. Да, похоже, это так… ( RemoveBackslashUnlessRoot() также будет работать). Я все еще нахожу удивительным, что для этого нет встроенной функции даже в таком специализированном инструменте (не говоря уже о .NET). ExpandFileName() выполняет 90% работы, но в идеале сравнение должно определить, как использовать регистр символов переносимым способом…