详解Office 外接程序 COM Add In的LoadBehavior及其妙用

URL:http://www.onlyblog.com/blog2/cysky007/11538.html

 

Office的所有COM Add In,包括用Shared Add In模板和VSTO Add In模板创建的,都会在注表里面存储一些信息。对于当前用户安装的Add In,以Excel为例,对应的注册表键值存储于:My Computer"HKCU"Software"Microsoft"Office"Addins"AddInName;机器级别的Add In存储于:My Computer"HKLM"Software"Microsoft"Office"Addins"AddInName。普通的Shared Add In, 键下面有3个值,Description,FriendlyName,LoadBehavior。VSTO Add In多出两个键值:CommandLineSafe和Manifest。Manifest是用来指向自定义代码所处的dll位置的,CommandLineSafe用来指示Add In是不是命令行安全的,会不会显示在COM Add In Dialog里面。Description和FriendlyName就是Add In的描述和显示的名字,没啥好说的。

                而LoadBehavior是这篇文章的主角。LoadBehavior指示了该Add In的装载行为,它可以由以下几个值组合而成: (前两个中的一个+后三个中的一个)

0   = Disconnect

不装载

1   = Connected

装载

2   = Bootload

启动程序时装载

8   = DemandLoad

需要时装载

16 = ConnectFirstTime

第一次启动时装载

也就是说,当LoadBehavior为0,2,8,16的时候,Add In不装载;当其为1+2=3的时候,装载并且每次Office程序启动时都装载;当其为9的时候,装载,但只当用户需要时装载;17的时候,装载,只有第一次启动的时候装载。如果我们不去改动,一般而言,正常工作的Add In其LoadBehavior是3,但如果当Add In启动的时候发生异常,这个Add In会被软禁用(Soft Disabled),LoadBehavior的值会被改为0+2=2,Add In将不被装载。注意,虽然这里的值是2,表示启动时装载,但事实上,其是由0+2所得,大的前提决定了不装载。

      那我说的LoadBehavior的妙用在何处呢?这源于最近碰到的一个问题,有人问我,能不能用代码来获取Office中被硬禁用(Hard Disable)的COM Add In,或者至少知道,有没有被硬禁用的Add In?这个问题有点棘手,因为Office对象模型中,根本找不到任何信息。Google甚至都找不到,有人有类似的要求。

           在给出解决方案前,有必要讲述一下,上面提到的硬禁用和软禁用的区别。首先,硬禁用和软禁用的表象就不一样,被软禁用的Add In会出现在COM Add-Ins对话框中,只不过前面的Checkbox不会被勾上。被硬禁用的Add In虽然也会出现在COM Add-Ins对话框中,但它们会被单独再列到另外一个叫Disabled Items的对话框里面。下面是COM Add-Ins对话框和Disabled Items对话框的截图。由下面的图可以看出来ExcelAddIn和ExcelAddIn1是被用户手动禁用,或者被软禁用的;ExcelAddIn2则是被硬禁用的。

COM Add-Ins 软禁用 对话框截图

Disabled Items 硬禁用 对话框截图

硬禁后第一次开启时的提示

那是什么导致Add In被软禁用和硬禁用的呢?为了模拟出问题,并解决,我也必须让自己的机器上出现一个被软禁用,一个被硬禁用的Add In。

    软禁用:当Add In在构造函数或者Startup event handle函数里面抛出一个没有处理的异常的时候,系统将该Add In软禁用,将其LoadBehavior值改为2。要重现一个软禁用很简单,在Startup event handle里面抛出一个异常就可以了,代码如下:

       private void ThisAddIn_Startup(object sender, System.EventArgs e)

        {

           throw new Exception("Make the Add in disabled");

        }

       硬禁用:发生在,Add In装载时由于严重的错误导致应用程序关闭,或者在构造函数或Startup event handle函数执行时,强行关掉Visual Studio Debugger时。这将导致再一次启动应用程序的时候,Office向用户询问是否硬禁用当前Add In。方法同样很简单,用一个MessageBox停住Startup event handle函数的执行过程,然后强行关掉Visual Studio,下次程序(本例Excel)启动时,选择禁用Add In。

       private void ThisAddIn_Startup(object sender, System.EventArgs e)

        {

            MessageBox.Show("Stop here");

        }

