WIX安装.NET和VSTO如果管理员,如果非管理员提前失败

时间:2014-02-04 19:28:35

标签: wix vsto burn

我正在尝试将Excel插件部署到大众市场。该插件需要VSTO运行时(vstor_redist.exe)和.NET 4.5(适用于64位操作系统)或.NET 4.0(适用于32位操作系统)。我愿意假设潜在用户至少已经拥有.NET 2.0。目前我的设置包括:

  1. 单独的32位和64位WIX .msi安装程序,以每用户模式安装插件。
  2. 分隔32位和64位引导程序包,它们包装每个.msi并安装VSTO运行时和.NET,如下面的代码所示:

    <util:RegistrySearch Id="VSTORuntimeTest" Root="HKLM" Key="SOFTWARE\Microsoft\VSTO Runtime Setup\v4R\" Value="VSTORFeature_CLR40" Variable="VSTORFeature"/>
    <util:RegistrySearch Id="VSTORuntimeVersionV4R" Root="HKLM" Key="SOFTWARE\Microsoft\VSTO Runtime Setup\v4R\" Value="Version" Variable="VSTORVersionV4R"/>
    <util:RegistrySearch Id="VSTORuntimeVersionV4" Root="HKLM" Key="SOFTWARE\Microsoft\VSTO Runtime Setup\v4\" Value="Version" Variable="VSTORVersionV4"/>
    
    <Chain>
      <!-- Install .Net 4.0 or 4.5, depending on build -->
      <?ifdef x64?>
      <PackageGroupRef Id="NetFx45Web" />
      <?endif ?>
    
      <?ifdef x86?>
      <PackageGroupRef Id="NetFx40Web" />
      <?endif ?>
      <RollbackBoundary />
    
      <!-- Install VSTO runtime -->
      <ExePackage Id="VSTORuntime" SourceFile="..\resources\vstor_redist.exe" Permanent="yes" Vital="yes" Cache="no" Compressed="no"
                  DownloadUrl="http://go.microsoft.com/fwlink/?LinkId=158917"
                  PerMachine="yes"
                  InstallCommand="/q /norestart"
                  DetectCondition="VSTORFeature"
                  InstallCondition="NOT VSTORFeature OR NOT (VSTORVersionV4R >=v10.0.40303) OR NOT (VSTORVersionV4 >=v10.0.21022)" />
      <RollbackBoundary />
    
      <?ifdef x64?>
      <MsiPackage
        Id="nx_msi_package_version"
        SourceFile="..\My 64 bit Setup.msi"
        Compressed="yes"
        Vital="yes" />
      <?endif ?>
    
      <?ifdef x86?>
      <MsiPackage
        Id="nx_msi_package_version"
        SourceFile="..\My 32 bit Setup.msi"
        Compressed="yes"
        Vital="yes" />
      <?endif ?>
    
    </Chain>
    
  3. 一个.NET 2.0包装器,它包含bootstrappers作为嵌入式资源,并且部署&amp;为客户端操作系统运行正确的引导程序。 (基本上是Yochai Timmer在Single MSI to install correct 32 or 64 bit c# application中的答案)

  4. 整个事情感觉像是一个turducken,但是当用户拥有管理员凭据时,它可以很好地用于静默升级和全新安装。但是,如果用户不是管理员,并且还没有安装VSTO和相应的.NET,则会因为错误而失败:“0x8007051b - 在长时间下载后,此安全ID可能不会被指定为对象的所有者”过程

    我想要做的是提前检查用户是否需要请求管理员干预并为他们安装VTSO和/或.NET,并显示一条消息,理想情况下是网站链接,当这是案子。此检查可以在引导程序中,也可以在我的.NET 2.0包装程序中。关于如何最好地做到这一点的任何建议?

    谢谢,Eric

1 个答案:

答案 0 :(得分:0)

对我来说最好的方法是在我的32位C#包装器中完成工作。正如我的问题中的代码所示,Burn似乎没有提供任何支持VSTO的内置软件包 - 而是我只是手动阅读注册表并将其逻辑基于此。 Burn确实为.NET 4.0和.NET 4.5提供了预构建的软件包,但是我没有看到一种简单的方法来支持Fail Early这些。

我的C#2.0包装器现在包含以下逻辑:

    private static bool NeedsMorePermissionToInstallPrerequisites(out string error)
    {
        error = string.Empty;

        // Is user an admin?  If so, we're OK
        if (PrivilegeTester.CanBeAdmin())
        {
            return false;
        }

        // Is .NET already installed?
        bool isDotNetInstalled;
        string dotNetVersion;
        if (Is64BitOperatingSystem())
        {
            isDotNetInstalled = PrereqSoftwareChecker.IsDotNet45Installed();
            dotNetVersion = "Microsoft .NET 4.5";
        }
        else
        {
            isDotNetInstalled = PrereqSoftwareChecker.IsDotNet40Installed();
            dotNetVersion = "Microsoft .NET 4.0";
        }

        // Is VTSO already installed?
        bool isVtsoInstalled = PrereqSoftwareChecker.IsVstoRuntimeInstalled();

        if (isVtsoInstalled && isDotNetInstalled)
        {
            return false;
        }

        // If we got this far, there's trouble.  Build the error.
        [...]

此处CanBeAdmin()功能基于Calling IPrincipal.IsInRole on Windows 7,IsVstoRuntimeInstalled()查看我在原始问题中使用的VSTORuntimeTest等逻辑中完全相同的注册表项集。 .NET检查还使用MSDN中详细记录的密钥查看注册表。例如:

    internal static bool IsDotNet40Installed()
    {
        try
        {
            Version dotnet4Version  = new Version(GetHKLMValue("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4.0\\Client", "Version").ToString());
            return dotnet4Version >= new Version("4.0.0.0");
        }
        catch
        {
            return false;
        }
    }

    private static object GetHKLMValue(string key, string valueName)
    {
        return Registry.GetValue("HKEY_LOCAL_MACHINE\\" + key, valueName, null);
    }

如果Burn可以更好地处理这样的事情会很好,但它可能很复杂,因为只提供一个Fail Early .NET软件包和一个单独的Fail Early VSTO软件包就不足以构建一个完整的软件包列表。需要由管理员独立安装。

在bootstrapper-wrapper代码中使用C#和.NET 2.0显然是一个风险,但我猜测没有太多旧的XP盒子在野外有Office,至少没有。 NET 2.0。