0

我需要将 MSI 中的文件提取到一个文件夹中,但是更改文件的目录结构,所有这些都来自 C# 应用程序(即:不是通过管理员安装或任何其他 MSI 安装)。从概念上讲,我想将 MSI 的嵌入式 cab 解压缩到我选择的文件夹中。要进行提取,我使用的是 WiX 3.6 DTF 库,但无法确定如何更改文件夹结构。

因此,例如,如果我运行 MSI 安装程序,“Component1”的目标文件夹将为c:\Program Files(x86)\Company Name\Demo Product Installer\Component1\,但在我的提取器应用程序运行时,我想将其更改为c:\SomeOtherPlace\Demo Product Installer\Component1\,最好通过更改APPLICATIONFOLDER目录路径(见下文) .

对于 MSI,我定义了这样的目录结构:

<Fragment>
  <Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="ProgramFilesFolder">
      <Directory Id="APPLICATIONFOLDER" Name="Company Name">
        <Directory Id="ProductFolder" Name="Demo Product Installer">
          <Directory Id="Cmp1Folder" Name="Component1" />
          <Directory Id="Cmp2Folder" Name="Component2" />
        </Directory>
      </Directory>
    </Directory>
  </Directory>
</Fragment>

然后,在需要提取文件的代码中,我这样做了:

var msiFilePath = "myInstallerFile.msi";
var targetFolder = @"c:\SomeOtherPlace\";
using (var msiPackage = new InstallPackage(msiFilePath, DatabaseOpenMode.ReadOnly))
{
    msiPackage.WorkingDirectory = targetFolder;

    var dirMapping = msiPackage.Directories;    
    if (dirMapping.ContainsKey("APPLICATIONFOLDER"))                    
    {
        //This doesn't work, but represents what I hope to do:
        var oldInstallPath = dirMapping["APPLICATIONFOLDER"];                        
        oldInstallPath.TargetPath = targetFolder;                   
    }

    msiPackage.UpdateDirectories();                    
    msiPackage.ExtractFiles();                    
    msiPackage.Close();
}

有没有办法在运行时使用 DTF 对象修改这样的文件夹结构?我知道我可以在事后移动文件,但如果我能这样做,它会更干净。

4

2 回答 2

1

提取后移动文件肯定会更容易。您可能能够将数据库复制到临时文件,打开它进行编辑和操作表,然后将其作为包打开并解压缩。您也可以在不提交到磁盘的情况下对表(临时表)进行内存更新。

于 2012-10-10T02:17:34.817 回答
1

根据 Chirtopher 的回答中的提示(“您可能会在内存中更新表格......”),我能够找到一个可行的解决方案:

var msiFilePath = "myInstallerFile.msi";
var targetFolder = @"c:\SomeOtherPlace\";
using (var msiPackage = new InstallPackage(msiFilePath, DatabaseOpenMode.Transact))
{
    msiPackage.WorkingDirectory = targetFolder;

    var dirMapping = msiPackage.Directories;    
    if (dirMapping.ContainsKey("APPLICATIONFOLDER"))                    
    {
        //**** Modified code starts here ***//           
        // Changed the "APPLICATIONFOLDER" entry from "Company Name" to ".",
        // which is a special value to denote the extracted folder.
        var record = new Record(".", "APPLICATIONFOLDER");
        msiPackage.Execute("UPDATE `Directory` SET `DefaultDir` = ? WHERE `Directory` = ?", record);
        //**** Modified code ends here ***//
    }

    msiPackage.UpdateDirectories();                    
    msiPackage.ExtractFiles();  

    //Close **without** calling Commit() to ensure changes are not persisted                  
    msiPackage.Close();
}

请注意,我还将 DatabaseOpenMode 更改为 Transact。

当然,如果您想对文件夹结构进行更高级的更改,则必须从 Directory 表中修改/插入/删除其他记录。(参见http://msdn.microsoft.com/en-us/library/windows/desktop/aa368295(v=vs.85).aspx供参考)

于 2012-10-10T19:34:39.767 回答