接下来,看看上面问题的解决方案。在Office对象模型中,Application对象有个COMAddIns属性,它是一个集合,包括了当前应用程序中所有注册过的COM Add In,无论这个Add In是否激活。我们可以在这个集合中循环,得到每个COMAddIn的句柄,而COMAddIn又暴露了一些有用的属性,比如Connect属性。当Connect返回true时,说明这个Add In是激活的,如果返回false,说明这个Add In未激活,有可能是被用户手动禁用了,还有可能是被软禁用或硬禁用了。但是COMAddIn的属性只告诉我们这么多,通过Office对象模型,我们无法分辨,应用程序中是否存在被硬禁用的Add In,如果有,哪些是被硬禁用的Add In。通过查看硬禁用的Add In在注册表中LoadBehavior的值,惊奇地发现,硬禁用的Add In,其LoadBehavior值竟然为3!这样我们就可以结合COMAddIns集合和注册表里LoadBehavior的信息来判断哪些COM Add In是被硬禁用的,哪些是由于软禁用或者其它原因未被装载的。实现的代码如下:

private void ThisAddIn_Startup(object sender, System.EventArgs e)

        {

            RegistryKey key = null;

 

            foreach(Office.COMAddIn cAddin in this.Application.COMAddIns)

            {

                if (!cAddin.Connect)

                {

                    try

                    {

                        key = Registry.LocalMachine;

                        key = key.OpenSubKey("Software").OpenSubKey("Microsoft")

                        .OpenSubKey("Office").OpenSubKey("Excel").OpenSubKey("Addins")

                        .OpenSubKey(cAddin.ProgId);

                        if (Convert.ToInt32(key.GetValue("LoadBehavior")) == 3)

                        {

                            MessageBox.Show(cAddin.ProgId + " is disabled!");

                        }

                        else

                        {

                            MessageBox.Show(cAddin.ProgId + " is not loaded!");

                        }

                    }

                    catch(Exception ex)

                    {

                        key = Registry.CurrentUser;

                        key = key.OpenSubKey("Software").OpenSubKey("Microsoft")

                        .OpenSubKey("Office").OpenSubKey("Excel").OpenSubKey("Addins")

                        .OpenSubKey(cAddin.ProgId);

                        if (Convert.ToInt32(key.GetValue("LoadBehavior")) == 3)

                        {

                            MessageBox.Show(cAddin.ProgId + " is disabled!");

                        }

                        else

                        {

                            MessageBox.Show(cAddin.ProgId + " is not loaded!");

                        }

                    }

                }

            }

        }

 

PS:如何显示COM Add-ins和Disabled Items对话框?(没有中文的Office,所以菜单和按钮都按英文版中的写法,对照着应该很好找到)

·         COM Add-ins对话框:

o   Office 2007:Office Button->Excel Options->Add-Ins Tab->Choose Item COM Add-ins in the Manage DropDownList->Click Button Go

o   Office 2003:Right Click the Menu->Click Customize… Button->In Commands Tab->Tools Categorie->Drag COM Add-Ins Command to one of the tool bar->Click the new added COM Add-ins Button

 

·         Disabled Items对话框:

o   Office 2007:Office Button->Excel Options->Add-Ins Tab->Choose Item Disabled Items in the Manage DropDownList->Click Button Go

o   Office 2003:Menu Help->About Microsoft Office Excel->Disabled Items

