65.9K
CodeProject 正在变化。 阅读更多。
Home

用于部署 Visual Studio 2005 插件的自定义操作

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (16投票s)

2006年7月23日

CPOL

3分钟阅读

viewsIcon

145006

downloadIcon

782

引导您构建一个通用的自定义操作来操作和 XCopy .addin 文件以及您的加载项程序集,该操作适用于大多数加载项部署方案。

引言

最近开发了一个 Visual Studio 2005 加载项,我发现当涉及到部署加载项时,不再自动创建安装项目。正如 MSDN 在线文档中描述的那样,Visual Studio 2005 现在依赖于 *.addin* 文件进行加载项部署。

在 Visual Studio .NET 2002 和 Visual Studio .NET 2003 中,您需要使用程序集注册工具 (regasm.exe) 将加载项程序集注册为 Windows 的 COM 组件。此外,您还需要通过 Windows 注册表中的键将加载项注册到 Visual Studio,然后加载项才能出现在加载项管理器中。

这些步骤在 Visual Studio 2005 中发生了变化。您不再需要使用 regasm 将 .NET 程序集注册到 Windows。相反,您只需将程序集 .DLL 文件放入特定目录,以及一个具有 .Addin 文件扩展名的 XML 文件。此 XML 文件描述了 Visual Studio 需要在加载项管理器中显示加载项的信息。当 Visual Studio 启动时,它会在 .Addin 文件位置(如下所示)中查找任何可用的 .Addin 文件。如果找到任何文件,它将读取 XML 文件并向加载项管理器提供启动加载项所需的信息。

这种简化的注册方法允许对托管代码加载项进行 XCopy 式安装。如果您将所有文件放在正确的位置,您的加载项就可以正常工作。此外,它使用注释的 XML 来定义加载项的注册设置,这使得信息比注册表项更容易理解和编辑。

那么现在的问题是,我们如何仍然使用 Windows Installer (*.msi*) 来部署具有这种新注册方法的加载项。在这里,我将引导您构建一个通用的自定义操作来操作和 XCopy *.addin* 文件以及您的加载项程序集,该操作适用于大多数加载项部署方案。

.Addin 文件

以下是一个完整的 *.Addin* XML 文件的示例。 *.Addin* 文件通常位于 *\Documents and Settings\All Users\My Documents\Visual Studio 2005\Addins* 或 *\Documents and Settings\<用户名>\My Documents\Visual Studio 2005\Addins*。 `Assembly` 节点(**粗体**)指定加载项二进制文件的位置。此字段可以设置为本地路径、网络路径或有效的 URL。并且,这是自定义操作在部署时更新的位置。

<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<Extensibility 
  xmlns="http://schemas.microsoft.com/AutomationExtensibility">
    <HostApplication>
        <Name>Microsoft Visual Studio Macros</Name>
        <Version>8.0</Version>
    </HostApplication> 
    <HostApplication>
        <Name>Microsoft Visual Studio</Name>
        <Version>8.0</Version>
    </HostApplication>
    <Addin>
        <FriendlyName>My new add-in.</FriendlyName>
        <Description>This add-in does something important.</Description>
        <AboutBoxDetails>Copyright MyCompany 2006.</AboutBoxDetails>
        <AboutIconData>0000 . . . FFFF0000</AboutIconData>
        <Assembly>[Path to add-in]\MyNewAddin.dll</Assembly>
        <FullClassName>MyNewAddin.Connect</FullClassName>
        <LoadBehavior>1</LoadBehavior>
        <CommandPreload>0</CommandPreload>
        <CommandLineSafe>0</CommandLineSafe>
    </Addin>
    <ToolsOptionsPage>
        <Category Name="MyNewAddin">
        <SubCategory Name="General">
            <Assembly>[Path to add-in]\MyNewAddin.dll</Assembly>
            <FullClassName>MyNewAddin.OptionsPage</FullClassName>
        </SubCategory>
        </Category>
    </ToolsOptionsPage>
</Extensibility>

创建自定义操作项目

创建一个类库项目,并通过选择安装程序类来添加新项。 新添加的类将继承自 `System.Configuration.Install.Installer` 类,该类具有诸如 `Install`、`Commit`、`Rollback` 和 `Uninstall` 之类的方法,您可以覆盖这些方法。

namespace AddinCustomAction
{
    using System;
    using System.IO;
    using System.Diagnostics;
    using System.Collections;
    using System.ComponentModel;
    using System.Configuration.Install;
    using System.Xml;
    
