我想将自定义c#windows窗体(或WPF)用户控件嵌入到Outlook视图中。 我正在使用Outlook 2003和Visual Studio 2008。
我在这里下载了一个Outlook 2007的示例:
也在这里:
http://msdn.microsoft.com/en-us/library/aa479345.aspx
我测试了它并且在2007年它正在工作,但是在2003年我想要打开视图时出现以下错误:
由于错误80131509无法完成操作
我可以从Visual Studio启动它,它正好注册文件夹,调试工作等等。它创建一个HTML页面,其中包含我的类型作为对象参数 - 但是应该调用的Initialize方法不存在(不通过JS显示)或者它有一些错误。
RegisterSafeForScripting的断点也永远不会被击中 - 可能与此有关。
答案 0 :(得分:1)
听起来您需要为程序集创建运行时安全策略。 Visual Studio / VSTO 自动设置。您可以通过从Visual Studio运行项目然后在管理工具下打开Microsoft .NET Framework 2.0配置应用程序来检查这一点。浏览到运行时安全策略并检查代码组。 VSTO项目在用户>代码组> All_Code> VSTOProjects。
以下是我的笔记。
代码访问安全策略工具使用户和管理员可以修改计算机策略级别,用户策略级别和企业策略级别的安全策略。
使用Windows Installer为Office System SE解决方案部署Visual Studio 2005工具(第1部分,共2部分)
答案 1 :(得分:0)
首先感谢AMissico - 我将查看您提供的说明和链接。 follwinng代码为我做了诀窍(但按钮控件和其他人已经打破了布局 - 但WFP工作,所以我将使用wpf)。我必须重构代码,但它是我的工作版本......
我终于发现这个例子在我稍微调整一下之后起作用了: http://www.microsoft.com/downloads/details.aspx?familyid=078124E9-1E88-4F51-8C98-3C1999CFE743&displaylang=en
以下文件或多或少取自上面的例子
using System;
using System.IO;
using System.Collections.Generic;
using MSOutlook = Microsoft.Office.Interop.Outlook;
using System.Runtime.InteropServices;
namespace Outlook2003KnowledgeBaseAddIn.Setup
{
public sealed class FolderHomePage
{
/// <summary>
/// List of web view files that have been written out during this Outlook intance
/// </summary>
private static List<string> listWebViewFiles = new List<string>();
/// <summary>
/// Registers a specific managed type as a folder home page. Returns a file path for the folder home page
/// </summary>
/// <param name="viewType">Type of the home page control.
/// Control must be ComVisible should be registered safe for scripting</param>
/// <returns>file path to the folder home page</returns>
public static string RegisterType(Type viewType)
{
if (viewType == null)
return null;
//TODO: ensure that viewType inherits from System.Windows.Forms.Control
//Create the Local App Data directory for the Web view files to reside in
string webViewDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Properties.Resources.WebViewDirectoryName);
if (Directory.Exists(webViewDirectory) == false)
Directory.CreateDirectory(webViewDirectory);
//Create the web view file name based on the viewType guid in the web view directory
string webViewFile = Path.Combine(webViewDirectory, viewType.GUID.ToString("N") + ".htm");
//if the file has been written out already in this session, return
if (listWebViewFiles.Contains(webViewFile))
return webViewFile;
//If the file exists, delete it (for versioning reasons)
if (File.Exists(webViewFile))
File.Delete(webViewFile);
//Open a file stream and text writer for the Web view stream
FileStream stm = new FileStream(webViewFile, FileMode.Create, FileAccess.Write);
TextWriter writer = new StreamWriter(stm, System.Text.Encoding.ASCII);
//Look to see if the viewType has an init method that takes a single Outlook App parameter
System.Reflection.MethodInfo initInfo = viewType.GetMethod("Initialize", new Type[] { typeof(MSOutlook.Application) });
//If the viewType doesn't have an Init method, just write out the html page header
//TODO move HTML code to resource strings
if (initInfo == null)
{
writer.WriteLine("<html><body rightmargin = '0' leftmargin ='0' topmargin ='0' bottommargin = '0'>");
}
//If the viewType does have an Init method, write script to trap the Body.OnLoad event and call the Init method
//passing in the window.external.OutlookApplication object as the parameter
else
{
writer.WriteLine("<html><body rightmargin = '0' leftmargin ='0' topmargin ='0' bottommargin = '0' onload='OnBodyLoad()'>");
writer.WriteLine("<script>\n\tfunction OnBodyLoad()\n\t{\n\t\tvar oApp = window.external.OutlookApplication;");
writer.WriteLine("\t\t{0}.Initialize(oApp);", viewType.Name);
writer.WriteLine("\t}\n</script>");
}
//Write out an object tag that loads up the viewType as a com object via its class id
writer.WriteLine("<object classid='clsid:{0}' ID='{1}' VIEWASTEXT width='100%' height='100%'/>", viewType.GUID, viewType.Name);
writer.WriteLine("</body></html>");
//Close the file
writer.Close();
stm.Close();
//save this file name so we don't write it out multiple times per outlook session
listWebViewFiles.Add(webViewFile);
return webViewFile;
}
private const string CATID_SafeForScripting = "7DD95801-9882-11CF-9FA9-00AA006C42C4";
private const string CATID_SafeForInitializing = "7DD95802-9882-11CF-9FA9-00AA006C42C4";
/// <summary>
/// Registers a managed type that's exposed for COM interop as safe for initializing and scripting
/// </summary>
/// <param name="comType"></param>
public static void RegisterSafeForScripting(Type comType)
{
Guid clsid = comType.GUID;
Guid interfaceSafeScripting = new Guid(CATID_SafeForScripting);
Guid interfaceSafeForInitializing = new Guid(CATID_SafeForInitializing);
ICatRegister reg = (ICatRegister)new ComComponentCategoriesManager();
reg.RegisterClassImplCategories(ref clsid, 1, new Guid[] { interfaceSafeScripting });
reg.RegisterClassImplCategories(ref clsid, 1, new Guid[] { interfaceSafeForInitializing });
}
/// <summary>
/// Unregisters a managed type that's exposed for COM interop as safe for initializing and scripting
/// </summary>
/// <param name="comType"></param>
public static void UnregisterSafeForScripting(Type comType)
{
Guid clsid = comType.GUID;
Guid interfaceSafeScripting = new Guid(CATID_SafeForScripting);
Guid interfaceSafeForInitializing = new Guid(CATID_SafeForInitializing);
ICatRegister reg = (ICatRegister)new ComComponentCategoriesManager();
reg.UnRegisterClassImplCategories(ref clsid, 1, new Guid[] { interfaceSafeScripting });
reg.UnRegisterClassImplCategories(ref clsid, 1, new Guid[] { interfaceSafeForInitializing });
}
}
[ComImport(), Guid("0002E005-0000-0000-C000-000000000046")]
class ComComponentCategoriesManager
{
}
[ComImport(), Guid("0002E012-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ICatRegister
{
void RegisterCategories(int cCategories, IntPtr rgCategoryInfo);
void UnRegisterCategories(int cCategories, IntPtr rgcatid);
void RegisterClassImplCategories(
[In()] ref Guid rclsid,
int cCategories,
[In(), MarshalAs(UnmanagedType.LPArray)] Guid[] rgcatid);
void UnRegisterClassImplCategories(
[In()] ref Guid rclsid,
int cCategories,
[In(), MarshalAs(UnmanagedType.LPArray)] Guid[] rgcatid);
void RegisterClassReqCategories(
[In()] ref Guid rclsid,
int cCategories,
[In(), MarshalAs(UnmanagedType.LPArray)] Guid[] rgcatid);
void UnRegisterClassReqCategories(
[In()] ref Guid rclsid,
int cCategories,
[In(), MarshalAs(UnmanagedType.LPArray)] Guid[] rgcatid);
}
}
与此文件一起:
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Policy;
using System.Security;
using Outlook2003KnowledgeBaseAddIn.Setup;
using Outlook2003KnowledgeBaseAddIn.UI;
using Outlook2003KnowledgeBaseAddIn.UI.OutlookIntegration;
namespace Outlook2003KnowledgeBaseAddIn
{
[System.ComponentModel.RunInstaller(true)]
public class Installer : System.Configuration.Install.Installer
{
public Installer()
{
}
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
try
{
ConfigureSecurityPolicy();
RegisterFolderHomePages();
}
catch (Exception ex)
{
throw new System.Configuration.Install.InstallException("Custom Installer Failed", ex);
}
}
public override void Uninstall(System.Collections.IDictionary savedState)
{
base.Uninstall(savedState);
try
{
DeleteSecurityPolicy();
UnregisterFolderHomePages();
}
catch (Exception ex)
{
throw new System.Configuration.Install.InstallException("Custom Installer Failed", ex);
}
}
private void RegisterFolderHomePages()
{
//Utility.FolderHomePage.RegisterSafeForScripting(typeof(FolderHomePages.AccountToday));
FolderHomePage.RegisterSafeForScripting(typeof(WebViewControl));
}
private void UnregisterFolderHomePages()
{
//Utility.FolderHomePage.UnregisterSafeForScripting(typeof(FolderHomePages.AccountToday));
FolderHomePage.UnregisterSafeForScripting(typeof(WebViewControl));
}
private void ConfigureSecurityPolicy()
{
// Find the machine policy level
PolicyLevel machinePolicyLevel = GetMachinePolicyLevel();
// Get the install directory of the current installer
string assemblyPath = this.Context.Parameters["assemblypath"];
string installDirectory =
assemblyPath.Substring(0, assemblyPath.LastIndexOf("\\"));
if (!installDirectory.EndsWith(@"\"))
installDirectory += @"\";
installDirectory += "*";
// Create the code group
CodeGroup codeGroup = new UnionCodeGroup(
new UrlMembershipCondition(installDirectory),
new PolicyStatement(new NamedPermissionSet("FullTrust")));
codeGroup.Description = Properties.Resources.CasPolicyDescription;
codeGroup.Name = Properties.Resources.CasPolicyName;
// Add the code group
machinePolicyLevel.RootCodeGroup.AddChild(codeGroup);
// Save changes
SecurityManager.SavePolicy();
}
private static void DeleteSecurityPolicy()
{
PolicyLevel machinePolicy = GetMachinePolicyLevel();
foreach (CodeGroup codeGroup in machinePolicy.RootCodeGroup.Children)
{
if (codeGroup.Name == Properties.Resources.CasPolicyName)
machinePolicy.RootCodeGroup.RemoveChild(codeGroup);
}
SecurityManager.SavePolicy();
}
private static PolicyLevel GetMachinePolicyLevel()
{
System.Collections.IEnumerator policyHierarchy = SecurityManager.PolicyHierarchy();
while (policyHierarchy.MoveNext())
{
PolicyLevel level = (PolicyLevel)policyHierarchy.Current;
if (level.Type == PolicyLevelType.Machine)
return level;
}
throw new ApplicationException("Could not find Machine Policy level. Code Access Security is not configured for this application.");
}
}
}
此方法设置Web视图:
private void CreateWebViewFolders()
{
MSOutlook.MAPIFolder root = Folder.GetRootFolder(Application.Session);
MSOutlook.MAPIFolder webViewFolder = Folder.CreateFolder(root, Properties.Resources.WebViewFolderName);
webViewFolder.WebViewURL = FolderHomePage.RegisterType(typeof(WebViewControl));
webViewFolder.WebViewOn = true;
}