部署 Office 2016 VSTO 加载项的最佳做法

本文关键字:最佳 加载项 Office 2016 VSTO 部署 | 更新日期: 2023-09-27 17:56:43

我们已经为Office 2016开发了一些内部工具栏,并希望将它们部署到所有用户。

目前,VSTO 构建为 EXE,我们可以使用组策略部署该 EXE。安装后,加载项将显示在"添加/删除程序"(Windows 10)中。

但是,我们希望将来证明这一点,以便我们可以在进行更新时推出较新版本的工具栏。

使用组策略方法,我们最终安装了多个版本的 EXE。(应用程序中实际上只有一个,但您可以在添加/删除程序中看到两者)。

我们应该如何打包这些插件,以便我们可以推出未来的版本(通过 GPO 或脚本)?我怀疑MSI可能是要走的路,但这对我们来说是一个新的领域。

部署 Office 2016 VSTO 加载项的最佳做法

使用我的 VSTO 加载项,我通过 ClickOnce 进行部署。ClickOnce 具有在用户打开相应的 Office 应用程序时自动检查更新的巨大优势。

当然,ClickOnce 很难通过组策略进行部署(尽管解决方案确实存在)。您可以查看的一件事是创建使用 MSBuild 生成的 ClickOnce 引导程序可执行文件(安装程序.exe),并改为通过组策略部署它。

可以通过以下两种方式之一生成引导程序:在 Visual Studio 中(项目属性、发布、先决条件、创建安装程序以安装先决条件组件)或使用 Microsoft 以编程方式生成引导程序。

using System;
using System.IO;
using System.Reflection;
using Microsoft.Build.Construction;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Logging;
using Microsoft.Build.Tasks.Deployment.ManifestUtilities;
using Microsoft.Build.Utilities;
public class BootstrapperExample {
    private string GenerateBootstrapper(string manifestFile, string applicationName, string applicationUrl, params string[] prerequisites) {
        // root element
        ProjectRootElement xml = ProjectRootElement.Create();
        xml.ToolsVersion = "4.0";
        xml.DefaultTargets = "BuildBootstrapper";
        // build properties
        var propertyGroup = xml.AddPropertyGroup();
        propertyGroup.AddProperty("TargetFrameworkVersion", "v4.5");
        propertyGroup.AddProperty("VisualStudioVersion", "11.0");
        // prerequisites (product codes of each required package, e.g. ".NETFramework,Version=v4.5")
        var itemGroup = xml.AddItemGroup();
        foreach (string productCode in prerequisites) {
            itemGroup.AddItem("BootstrapperFile", productCode);
        }
        // target
        var target = xml.AddTarget("BuildBootstrapper");
        var task = target.AddTask("GenerateBootstrapper");
        task.SetParameter("ApplicationFile", Path.GetFileName(manifestFile));
        task.SetParameter("ApplicationName", applicationName);
        task.SetParameter("ApplicationUrl", applicationUrl);
        task.SetParameter("BootstrapperItems", "@(BootstrapperFile)");
        task.SetParameter("OutputPath", Path.GetDirectoryName(manifestFile));
        task.SetParameter("Path", @"C:'Program Files (x86)'Microsoft SDKs'Windows'v8.0A'Bootstrapper");     // replace with actual path
        var proj = new ProjectInstance(xml);
        var req = new BuildRequestData(proj, new string[] { "BuildBootstrapper" });
        var parameters = new BuildParameters();
        // optional logging of the build process
        var logger = new FileLogger();
        Uri codeBase = new Uri(Assembly.GetEntryAssembly().CodeBase);
        logger.Parameters = "logfile=" + Path.Combine(Path.GetDirectoryName(codeBase.LocalPath), "msbuild.log");
        parameters.Loggers = new ILogger[] { logger };
        // build the bootstrapper executable (setup.exe)
        var result = BuildManager.DefaultBuildManager.Build(parameters, req);
        if (result.OverallResult == BuildResultCode.Failure) {
            throw new InvalidOperationException("MSBuild task failed!", result.Exception);
        }
        // return path to the built setup.exe
        return Path.Combine(Path.GetDirectoryName(manifestFile), "setup.exe");
    }
}