<think>嗯,用户想了解在Visual C# .NET中创建COM加载项。首先,我得确认自己对COM加载项的理解是否正确。COM加载项通常用于扩展Office应用程序的功能,比如Excel、Word等,通过实现特定的接口让Office能调用这些组件。不过,用户提到的是Visual C# .NET,所以可能需要用C#来创建这样的COM可见的类库。 接下来,我需要回忆如何在C#中创建COM可调用的组件。记得需要用到Interop服务,可能还要在项目属性里设置“使程序集COM可见”,并且注册COM互操作。另外,类必须有一个无参数的构造函数,并且实现IDTExtensibility2接口,这是Office加载项的标准接口。 不过,用户可能不太清楚具体的步骤,所以需要分步骤讲解。比如创建类库项目,添加必要的引用,比如Office的互操作库。然后,实现接口的方法,比如OnConnection、OnDisconnection等。还要注意Guid属性,因为COM需要唯一的CLSID。 可能遇到的问题包括注册失败,这时候需要用RegAsm工具注册DLL,或者以管理员权限运行命令提示符。另外,确保平台目标一致,比如32位或64位Office对应的设置。用户可能会遇到运行时错误,比如类型未注册,这时候需要检查注册步骤是否正确。 是否需要示例代码?可能用户需要一段简单的代码框架,展示如何实现接口和基本方法。但也要注意代码的正确性,比如使用正确的特性和方法签名。同时,提醒用户部署时需要注册DLL,并可能需要在Office中启用加载项。 还需要注意,C#创建COM加载项可能不如VB6或C++传统,但.NET通过互操作支持是可行的。可能需要使用RegAsm或项目设置中的“为COM互操作注册”选项。另外,强命名程序集可能在某些情况下需要,以避免版本冲突。 总结下来,步骤大致是:创建类库项目,添加引用,实现接口,设置COM可见,注册DLL,在Office中启用。可能还需要处理安全性或权限问题。确保每个步骤都详细说明,帮助用户逐步完成。</think>在Visual C# .NET中创建COM加载项的步骤如下: ### 一、基础概念 1. **COM加载项**:用于扩展Office应用程序(如Excel、Word)的功能 2. **工作原理**:通过实现`IDTExtensibility2`接口与宿主程序交互 3. **适用场景**:需要与Office深度集成的自动化任务 ### 二、环境准备 1. 开发工具: - Visual Studio(推荐2017及以上) - .NET Framework 4.0+ 2. 必需引用: ```csharp using System.Runtime.InteropServices; using Extensibility; // 来自Office PIA ``` ### 三、实现步骤 1. **创建类库项目** ```csharp [Guid("YOUR_GUID_HERE")] [ProgId("YourCompany.YourAddin")] [ClassInterface(ClassInterfaceType.None)] [ComVisible(true)] public class MyAddin : IDTExtensibility2 ``` 2. **实现核心接口方法** ```csharp public void OnConnection(object Application, ext_ConnectMode ConnectMode, object AddInInst, ref Array custom) { // 初始化代码 } public void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom) { // 清理代码 } ``` 3. **项目配置** - 程序集属性 → 生成 → 勾选"注册COM互操作" - 签名 → 为程序集创建强名称密钥 ### 四、注册与部署 1. **手动注册(管理员权限)** ```bash regasm YourAddin.dll /codebase ``` 2. **Office集成** ```reg Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Office\Excel\Addins\YourCompany.YourAddin] "FriendlyName"="My C# Addin" "Description"="Custom COM Addin" "LoadBehavior"=dword:00000003 ``` ### 五、调试技巧 1. 附加到Office进程: ```text Debug → Attach to Process → 选择EXCEL.EXE/WINWORD.EXE ``` 2. 常见错误处理: - 0x80070005:权限不足,需管理员权限运行 - 0x80131515:CLSID注册失败,检查GUID唯一性 ### 六、进阶优化 1. 使用`IRibbonExtensibility`实现Ribbon界面 2. 采用ClickOnce部署方案 3. 实现`IDisposable`规范资源释放 建议从简单的功能模块开始验证,逐步添加复杂逻辑。注意32/64位兼容性问题,推荐统一使用x86编译目标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值