(转)刚开始Outlook Addin的布署问题

转自:http://weblogs.asp.net/mnissen/articles/427504.aspx

遇到的问题:
VSTO开发的Outlook Addin生成的默认setup工程不能正确的将插件安装到客户端,安装过程没有报错,注册表的Outlook下面的Addin也有注册。

 

最后的解决:客户端需要满足下面几个条件:

1.                       .NET Framework 2.0 (RC1)

2.                       Microsoft Office 2003 w/Outlook

3.                       Microsoft Office 2003 SP1 (or later)

4.                       Microsoft Office 2003 Primary Interop Assemblies (O2003PIA.exe) (how-to)

5.                       Visual Studio Tools for Office Runtime (vstor.exe) (Same version as .NET Framework!)

6.                       Language pack for vstor (Optional)

7.                       Registry keys for Outlook plugin (fixed by default VSTO Setup project)

8.                       Code Access Security FullTrust grant to your assemblies

 

相关的软件可以去Microsoft网站下载。

 

VSTO模版中生成的setup工程中欠缺如下两个方面:

1.              reference中缺少Microsoft.Office.Tools.Common.dll,这点可以简单的在主工程中添加reference选择相应的dll即可。

2.              需要msi自动的实现Code Access Security(而不是在客户机安装.NET Framework 2.0 Configuration Tools然后手动配置安全策略),实现方法如下:

 

新建一个System.Configuration.Install.Installer的继承,通过右键点击你的工程然后Add New Item | Installer Class,命名为Installer,然后在Installer.cs中写入代码如下:

