独乐乐不如众乐乐——将 VSTO 插件部署给所有用户(下篇)
来源:互联网 发布:js模拟点击input file 编辑:程序博客网 时间:2024/06/06 22:06
注:本文原作者 Misha Shneerson 是 VSTO 团队的工程师。原文可以在下列地址找到:http://blogs.msdn.com/mshneer/archive/2007/09/05/deploying-your-vsto-add-in-to-all-users-part-ii.aspx。
在“上篇”中,我们介绍了准备知识。本文要把它付诸实用:如何在你的 Office 2007 插件安装程序中具体实现“部署到所有本机所有用户”,这包括任何安装程序都要处置的“安装”、“修复”和“删除”三大功能:
- 在安装插件的时候,我们需要写入一些类似“上篇”中“testpropagation_create.reg”文件的注册表键值,其中包含的“Create”指令会让 Office 把注册表键值复制到用户的 HKCU 里面去。
- 在卸载插件的时候,我们要把“Create”指令替换成“Delete”指令,让 Office 删除 HKCU 中对应的键值。同时,我们还需要把“Count”注册表值减少,这样可以保证 Office 要执行“Delete”指令。
- 在执行修复的时候,我们需要增加“Count”的值,这样会让 Office 再把 HKLM 里面的键值复制到 HKCU。
我们先来处理安装的时候需要用到的键值。最方便的方法莫过于修改一下现成的 VSTO 2005 SE 插件安装程序工程(创建插件工程时附带自动创建的安装程序工程)。就让我们来开一个新的 Excel 2007 插件工程好了,起个名字叫“MyAddIn”。你会发现 VSTO 自动帮你创建了一个配套的 MyAddInSetup 工程。打开这个工程,切换到注册表视图,然后把里面现成的注册表键值设置全部删除(比如那些在 HKEY_CURRENT_USER 里面的)。然后,把下面的注册表信息保存到一个 .reg 文件中,右键单击“Registry on Target Machine”节点,选择“导入(Import)……”,选中你刚才创建的 .reg 文件。这样就把我们需要的注册表信息导入安装程序工程了。如果有必要,你可以调整下面高亮显示的部分,以对应项目的实际情况。
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Office/12.0/User Settings/MyCompany.MyAddIn/Create/Software/Microsoft/Office/Excel/Addins/MyCompany.MyAddIn]
"Description"="MyAddIn -- an addin created with VSTO technology"
"Manifest"="[TARGETDIR]MyAddIn.dll.manifest"
"FriendlyName"="MyAddIn"
"LoadBehavior"=dword:00000003
"CommandLineSafe"=dword:00000001
做完这一步,你的注册表视图看起来应该类似于下图:
好了,这样一来,我们就可以保证在卸载 Add-In 的时候,相关的注册表键值会被正确删除。我还建议大家在属性窗口里面把“Create”节点的“DeleteOnUninstall”属性设置成 True,以此保证这个键值会在卸载的时候被删除。
请注意,我们还需要在“MyCompany.MyAddIn”节点增加一个“Count”值。但是不能通过“注册表视图”来加。因为我们不但需要在卸载的时候保留这个值,还要将其减小。如果在设计器里面添加,那就会在卸载的时候被删除了。
所以我们需要创建一个自定义安装动作(Custom Action),让它来改变 Count 的值,并且在卸载过程中创建一个“Delete”指令。
下面我将向大家展示 Darryn Lavery(促成本文的首要功臣)为他的 MSDN 专栏文章编写的代码(这篇即将发布的文章更加详尽地阐述了本文讨论的问题和解决方案),他无私地把代码与我共享,而我就借花献佛,拿来和大家分享。不过还是要感谢 Darryn。
现在我们就来仔细瞧瞧这个 Custom Action 的代码:先定义一个 RegisterOffice2007AddIn 类,添加一些私有方法。 class RegisterOffice2007AddIn { #region private methods private const string userSettingsLocation = @"Software/Microsoft/Office/12.0/User Settings"; public void IncrementCounter(RegistryKey instructionKey) { if (value != null) { instructionKey.SetValue("Count", count); private string GetApplicationPath(string applicationName) { case "infopath": case "outlook": case "powerpoint": case "word": case "visio": case "project": default: #endregion
int count = 1;
object value = instructionKey.GetValue("Count");
if ((int)value != Int32.MaxValue)
count = (int)value + 1;
}
}
switch (applicationName.ToLower()) {
case "excel":
return @"Software/Microsoft/Office/Excel/Addins/";
return @"Software/Microsoft/Office/InfoPath/Addins/";
return @"Software/Microsoft/Office/Outlook/Addins/";
return @"Software/Microsoft/Office/PowerPoint/Addins/";
return @"Software/Microsoft/Office/Word/Addins/";
return @"Software/Microsoft/Visio/Addins/";
return @"Software/Microsoft/Office/MS Project/Addins/";
throw new Exception(applicationName + " is not a supported application", null);
}
}
上面的代码有两个方法:IncrementCounter 负责正确地更新“Count”键值;GetApplicationPath 返回针对某个 Office 应用程序的插件信息注册表键值路径。
再看一个在“安装”和“修复”的时候直接被调用的方法:
public void RegisterAddIn(string addInName) { try { if (userSettingsKey == null) { instructionKey = userSettingsKey.OpenSubKey(addInName, true); if (instructionKey == null) { IncrementCounter(instructionKey); } finally { if (userSettingsKey != null)
RegistryKey userSettingsKey = null;
RegistryKey instructionKey = null;
userSettingsKey = Registry.LocalMachine.OpenSubKey(userSettingsLocation, true);
throw new Exception("Internal error: Office User Settings key does not exist", null);
}
instructionKey = userSettingsKey.CreateSubKey(addInName);
} else {
// 删除“Delete”指令
try {
instructionKey.DeleteSubKeyTree("DELETE");
} catch (ArgumentException) { } // “Delete”指令不存在,忽略这种情况下的异常
}
if (instructionKey != null)
instructionKey.Close();
userSettingsKey.Close();
}
}
在上面的代码中,我们首先保证“Delete”注册表指令不存在,然后增加计数器值(Count 键值)。要注意的是,我们没有用代码创建“Create”指令,因为这个指令已经在之前的“注册表视图”中定义好了,它会被自动写入注册表。
最后就是在“卸载”的时候被调用的方法:
public void UnRegisterAddIn(string applicationName, string addInName) { try { if (userSettingsKey == null) { instructionKey = userSettingsKey.OpenSubKey(addInName, true); if (instructionKey == null) { string instructionString = deleteKey = instructionKey.CreateSubKey(instructionString); IncrementCounter(instructionKey); if (instructionKey != null) if (userSettingsKey != null)
RegistryKey userSettingsKey = null;
RegistryKey instructionKey = null;
RegistryKey deleteKey = null;
userSettingsKey = Registry.LocalMachine.OpenSubKey(userSettingsLocation, true);
throw new Exception("Internal error: Office User Settings key does not exist", null);
}
instructionKey = userSettingsKey.CreateSubKey(addInName);
} else {
// 确保“Create”指令被删除
try {
instructionKey.DeleteSubKeyTree("CREATE");
} catch (ArgumentException) { } // “Create”指令不存在,忽略这种情况下的异常
}
@"DELETE/" +
GetApplicationPath(applicationName) +
@"/" +
addInName;
} finally {
if (deleteKey != null)
deleteKey.Close();
instructionKey.Close();
userSettingsKey.Close();
}
}
好了,差不多大功告成!只要把这些代码包装进一个 Custom Action DLL(假设你已经有类似的经验),把 CustomActionData 属性设置成 /addinName="MyCompany.MyAddIn" /application="Excel"(具体的值根据你的情况自定义)。在“安装”、“卸载”或者“回滚”的时候调用这些方法,就可以啦。我会在稍后的日志中作一个总结。
- 独乐乐不如众乐乐——将 VSTO 插件部署给所有用户(下篇)
- 独乐乐不如众乐乐——将 VSTO 插件部署给所有用户(下篇)
- 独乐乐不如众乐乐——将 VSTO 插件部署给所有用户
- 将 VSTO 插件部署给所有用户(下篇)
- (转)将 VSTO 插件部署给所有用户(下篇)
- (转)将 VSTO 插件部署给所有用户(上篇)
- oracle—将指定用户下所有表的查询权限赋给另一个用户
- 晓之以理,不如动之以情——新书《以大致胜》解读(下篇)
- oracle——将指定用户下所有表的查询权限赋权给查询用户
- oracle——将指定用户下所有表的查询权限赋权给查询用户
- 将某个用户下面的所有表的查询权限赋给另外一用户
- NO.60 Oracle 快速将某用户所有table的select权限授权给另一用户
- oracle将A用户下的所有表的查看权限赋予给B用户
- 将指定用户下所有表的查询权限赋权给查询用户
- 将某个用户的所有表的查询权限授权给另一个用户
- oracle将A用户下的所有table,packe的权限赋予给B用户
- 将一个用户下所有表的查询权限赋给另一个用户
- 怎么将数据库某一用户下的所有表权限赋给另一用户
- 被中国人误传了数千年的七句话
- 5.12
- 记唐骏讲座
- IT技术人才的出路
- 原则二:不使用else关键字
- 独乐乐不如众乐乐——将 VSTO 插件部署给所有用户(下篇)
- struts 1* + spring
- log4cxx体系结构
- CAS 代码访问安全性 (翻译)
- 编了一个服务器
- inline itemRender visit the parent's parameter
- toad赋用户权限
- 数据库范式
- oracle9导10g