dbnex14 dbnex14 - 3 months ago 75
C# Question

Outlook VSTO - Adding file path/hyperlink to MailItem WordEditor from Outlook VSTO

I am having following problem. I have a window that opens and allows me to select some files.
Then I can right-click on that window and choose to attach paths of selected files to a new mail dialog.

The workflow is like this:


  1. I open my windows and select couple of files

  2. Right-click, choose to add selected files paths to MailItem

  3. Logic will check if there is an
    ActiveInspector


    3.1. If there is one, I get its
    CurrentItem as MailItem
    (so, new mail dialog exists and does not need to be created)

    3.2. If there is none, I call
    CreateItem(Microsoft.Office.Interop.OLItemType.olMailItem)
    to create
    new mail dialog and then I call
    MailItem.Display(false)
    to display
    the mail item dialog

  4. Next I loop through list of selected files paths and add them to the new mail dialog. This works great.



PROBLEM If I open my window for the 2nd time to select more files and add their paths to the same mail dialog I opened earlier, they are not added.

Here is the code:

public void AddFilePaths(List<string> paths)
{
if (paths.Count > 0)
{
var inspector = MyAddIn.Application.ActiveInspector();
MailItem mi = null;
bool newMailItem = false;

if (inspector != null)
{
// If new mail dialog is already open, just get it.
// This is called on my 2nd attempt to add paths to new mail.
// This MailItem is the same one created on 1st call in below
// else block. I confirmed that by adding some dummy email
// Body in below else block, then checking for it here on
// 2nd call. I think this proves that correct
// Inspector/MailItem is returned here.
mi = MyAddIn.Application.ActiveInspector().CurrentItem as MailItem;
}
else
{
// create new mail dialog and display it
// this is called on my 1st call to add paths to new mail
mi = MyAddIn.Application.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
mi.Body = "Dummy email body";
newMailItem = true;
}

if (newMailItem)
{
mi.Display();
inspector = MyAddIn.Application.ActiveInspector();
}

if (inspector != null)
{
foreach (var path in paths)
{
AddPathToActiveInspector(path);
}
}
}
}


The code above calls this method to add path to the current
ActiveInspector
WordEditor
:

public void AddPathToActiveInspector(string path)
{
var inspector = MyAddIn.Application.ActiveInspector();
dynamic we = inspector.WordEditor;
dynamic word = we.Application;
const string nl = "\n";

// I have noticed that if I am debugging, this line will throw error
// "COMException was unhandled by user code", "An exception of type
// System.Runtime.Interop.Services.COMException occurred in
// System.Dynamic.dll but was not handled by user code:
// Message: This command is not available
// InnerException: null
// I have also seen following error on 2nd attempt: "The TypeText
// method or property is not available because the document is
// locked for editing."
word.Selection.TypeText(nl);

string address = path;
string subAddress = "";
string screenTip = "";
string displayText = path;
word.ActiveDocument.Hyperlinks.Add(word.Selection.Range, ref address, ref subAddress, ref screenTip, ref displayText);
word.Selection.TypeText(" ");
}

Answer

I would simply create new email message each time you are adding your paths to avoid possibility of adding paths to wrong email message which could happen if you have opened multiple emails.

  1. Add reference to Microsoft.Office.Interop.Word to your project
  2. Add using Microsoft.Office.Interop.Word on top of your class file

Here is the code:

public void AddFilePaths(List<string> paths)
{
    if (paths.Count > 0)
    {
        MailItem  mi = ThisAddIn.Application.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
        mi.Display();
        if (mi!= null)
        {
            foreach (var path in paths)
            {
                AddPathsToNewEmailMessage(path);
            }
        }
    }
}

The code above calls this method to add path to the new email message WordEditor:

public void AddPathsToNewEmailMessage(string path)
{
    object link = url;
    object result = "url";
    object missing = Type.Missing;
    string nl = "\n";

    var inspector = ThisAddIn.Application.ActiveInspector();
    MailItem currMessage = inspector.CurrentItem;
    Word.Document doc = currMessage.GetInspector.WordEditor;
    Word.Selection sel = doc.Windows[1].Selection;
    doc.Hyperlinks.Add(sel.Range, ref result, ref missing, ref missing, ref link, ref missing);
    sel.EndKey(Word.WdUnits.wdLine);
    sel.InsertAfter(nl);
    sel.MoveDownWord.WdUnits.wdLine);
}