ContractedBlock.gif ExpandedBlockStart.gif
  1None.gifusing System;
  2None.gifusing System.Collections.Generic;
  3None.gifusing System.ComponentModel;
  4None.gifusing System.Security.Policy;
  5None.gifusing System.Security;
  6None.gif
  7None.gifnamespace EOfficeSync
  8ExpandedBlockStart.gifContractedBlock.gifdot.gif{
  9InBlock.gif    // Code Access Security configuring installer by Mads Nissen 2005
 10InBlock.gif    // http://weblogs.asp.net/mnissen
 11InBlock.gif
 12InBlock.gif    [RunInstaller(true)]
 13InBlock.gif    public partial class Installer : System.Configuration.Install.Installer
 14ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 15InBlock.gif
 16InBlock.gif        private readonly string installPolicyLevel = "Machine";
 17InBlock.gif        private readonly string namedPermissionSet = "FullTrust";
 18InBlock.gif        private readonly string codeGroupDescription = "VSTO Permissions for Objectware Plugins";
 19InBlock.gif        private readonly string productName = "Objectware SharepointConnector";
 20InBlock.gif        private readonly bool debugBreakOnInstall = false;
 21InBlock.gif
 22InBlock.gif        private string codeGroupName = "";
 23InBlock.gif
 24ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 25InBlock.gif        /// Gets a CodeGroup name based on the productname and URL evidence
 26ExpandedSubBlockEnd.gif        /// </summary>

 27InBlock.gif        private string CodeGroupName
 28ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 29InBlock.gif            get
 30ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 31InBlock.gif                if (codeGroupName.Length == 0)
 32ExpandedSubBlockStart.gifContractedSubBlock.gif                dot.gif{
 33InBlock.gif                    codeGroupName = "[" + productName + "" + InstallDirectory;
 34ExpandedSubBlockEnd.gif                }

 35InBlock.gif                return codeGroupName;
 36ExpandedSubBlockEnd.gif            }

 37ExpandedSubBlockEnd.gif        }

 38InBlock.gif
 39ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 40InBlock.gif        /// Gets the installdirectory with a wildcard suffix for use with URL evidence
 41ExpandedSubBlockEnd.gif        /// </summary>

 42InBlock.gif        private string InstallDirectory
 43ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 44InBlock.gif            get
 45ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 46InBlock.gif                // Get the install directory of the current installer
 47InBlock.gif                string assemblyPath = this.Context.Parameters["assemblypath"];
 48InBlock.gif                string installDirectory =
 49InBlock.gif                    assemblyPath.Substring(0, assemblyPath.LastIndexOf("\\"));
 50InBlock.gif
 51InBlock.gif                if (!installDirectory.EndsWith(@"\"))
 52InBlock.gif                    installDirectory += @"\";
 53InBlock.gif                installDirectory += "*";
 54InBlock.gif
 55InBlock.gif                return installDirectory;
 56ExpandedSubBlockEnd.gif            }

 57ExpandedSubBlockEnd.gif        }

 58InBlock.gif
 59InBlock.gif        public Installer()
 60ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 61ExpandedSubBlockEnd.gif        }

 62InBlock.gif
 63InBlock.gif        public override void Install(System.Collections.IDictionary stateSaver)
 64ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 65InBlock.gif            base.Install(stateSaver);
 66InBlock.gif
 67InBlock.gif            try
 68ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 69InBlock.gif                ConfigureCodeAccessSecurity();
 70InBlock.gif                // Method not able to persist configuration to config file:
 71InBlock.gif                // SetPortalUrlFromInstallerParameter();
 72ExpandedSubBlockEnd.gif            }

 73InBlock.gif            catch (Exception ex)
 74ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 75InBlock.gif                System.Windows.Forms.MessageBox.Show(ex.ToString());
 76InBlock.gif                this.Rollback(stateSaver);
 77ExpandedSubBlockEnd.gif            }

 78ExpandedSubBlockEnd.gif        }

 79InBlock.gif
 80ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 81InBlock.gif        /// Configures FullTrust for the entire installdirectory
 82ExpandedSubBlockEnd.gif        /// </summary>

 83InBlock.gif        private void ConfigureCodeAccessSecurity()
 84ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 85InBlock.gif
 86InBlock.gif            PolicyLevel machinePolicyLevel = GetPolicyLevel();
 87InBlock.gif
 88InBlock.gif            if (null == GetCodeGroup(machinePolicyLevel))
 89ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 90InBlock.gif                // Create a new FullTrust permission set
 91InBlock.gif                PermissionSet permissionSet = new NamedPermissionSet(this.namedPermissionSet);
 92InBlock.gif
 93InBlock.gif                IMembershipCondition membershipCondition =
 94InBlock.gif                    new UrlMembershipCondition(InstallDirectory);
 95InBlock.gif
 96InBlock.gif                // Create the code group
 97InBlock.gif                PolicyStatement policyStatement = new PolicyStatement(permissionSet);
 98InBlock.gif                CodeGroup codeGroup = new UnionCodeGroup(membershipCondition, policyStatement);
 99InBlock.gif                codeGroup.Description = this.codeGroupDescription;
100InBlock.gif                codeGroup.Name = this.codeGroupName;
101InBlock.gif
102InBlock.gif                // Add the code group
103InBlock.gif                machinePolicyLevel.RootCodeGroup.AddChild(codeGroup);
104InBlock.gif
105InBlock.gif                // Save changes
106InBlock.gif                SecurityManager.SavePolicy();
107ExpandedSubBlockEnd.gif            }

108ExpandedSubBlockEnd.gif        }

109InBlock.gif
110ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
111InBlock.gif        /// Gets the currently defined policylevel
112InBlock.gif        /// </summary>
113ExpandedSubBlockEnd.gif        /// <returns></returns>

114InBlock.gif        private PolicyLevel GetPolicyLevel()
115ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
116InBlock.gif            // Find the machine policy level
117InBlock.gif            PolicyLevel machinePolicyLevel = null;
118InBlock.gif            System.Collections.IEnumerator policyHierarchy = SecurityManager.PolicyHierarchy();
119InBlock.gif
120InBlock.gif            while (policyHierarchy.MoveNext())
121ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
122InBlock.gif                PolicyLevel level = (PolicyLevel)policyHierarchy.Current;
123InBlock.gif                if (level.Label.CompareTo(installPolicyLevel) == 0)
124ExpandedSubBlockStart.gifContractedSubBlock.gif                dot.gif{
125InBlock.gif                    machinePolicyLevel = level;
126InBlock.gif                    break;
127ExpandedSubBlockEnd.gif                }

128ExpandedSubBlockEnd.gif            }

