M
Michael
I am writing an Outlook COM Add-in in C# (Visual Studio .NET 2003) which
attempts to modify an XML view definition for an Outlook folder (similar to
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnout2k2/html/odc_customviews.asp )
..
It works fine on my development machine, but when I distribute the add-in
using a setup project, the view definition change does not work (both
Windows XP SP1 and Outlook 2003 SP1), though no errors are reported. Other
parts of my add-in do work; only the view definition change does not appear
to work.
I have installed the Office XP PIAs on my system, since I want my add-in to
work for Outlook XP as well as Outlook 2003. I reference them directly (
which I'm not supposed to do according to the PIA readme file and
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnoxpta/html/odc_oxppias.asp )
, though I tried it the proper way with the same results. The 4 PIAs
related to Outlook are included in my setup project (as Detected
Dependencies), I have imported the registry entries, and I have them
installing to the GAC. I suspect that the method for installation of my
program and/or the PIAs is related to my problem, but I could be wrong, of
course.
Below is a small program which demonstrates the issue I am encountering
(this is not my actual project, just a test program). All of the action
happens in the OnConnection method. The program creates a folder under the
Inbox, copies an email there, and modifies the view such that only the
Subject field is displayed (removing the From, Received, etc fields). Any
help/advice is appreciated. -- Michael
------------------------- Connect.cs -------------------------
namespace OutlookAddinTest
{
using System;
using Microsoft.Office.Core;
using Extensibility;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Xml;
using Outlook = Microsoft.Office.Interop.Outlook; // Office XP PIAs
[GuidAttribute("E08191FA-C5B7-4835-AB11-1F2C67A85EB7"),
ProgId("OutlookAddinTest.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2
{
public Connect()
{
}
/// <summary>
/// Implements the OnConnection method of the IDTExtensibility2
interface.
/// Receives notification that the Add-in is being loaded.
/// </summary>
/// <param term='application'>
/// Root object of the host application.
/// </param>
/// <param term='connectMode'>
/// Describes how the Add-in is being loaded.
/// </param>
/// <param term='addInInst'>
/// Object representing this Add-in.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnConnection(object application, Extensibility.ext_ConnectMode
connectMode, object addInInst, ref System.Array custom)
{
// Get the application and namespace
Outlook.Application olApp = (Outlook.Application) application;
Outlook.NameSpace olNs = olApp.GetNamespace("MAPI");
// Find the Inbox
Outlook.MAPIFolder olInboxFolder =
olNs.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
// Create a folder under the Inbox
Outlook.MAPIFolder newFolder = olInboxFolder.Folders.Add("Test Folder",
Outlook.OlDefaultFolders.olFolderInbox);
// Assume there is an email in the Inbox...
Outlook.MailItem randomEmail = (Outlook.MailItem) olInboxFolder.Items[1];
// Copy it to the new folder (by making a copy and then moving the copy).
// This will just make it easier to the see the results of the view
changes... it is not completely necessary.
Outlook.MailItem newEmail = (Outlook.MailItem) randomEmail.Copy();
newEmail = (Outlook.MailItem) newEmail.Move(newFolder);
// Create a new view
Outlook.View newView1 = newFolder.Views.Add("Test View",
Outlook.OlViewType.olTableView,
Outlook.OlViewSaveOption.olViewSaveOptionThisFolderOnlyMe);
// Let's look at the default XML (in the debugger)
Debug.WriteLine(newView1.XML, "View XML");
// Modify the XML
newView1.XML = XmlModifiedUsingXmlManipulation(newView1.XML);
// Note: I had also tried hand-editing the default XML and assigning it
here (rather than using the
// XmlModifiedUsingXmlManipulation method) with the same results.
newView1.Save();
newView1.Apply(); // Oddly, this line generates an error (for me) in
Office XP...
}
/// <summary>
/// Modify Outlook View XML using C# XML routines.
/// </summary>
/// <param name="xmlString">XML string from an Outlook View</param>
/// <returns></returns>
private string XmlModifiedUsingXmlManipulation(string xmlString)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
XmlNode docNode = xmlDoc.DocumentElement;
// Remove most columns
foreach (XmlNode column in docNode.SelectNodes("//column"))
{
if (column.SelectSingleNode("prop").InnerText !=
"urn:schemas:httpmail:subject" &&
column.SelectSingleNode("prop").InnerText != "DAV:href")
{
Debug.WriteLine("Deleting project column " + column.InnerXml, "XML
Column");
column.ParentNode.RemoveChild(column);
}
else
{
Debug.WriteLine("Leaving project column " + column.InnerXml, "XML
Column");
}
}
// Turn off new item row and "in cell" edit.
XmlNode x = docNode.SelectSingleNode("newitemrow");
if (x != null)
{
x.InnerText = "0";
}
x = docNode.SelectSingleNode("incelledit");
if (x != null)
{
x.InnerText = "0";
}
string newXML = xmlDoc.InnerXml;
// Let's look at the default XML
Debug.WriteLine(newXML, "New XML");
return newXML;
}
public void OnDisconnection(Extensibility.ext_DisconnectMode
disconnectMode, ref System.Array custom)
{
}
public void OnAddInsUpdate(ref System.Array custom)
{
}
public void OnStartupComplete(ref System.Array custom)
{
}
public void OnBeginShutdown(ref System.Array custom)
{
}
}
}
attempts to modify an XML view definition for an Outlook folder (similar to
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnout2k2/html/odc_customviews.asp )
..
It works fine on my development machine, but when I distribute the add-in
using a setup project, the view definition change does not work (both
Windows XP SP1 and Outlook 2003 SP1), though no errors are reported. Other
parts of my add-in do work; only the view definition change does not appear
to work.
I have installed the Office XP PIAs on my system, since I want my add-in to
work for Outlook XP as well as Outlook 2003. I reference them directly (
which I'm not supposed to do according to the PIA readme file and
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnoxpta/html/odc_oxppias.asp )
, though I tried it the proper way with the same results. The 4 PIAs
related to Outlook are included in my setup project (as Detected
Dependencies), I have imported the registry entries, and I have them
installing to the GAC. I suspect that the method for installation of my
program and/or the PIAs is related to my problem, but I could be wrong, of
course.
Below is a small program which demonstrates the issue I am encountering
(this is not my actual project, just a test program). All of the action
happens in the OnConnection method. The program creates a folder under the
Inbox, copies an email there, and modifies the view such that only the
Subject field is displayed (removing the From, Received, etc fields). Any
help/advice is appreciated. -- Michael
------------------------- Connect.cs -------------------------
namespace OutlookAddinTest
{
using System;
using Microsoft.Office.Core;
using Extensibility;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Xml;
using Outlook = Microsoft.Office.Interop.Outlook; // Office XP PIAs
[GuidAttribute("E08191FA-C5B7-4835-AB11-1F2C67A85EB7"),
ProgId("OutlookAddinTest.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2
{
public Connect()
{
}
/// <summary>
/// Implements the OnConnection method of the IDTExtensibility2
interface.
/// Receives notification that the Add-in is being loaded.
/// </summary>
/// <param term='application'>
/// Root object of the host application.
/// </param>
/// <param term='connectMode'>
/// Describes how the Add-in is being loaded.
/// </param>
/// <param term='addInInst'>
/// Object representing this Add-in.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnConnection(object application, Extensibility.ext_ConnectMode
connectMode, object addInInst, ref System.Array custom)
{
// Get the application and namespace
Outlook.Application olApp = (Outlook.Application) application;
Outlook.NameSpace olNs = olApp.GetNamespace("MAPI");
// Find the Inbox
Outlook.MAPIFolder olInboxFolder =
olNs.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
// Create a folder under the Inbox
Outlook.MAPIFolder newFolder = olInboxFolder.Folders.Add("Test Folder",
Outlook.OlDefaultFolders.olFolderInbox);
// Assume there is an email in the Inbox...
Outlook.MailItem randomEmail = (Outlook.MailItem) olInboxFolder.Items[1];
// Copy it to the new folder (by making a copy and then moving the copy).
// This will just make it easier to the see the results of the view
changes... it is not completely necessary.
Outlook.MailItem newEmail = (Outlook.MailItem) randomEmail.Copy();
newEmail = (Outlook.MailItem) newEmail.Move(newFolder);
// Create a new view
Outlook.View newView1 = newFolder.Views.Add("Test View",
Outlook.OlViewType.olTableView,
Outlook.OlViewSaveOption.olViewSaveOptionThisFolderOnlyMe);
// Let's look at the default XML (in the debugger)
Debug.WriteLine(newView1.XML, "View XML");
// Modify the XML
newView1.XML = XmlModifiedUsingXmlManipulation(newView1.XML);
// Note: I had also tried hand-editing the default XML and assigning it
here (rather than using the
// XmlModifiedUsingXmlManipulation method) with the same results.
newView1.Save();
newView1.Apply(); // Oddly, this line generates an error (for me) in
Office XP...
}
/// <summary>
/// Modify Outlook View XML using C# XML routines.
/// </summary>
/// <param name="xmlString">XML string from an Outlook View</param>
/// <returns></returns>
private string XmlModifiedUsingXmlManipulation(string xmlString)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
XmlNode docNode = xmlDoc.DocumentElement;
// Remove most columns
foreach (XmlNode column in docNode.SelectNodes("//column"))
{
if (column.SelectSingleNode("prop").InnerText !=
"urn:schemas:httpmail:subject" &&
column.SelectSingleNode("prop").InnerText != "DAV:href")
{
Debug.WriteLine("Deleting project column " + column.InnerXml, "XML
Column");
column.ParentNode.RemoveChild(column);
}
else
{
Debug.WriteLine("Leaving project column " + column.InnerXml, "XML
Column");
}
}
// Turn off new item row and "in cell" edit.
XmlNode x = docNode.SelectSingleNode("newitemrow");
if (x != null)
{
x.InnerText = "0";
}
x = docNode.SelectSingleNode("incelledit");
if (x != null)
{
x.InnerText = "0";
}
string newXML = xmlDoc.InnerXml;
// Let's look at the default XML
Debug.WriteLine(newXML, "New XML");
return newXML;
}
public void OnDisconnection(Extensibility.ext_DisconnectMode
disconnectMode, ref System.Array custom)
{
}
public void OnAddInsUpdate(ref System.Array custom)
{
}
public void OnStartupComplete(ref System.Array custom)
{
}
public void OnBeginShutdown(ref System.Array custom)
{
}
}
}