5

我有一个 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>

但是,如果存在可选文件夹,则更高版本不起作用但如果不存在,则可以使用。换句话说,就好像Depth 属性之一被忽略了;我的猜测是这是因为我在树中的不同级别使用了两次深度属性。

关于如何解决这个问题的任何建议?


更新- 添加了来自 msiexec /i [msiname] /l*v [logfile] 的日志片段提取:

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.
4

2 回答 2

6

使用Depth时的行为FileSearch

DepthFileSearch是 的直接后代时,工作方式不同DirectorySearch

在正常情况下,指定指定路径之上Depth的最大文件夹级别数。但是,如果是直接后代,则指定文件夹级别的最大数量以查找指定路径下的文件。FileSearchDepth

换句话说,无法指定作为文件直接父目录的目录的深度。

例子

让我们看看您粘贴的代码:

<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指 和 之间的级别AppFolderAppNameExe

解决方法

以下 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>
于 2013-10-02T20:41:21.630 回答
3

第二个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>
于 2013-10-02T21:01:32.140 回答