129InBlock.gif
130InBlock.gif            if (machinePolicyLevel == null)
131ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
132InBlock.gif                throw new ApplicationException(
133InBlock.gif                    "Could not find Machine Policy level. Code Access Security " +
134InBlock.gif                    "is not configured for this application."
135InBlock.gif                    );
136ExpandedSubBlockEnd.gif            }

137InBlock.gif            return machinePolicyLevel;
138ExpandedSubBlockEnd.gif        }

139InBlock.gif
140ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
141InBlock.gif        /// Gets current codegroup based on CodeGroupName at the given policylevel
142InBlock.gif        /// </summary>
143InBlock.gif        /// <param name="policyLevel"></param>
144ExpandedSubBlockEnd.gif        /// <returns>null if not found</returns>

145InBlock.gif        private CodeGroup GetCodeGroup(PolicyLevel policyLevel)
146ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
147InBlock.gif            foreach (CodeGroup codeGroup in policyLevel.RootCodeGroup.Children)
148ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
149InBlock.gif                if (codeGroup.Name.CompareTo(CodeGroupName) == 0)
150ExpandedSubBlockStart.gifContractedSubBlock.gif                dot.gif{
151InBlock.gif                    return codeGroup;
152ExpandedSubBlockEnd.gif                }

153ExpandedSubBlockEnd.gif            }

154InBlock.gif            return null;
155ExpandedSubBlockEnd.gif        }

156InBlock.gif
157InBlock.gif        public override void Uninstall(System.Collections.IDictionary savedState)
158ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
159InBlock.gif            if (debugBreakOnInstall)
160InBlock.gif                System.Diagnostics.Debugger.Break();
161InBlock.gif
162InBlock.gif            base.Uninstall(savedState);
163InBlock.gif            try
164ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
165InBlock.gif                this.UninstallCodeAccessSecurity();
166ExpandedSubBlockEnd.gif            }

167InBlock.gif            catch (Exception ex)
168ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
169InBlock.gif                System.Windows.Forms.MessageBox.Show("Unable to uninstall code access security:\n\n" + ex.ToString());
170ExpandedSubBlockEnd.gif            }

171ExpandedSubBlockEnd.gif        }

172InBlock.gif
173InBlock.gif        private void UninstallCodeAccessSecurity()
174ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
175InBlock.gif            PolicyLevel machinePolicyLevel = GetPolicyLevel();
176InBlock.gif
177InBlock.gif            CodeGroup codeGroup = GetCodeGroup(machinePolicyLevel);
178InBlock.gif            if (codeGroup != null)
179ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
180InBlock.gif                machinePolicyLevel.RootCodeGroup.RemoveChild(codeGroup);
181InBlock.gif
182InBlock.gif                // Save changes
183InBlock.gif                SecurityManager.SavePolicy();
184ExpandedSubBlockEnd.gif            }

185ExpandedSubBlockEnd.gif        }

186ExpandedSubBlockEnd.gif    }

187ExpandedBlockEnd.gif}

 

VB.Net版本的请查看:http://weblogs.asp.net/mnissen/articles/429117.aspx
setup工程View | Custom Actioninstalluninstall中添加新的Custom Action,选择生成好的Primary Output。完工。

