WiX DirectorySearch/@Depth игнорируется, если используется более одного раза в одном дереве.

У меня есть установщик WiX, который устанавливает кучу файлов расширения в каталог приложения для другого приложения. Чтобы гарантировать, что файлы окажутся в нужном месте, я использую несколько вложенных DirectorySearch для поиска каталога приложения.

Приложение обычно устанавливается по следующему шаблону:

\Program Files (x86)\CompanyName\ProductName\[version]\[environment]\[optional intermediate folder]\AppFolderName

Другими словами, общие папки установки включают:

\Program Files (x86)\CompanyName\ProductName\1.0\Prod\AppFolderName
\Program Files (x86)\CompanyName\ProductName\1.1\Prod\OptionalFolderName\AppFolderName
\Program Files (x86)\CompanyName\ProductName\1.2\Test\AppFolderName
\Program Files (x86)\CompanyName\ProductName\1.2\Test\OptionalFolderName\AppFolderName

Чтобы справиться с этим, я использую вложенный набор элементов DirectorySearch для назначения пути к свойству. Следующее работает, если присутствует необязательная папка (OptionalFolderName):

<Property Id="SOMEAPPFOLDER">
  <DirectorySearch Id="ProgramFilesFolder" Path="[ProgramFilesFolder]">
    <DirectorySearch Id="CompanyNameFolder" Path="CompanyName">
      <DirectorySearch Id="ProductFolder" Path="ProductName">
          <DirectorySearch Id="EnvironmentFolder" Path="$(var.ENVIRONMENTNAME)" Depth="2">
            <DirectorySearch Id="OptionalIntermediateFolder" Path="OptionalFolderName">
              <DirectorySearch Id="AppFolder" Path="AppFolderName" AssignToProperty="yes">
                <FileSearch Id="AppNameExe" Name="AppName.exe" MinVersion="$(var.MIN_VERSION).0" MaxVersion="$(var.MAX_VERSION).999" />
              </DirectorySearch>
            </DirectorySearch>
        </DirectorySearch>
      </DirectorySearch>
    </DirectorySearch>
  </DirectorySearch>
</Property>

Однако, поскольку OptionalFolderName является необязательным, я хочу использовать DirectorySearch, чтобы определить, находится ли папка приложения непосредственно в папке среды или на один уровень ниже. Пытаясь сделать это, я изменил дерево поиска на:

<Property Id="SOMEAPPFOLDER">
  <DirectorySearch Id="ProgramFilesFolder" Path="[ProgramFilesFolder]">
    <DirectorySearch Id="CompanyNameFolder" Path="CompanyName">
      <DirectorySearch Id="ProductFolder" Path="ProductName">
        <DirectorySearch Id="EnvironmentFolder" Path="$(var.ENVIRONMENTNAME)" Depth="2">
          <DirectorySearch Id="AppFolder" Path="AppFolderName" Depth="2" AssignToProperty="yes">
            <FileSearch Id="AppNameExe" Name="AppName.exe" MinVersion="$(var.MIN_VERSION).0" MaxVersion="$(var.MAX_VERSION).999" />
          </DirectorySearch>
        </DirectorySearch>
      </DirectorySearch>
    </DirectorySearch>
  </DirectorySearch>
</Property>

Однако более поздняя версия не работает, если присутствует необязательная папка, но работает, если ее нет. Другими словами, как будто игнорируется один из атрибутов глубины; я предполагаю, что это связано с тем, что я дважды использую атрибут глубины на разных уровнях дерева.

Любые предложения о том, как я могу обойти это?


Обновление — добавлен фрагмент фрагмента журнала из msiexec /i [msiname] /l*v [файл журнала]:

Action 14:38:47: AppSearch. Searching for installed applications
Action start 14:38:47: AppSearch.
AppSearch: Property: SOMEAPPFOLDER, Signature: AppFolder
MSI (c) (00:90) [14:38:47:065]: Note: 1: 1322 2:  
MSI (c) (00:90) [14:38:47:065]: Note: 1: 1322 2:  
MSI (c) (00:90) [14:38:47:065]: Note: 1: 1324 2: [environmentname] 3: 1 
MSI (c) (00:90) [14:38:47:065]: Note: 1: 1325 2: CompanyName 
Action ended 14:38:47: AppSearch. Return value 1.
MSI (c) (00:90) [14:38:47:066]: Doing action: LaunchConditions
MSI (c) (00:90) [14:38:47:067]: Note: 1: 2205 2:  3: ActionText 
Action 14:38:47: LaunchConditions. Evaluating launch conditions
Action start 14:38:47: LaunchConditions.
MSI (c) (00:A8) [14:38:47:069]: Font created.  Charset: Req=0, Ret=0, Font: Req=MS Shell Dlg, Ret=MS Shell Dlg

