代码之家  ›  专栏  ›  技术社区  ›  Tim Erickson

.msi文件是否可以自行安装(可能通过自定义操作)?

  •  9
  • Tim Erickson  · 技术社区  · 17 年前

    我希望构建一个MSI,在它的安装过程中,它将与包含的文件/组件一起部署到targetdir。

    所以myapp.msi在其文件表中包含myapp.exe和myappbootstrapperempty.exe(没有资源)。

    用户启动myappbootstrapperpackaged.exe(包含myapp.msi作为资源,从Internet某处获取,或通过电子邮件或其他方式获取)。myappbootstrapperPackaged.exe将myapp.msi提取到临时文件夹,并通过msiexec.exe执行。

    在msiexec.exe进程完成后,我需要myapp.msi、mybootstrapperempty.exe(以及位于%programfiles%\myapp文件夹中的myapp.exe),以便确保myapp.exe在运行时可以访问myapp.msi(用于创建下面提到的打包内容)。

    myappbootstrapper*.exe可以尝试将myapp.msi复制到%programfiles%\myapp文件夹,但需要提升才能执行此操作,并且不允许通过Windows Installer卸载过程(从“添加/删除程序”或其他程序)删除它,应保留该过程。

    很明显(我觉得很明显-我错了吗?)我不能将msi作为一个文件包含在我的media/cab(鸡和蛋的场景)中,因此我认为在安装过程之前必须通过自定义操作完成,将原始msi添加到msi db的media/cab中,并在文件表中动态添加适当的条目。可以这样做吗?如果可以,怎么做?

    想象一个内容分发模型,其中内容文件只与应用程序一起分发。内容由最终用户在运行时通过应用程序生成,并打包成可分发的exe文件,其中包括应用程序和内容。

    myapp的安装程序必须保持为msi,但可以由引导程序exe执行。安装的myapp.exe必须能够访问myapp.msi,并且在运行时由应用程序从基础(空)myappbootstrapper.exe(也由msi安装)和最终用户创建的内容“组装”exe。exe的资源msi必须与用于安装执行运行时打包的应用程序的资源msi相同。

    WIX不与myapp一起安装。

    在运行/打包时不能有网络依赖性(即不能通过WebService进行打包—必须在本地完成)。

    我熟悉(并使用)自定义操作(托管和非托管、通过DTF或其他方式)。

    6 回复  |  直到 17 年前
        1
  •  9
  •   Wim Coenen    12 年前

    向WXS添加未压缩介质,如下所示:

    <Media Id='2'/>
    

    然后用这样的文件元素创建一个组件:

    <File Source='/path/to/myinstaller.msi' Compressed='no' DiskId='2' />
    

    这将使安装程序在安装介质上查找名为“myinstaller.msi”的文件,该文件与正在安装的msi位于同一文件夹中。上面的源路径应该指向一个虚拟文件,它只是为了安抚wix。

    编辑 :下面的示例test.wxs演示了它的工作原理。它生成一个test.msi文件,将自己安装到c:\program files\test。请注意,您需要将一个虚拟test.msi文件放在与text.wxs相同的文件夹中,以安抚wix。

    <?xml version='1.0' encoding='utf-8'?>
    <Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
       <Product
             Name='ProductName'
             Id='*'
             Language='1033'
             Version='0.0.1'
             Manufacturer='ManufacturerName' >
          <Package
                Keywords='Installer'
                Description='Installer which installs itself'
                Manufacturer='ManufactererName'
                InstallerVersion='100'
                Languages='1033'
                Compressed='yes'
                SummaryCodepage='1252'/>
    
          <Media Id='1' Cabinet='test.cab' EmbedCab='yes'/> 
          <Media Id='2' /> 
    
          <Directory Id='TARGETDIR' Name="SourceDir">
             <Directory Id='ProgramFilesFolder'>
                <Directory Id='TestFolder' Name='Test' >
                   <Component Id="InstallMyself">
                      <File Source="./test.msi" Compressed="no" DiskId="2" />
                   </Component>
                </Directory>
             </Directory>
          </Directory>
    
          <Feature
                Id='Complete'
                Display='expand'
                Level='1'
                Title='Copy msi file to program files folder'
                Description='Test'>
    
             <ComponentRef Id="InstallMyself" />
          </Feature>
    
       </Product>
    </Wix>
    
        2
  •  3
  •   Davidson Corry    17 年前

    让一个.msi包从“内部”启动另一个.msi包称为 嵌套安装 和它的 bad juju (见规则20)。Windows Installer有一些用于管理当前安装的全局数据,但它不能同时处理好多个安装。出于同样的原因,如果您启动一个安装,然后在第一个安装仍在进行时尝试启动另一个安装,您通常会看到一个弹出窗口,显示“另一个安装正在进行,请等待安装完成”。

    您可以有一个程序,通常称为引导程序(我认为这就是您所指的),它本身不是一个安装包,而是 包含 作为资源的安装包(如.msi或.exe),可能已压缩。引导程序的操作是将资源提取/扩展到一个文件,通常在 %TEMP% 目录,然后启动提取的.exe或在提取的.msi上运行msiexec。如果需要在主包之前安装先决条件,引导程序可以包含多个资源,并逐个提取和安装它们。或者您可以将多个包作为单独的文件发送,并让引导程序一个接一个地从分发媒体执行/安装它们,或者将它们复制到目标计算机并从那里运行安装系列,或者……

    Wix本身没有安装,不。它是一个可以用它构建.msi包的工具。wix项目有一个通用的引导程序,但还没有实现。还有其他引导程序可用,例如 this one .

    您不需要自定义操作——事实上,因为引导程序本身不是Windows Installer安装包,“自定义操作”对它没有意义。而且,如果您对CA足够熟悉,能够了解托管/非托管/DTF,那么您就可以随时避免自定义操作。(咧嘴)

        3
  •  2
  •   Pavel Chuchuva grapeot    17 年前

    我认为引导程序更容易将MSI文件提取到某个预先定义的位置,而不是提取到temp文件夹。例如,到c:\documents and settings\all users\application data\my company\my product install cache。安装完成后,引导程序会将msi文件留在那里。如果在某个阶段,用户决定重新安装产品,Windows安装程序将能够找到源MSI文件。

    另外,将此文件的路径添加到 RemoveFile table 以便在卸载时将其删除。你可以使用 RemoveFile element 在Wix中。

        4
  •  1
  •   EBGreen    17 年前

    所以如果我理解,那么我想我应该让应用程序创建一个包含内容文件的转换(MST),并将其应用到基本的MSI。但我仍然不相信我能理解。:)

        5
  •  0
  •   saschabeaumont    17 年前

    我将配置到已知位置的msi缓存路径。

    然后在运行时,如果需要“编辑”MSI,请使用vbscript或类似工具。

    但是,我还是问为什么!?!

        6
  •  0
  •   Bob Donjacour    17 年前

    我还在研究部署多个MSI文件的方法。我有一个bootstrapper.exe程序,它捆绑MSI文件并一次运行一个。这解决了我大多数情况下的问题。

    它不能解决的情况是安装的GPO(全局策略对象)分发。GPO需要一个点msi文件来运行安装。

    要做到这一点,我所做的几乎解决了问题(但不是完全解决)。我把dot-msi文件放在安装程序的文件表中,把引导程序放在二进制表中,从installFinalize之后插入的自定义操作运行它。当然,引导程序将无法运行其他的msi,因为顶级msi保存了\msiexecute mutex。

    再往前走一点很容易。我让引导程序返回控制到顶层安装程序并继续。然后我添加了一个waitforsingleobject调用来等待顶级安装完成,引导程序随后可以继续完成安装。

    我的问题是,GPO安装发生在启动时,顶级安装在子安装程序完成和GPO重新启动计算机之前完成。

    当安装稍后可能实际失败时,顶级安装还会返回成功状态。

    我仍在寻找一种方法来阻止顶级安装完成,直到引导程序完成。

    推荐文章