详细内容可以参考http://weblogs.asp.net/mnissen

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Outlook 2003 addin<br> 赵果(apple) 2008年3月7日星期五<br><br><br>摘要:<br> 目前随着蓝牙、红外通信的不断发展,同步协议的应用变得越来越广泛。而同步引擎需要修改日志changelog的协助。本文的目的是记录用户对outlook2003联系人的操作日志,供同步引擎使用。<br>Outlook 2003 addin属于microsoft office com中的应用。目的是用于捕捉outlook2003 联系人(contacts)的增加、删除、修改的消息。<br><br>关键词:同步, changelog<br><br>工程介绍:<br>office com插件必须实现IDTExtensibility2接口。所有继承于IDTExtensibili ty2接口的COM插件必须实现5个方法:OnConnection,OnDisconnection,OnAddinUpdate,OnBeginShutDown,OnStartupComplete <br><br>1. 建立addin工程<br>(1) 启动VC++开发环境,新建一个工程,选择ATL COM AppWizard,为工程命名为Outlook Addin,确定。选择Dynamic Link Library完成。然后,点击菜单“插入”->“新建ATL对象”,选择“Simple Object”,命名为Addin,选择Attributes标签,选中Support ISupportErrorInfo,其他选项默认。<br>(2) 在新建的类上右键implement Interface->AddTypelib->Microsoft Add-in Designer-> IDTExtensibility2。如下图所示:<br> <br>图1 添加outlook2003接口图示<br> <br>图2 添加addin designer接口图示<br><br> <br>图3 添加接口图示<br>(3) 添加注册表信息<br>向导实现了我们所选择的接口,并为IDTExtensibility2接口的5个方法提供了默认实现。现在,一个基本的自动化COM对象就准备好了。通过向rgs文件添加注册条目,我们就可以用Outlook来注册这个插件。打开文件OAddin.rgs,在文件末尾插入以下代码:<br>HKCU_Software<br> {<br> Microsoft<br> {<br> Office<br> {<br> Outlook<br> {<br> Addins<br> {<br> 'OAddin.OAddin'<br> {<br> val FriendlyName = s 'SMIME Addin'<br> val Description = s 'ATLCOM Outlook Addin'<br> val LoadBehavior = d '00000003'<br> val CommandLineSafe = d '00000000' <br> }<br> }<br> }<br> }<br> }<br> }<br>}<br>注册条目看起来是很简单的。<br>1)LoadBehavior DWORD类型表明了Outlook装载COM插件的时机。我们的插件要在启动时装载,所以它的值设为3。LoadBehavior == 3 表示启动和连接时就自动运行;<br>• 0 = Disconnect - 不加载。<br>• 1 = Connected - 被加载。 <br>• 2 = Bootload - 宿主程序启动时加载。<br>• 8 = DemandLoad - 需要时加载。<br>• 16 = ConnectFirstTime - 只在下次运行时加载一次。<br>2)FriendlyName: 字符串类型,插件的名称,将在相应程序的COM加载对话框中看到。<br> 3)Description: 字符串类型,插件的描述信息。<br> 4)CommandLineSafe: DWORD类型,命令行方式,可以设置为0x01(真)或0x00(假)。<br><br>2. 代码分析:<br>(1)需要向outlook注册add, modify, delete事件<br>A. 申明outlook events;<br> SINK_ENTRY_INFO( 1, __uuidof(Outlook::ItemsEvents), 0xf001, getOutlookaddItemsEvents, &OnItemAddInfo )<br> SINK_ENTRY_INFO( 2, __uuidof(Outlook::ItemsEvents), 0xf002, getOutlookmodifyItemsEvents, &OnItemModifyInfo )<br> SINK_ENTRY_INFO( 3, __uuidof(Outlook::ItemsEvents), 0xf003, getOutlookdeleteItemsEvents, &OnItemDeleteInfo )<br>0xf001:add 0xf002 modify 0xf003 delete<br><br>B. 在onconnection中注册事件;<br>outlookItem_add::DispEventAdvise( (IDispatch*)m_spItemsEvents_Add, &__uuidof(Outlook::ItemsEvents) );<br><br>C. 在ondisconnection中释放事件,也是在outlook关闭时停止捕捉消息;<br><br>(2)在outlook回调你的函数中实现changeglog功能。<br>Eg: void __stdcall CAddin::getOutlookaddItemsEvents( IDispatch* pdispItemsEvents )<br>{<br> CComQIPtr<Outlook::_ContactItem> ct(pdispItemsEvents);<br>}<br><br><br>结论:<br>本人文笔不好,请各大蝦不要见笑,详细还是见代码吧,但本人能够保证程序没有任何问题。<br>本人对office系列的产品有较深的见解,并具有浓厚的兴趣。目前在研究outlook express的事件捕捉,希望有跟我志同道合的朋友欢迎跟我联系一起分享开发的快乐。QQ:35912467<br><br><br><br><br> 邮箱:my716917@sina.com<br> Hugo.zhao@mic.com.tw<br>电话:13458588397<br>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值