Couldn't find the AppFolderName app folder for [environment/version].
MSI (c) (00:90) [14:38:48:543]: Note: 1: 2205 2:  3: Error 
MSI (c) (00:90) [14:38:48:543]: Note: 1: 2228 2:  3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 1709 
MSI (c) (00:90) [14:38:48:543]: Product: [productname] -- Couldn't find the AppFolderName app folder for [environment/version].

Action ended 14:38:48: LaunchConditions. Return value 3.

person KristoferA    schedule 20.09.2013    source источник


Ответы (2)


Поведение Depth при использовании FileSearch

Depth работает иначе, когда FileSearch является непосредственным потомком DirectorySearch.

В обычном случае Depth указывает максимальное количество уровней папок выше указанного пути. Однако, если FileSearch является непосредственным потомком, Depth указывает максимальное количество уровней папок для поиска файла ниже по указанному пути.

Другими словами, невозможно указать глубину для каталога, который является непосредственным родительским файлом.

Пример

Давайте посмотрим на код, который вы вставили:

<Property Id="SOMEAPPFOLDER">
  <DirectorySearch Id="ProgramFilesFolder" Path="[ProgramFilesFolder]">
    <DirectorySearch Id="CompanyNameFolder" Path="CompanyName">
      <DirectorySearch Id="ProductFolder" Path="ProductName">
        <DirectorySearch Id="EnvironmentFolder" Path="$(var.ENVIRONMENTNAME)" Depth="2">
          <DirectorySearch Id="AppFolder" Path="AppFolderName" Depth="2" AssignToProperty="yes">
            <FileSearch Id="AppNameExe" Name="AppName.exe" MinVersion="$(var.MIN_VERSION).0" MaxVersion="$(var.MAX_VERSION).999" />
          </DirectorySearch>
        </DirectorySearch>
      </DirectorySearch>
    </DirectorySearch>
  </DirectorySearch>
</Property>

В приведенном выше примере первое использование Depth позволяет использовать два уровня каталогов между ProductFolder и EnvironmentFolder, но второе использование Depth относится к числу уровней между AppFolder и AppNameExe.

Временное решение

Следующий xml использует два поиска для обхода проблемы:

<!-- Locate the parent directory first -->
<Property Id="SOMEAPPFOLDER">
  <DirectorySearch Id="ProgramFilesFolder" Path="[ProgramFilesFolder]">
    <DirectorySearch Id="CompanyNameFolder" Path="CompanyName">
      <DirectorySearch Id="ProductFolder" Path="ProductName">
        <DirectorySearch Id="EnvironmentFolder" Path="$(var.ENVIRONMENTNAME)" Depth="1">
          <DirectorySearch Id="AppFolder" Path="AppFolderName" Depth="1" />
        </DirectorySearch>
      </DirectorySearch>
    </DirectorySearch>
  </DirectorySearch>
</Property>

<!-- Now, look for the file in the above directory -->
<Property Id="APPFILEEXISTS">
  <DirectorySearch Id="AppFolder" Path="SOMEAPPFOLDER">
    <FileSearch Id="AppNameExe" Name="AppName.exe" MinVersion="$(var.MIN_VERSION).0"
      MaxVersion="$(var.MAX_VERSION).999" />
  </DirectorySearch>
</Property>
person AbdullahC    schedule 02.10.2013
comment
Примечание. Я изменил Depth уровни на 1 (с 2), так как этого достаточно для указанных вами тестовых случаев. - person AbdullahC; 04.10.2013

Второй depth используется для поиска файла на два уровня ниже AppFolder, а не для поиска AppFolder на два уровня ниже EnvironmentFolder.

Вы можете выполнить первый поиск папки:

<Property Id="SOMEAPPFOLDER">
  <DirectorySearch Id="ProgramFilesFolder" Path="[ProgramFilesFolder]">
    <DirectorySearch Id="CompanyNameFolder" Path="CompanyName">
      <DirectorySearch Id="ProductFolder" Path="ProductName">
        <DirectorySearch Id="EnvironmentFolder" Path="$(var.ENVIRONMENTNAME)" Depth="2">
          <DirectorySearch Id="AppFolder" Path="AppFolderName" Depth="2" AssignToProperty="yes">
           <!-- <FileSearch Id="AppNameExe" Name="AppName.exe" MinVersion="$(var.MIN_VERSION).0" MaxVersion="$(var.MAX_VERSION).999" /> -->
          </DirectorySearch>
        </DirectorySearch>
      </DirectorySearch>
    </DirectorySearch>
  </DirectorySearch>
</Property>

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

<Property Id="APPEXISTS">
  <DirectorySearchRef Id="AppFolder" Parent="EnvironmentFolder" Path="AppFolderName">
     <FileSearch Id="AppNameExe" Name="AppName.exe" MinVersion="$(var.MIN_VERSION).0" MaxVersion="$(var.MAX_VERSION).999" />
  </DirectorySearchRef>
</Property>
person Juan Mellado    schedule 02.10.2013
comment
Спасибо, отлично работает! Поскольку Гиппо ответил первым, награда досталась @hippo. - person KristoferA; 11.10.2013