    /// <summary>
    /// Custom action for add-in deployment.
    /// </summary>

    [RunInstaller(true)]
    public partial class AddinInstaller : Installer
    {
        /// <summary>
        /// Namespace used in the .addin configuration file.
        /// </summary>         

        private const string ExtNameSpace = 
          "http://schemas.microsoft.com/AutomationExtensibility";
        
        /// <summary>
        /// Constructor. Initializes components.
        /// </summary>

        public AddinInstaller()
            : base()
        {
            InitializeComponent();
        }
        
        /// <summary>
        /// Overrides Installer.Install,
        /// which will be executed during install process.
        /// </summary>
        /// <param name="savedState">The saved state.</param>

        public override void Install(IDictionary savedState)
        {
            // Uncomment the following line, recompile the setup
            // project and run the setup executable if you want
            // to debug into this custom action.

            ////Debugger.Break();

            base.Install(savedState);
            
            // Parameters required to pass in from installer

            string productName = this.Context.Parameters["ProductName"];
            string assemblyName = this.Context.Parameters["AssemblyName"];
            
            // Setup .addin path and assembly path

            string addinTargetPath = Path.Combine(Environment.GetFolderPath(
                   Environment.SpecialFolder.MyDocuments), 
                   @"Visual Studio 2005\Addins");
            string assemblyPath = Path.GetDirectoryName(
                   System.Reflection.Assembly.GetExecutingAssembly().Location);
            string addinControlFileName = assemblyName + ".Addin";
            string addinAssemblyFileName = assemblyName + ".dll";
            
            try
            {
                DirectoryInfo dirInfo = new DirectoryInfo(addinTargetPath);
                if (!dirInfo.Exists)
                {
                    dirInfo.Create();
                }
                
                string sourceFile = Path.Combine(assemblyPath, addinControlFileName);
                XmlDocument doc = new XmlDocument();
                doc.Load(sourceFile);
                XmlNamespaceManager xnm = new XmlNamespaceManager(doc.NameTable);
                xnm.AddNamespace("def", ExtNameSpace);
                
                // Update Addin/Assembly node

                XmlNode node = doc.SelectSingleNode("/def:" + 
                    "Extensibility/def:Addin/def:Assembly", xnm);
                if (node != null)
                {
                    node.InnerText = Path.Combine(assemblyPath, addinAssemblyFileName);
                }
                
                // Update ToolsOptionsPage/Assembly node

                node = doc.SelectSingleNode("/def:Extensibility/def:" + 
                       "ToolsOptionsPage/def:Category/def:SubCategory/def:Assembly", xnm);
                if (node != null)
                {
                    node.InnerText = Path.Combine(assemblyPath, addinAssemblyFileName);
                }
                
                doc.Save(sourceFile);
                
                string targetFile = Path.Combine(addinTargetPath, addinControlFileName);
                File.Copy(sourceFile, targetFile, true);
                
                // Save AddinPath to be used in Uninstall or Rollback

                savedState.Add("AddinPath", targetFile);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }
        
        /// <summary>
        /// Overrides Installer.Rollback, which will be executed during rollback process.
        /// </summary>

        /// <param name="savedState">The saved state.</param>

        public override void Rollback(IDictionary savedState)
        {
            ////Debugger.Break();

            base.Rollback(savedState);
            
            try
            {
                string fileName = (string)savedState["AddinPath"];
                if (File.Exists(fileName))
                {
                    File.Delete(fileName);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }
        
        /// <summary>
        /// Overrides Installer.Uninstall, which will be executed during uninstall process.
        /// </summary>

        /// <param name="savedState">The saved state.</param>

        public override void Uninstall(IDictionary savedState)
        {
            ////Debugger.Break();

            base.Uninstall(savedState);

            try
            {
                string fileName = (string)savedState["AddinPath"];
                if (File.Exists(fileName))
                {
                    File.Delete(fileName);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }
    }
}

配置安装项目

将自定义操作项目的输出添加到安装项目。 如下所示,在“自定义操作”视图中,将自定义操作主输出添加到“安装”、“回滚”和“卸载”。

在“安装”操作中指定 `CustomActionData`。 指定 *AssemblyName* 作为 DLL 的名称,并指定 *ProductName* 作为产品的完整名称。

如果您想调试自定义操作,请在自定义操作类中要调试的方法中添加以下行

Debugger.Break();
© . All rights reserved.