April, 2011

  • Akash Blogging......

    Office 2010 PIA installer does not install the Word PIA if only Outlook 2010 is installed


    A few days ago I ran into an issue where the customer had written an add-in for Outlook 2010 and was working with the WordEditor property of the Inspector. The add-in was to be deployed to machines which had ONLY Outlook 2010 installed. Would this work?

    Yes, It should! In this case we got an exception that says that the file Microsoft.Office.Interop.Word.dll could not be found. Digging deeper into the issue we found out that it was an issue with the PIA Installer for Office 2010. The Installed did not install the Microsoft.Office.Interop.Word.dll if Word was not installed on the machine.

    Is that what the installer should be doing? NO. The Office 2007 PIA installed worked just fine and even if only Outlook was installed on the machine it installed the PIA for Outlook as well as for Word. Yes, this is an issue with the Office 2010 PIA installer and will be fixed!

    Now what? What are my options to solve the problem?

    The only two that I see are:

    1) Distribute the Microsoft.Office.Interop.Word.dll along with the setup: This is not something that we recommend. It is recommended to always install the PIA using the Official Installer. Now since the installed is not doing it’s job, look at option 2

    2) Use Late Binding: I was able to get the add-in to work without the word PIA. Writing late binding code could be a pain but it is the only other solution that worked!

    In the sample code below we are setting the subject and the body of the message to “This text was set by the add-in”. Notice the code to insert the text “This text was set by the add-in” into the body of the message late binding and WordEditor object.

    if (activeInspector.CurrentItem is Outlook.MailItem)
    Outlook.MailItem mail = ((Outlook.MailItem)activeInspector.CurrentItem);
    mail.Subject = "This text was set by the add-in";

    if (activeInspector.EditorType == Outlook.OlEditorType.olEditorWord)
    object wordDoc = activeInspector.WordEditor;
    object wordWin = null;

    IEnumerator wordDocEnumerator = null;

    if (null != wordDoc)
    object oWindows = wordDoc.GetType().InvokeMember("Windows", System.Reflection.BindingFlags.GetProperty, null, wordDoc, null);

    if (null != oWindows)
    wordDocEnumerator = (IEnumerator)oWindows.GetType().InvokeMember("GetEnumerator", System.Reflection.BindingFlags.InvokeMethod, null, oWindows, null);

    if (wordDocEnumerator.MoveNext())
    wordWin = wordDocEnumerator.Current;

    object oSelection = wordWin.GetType().InvokeMember("Selection", System.Reflection.BindingFlags.GetProperty, null, wordWin, null);
    oSelection.GetType().InvokeMember("TypeText", System.Reflection.BindingFlags.InvokeMethod, null, oSelection, new object[] { "This text was set by the add-in" });
    MessageBox.Show("Could not find the word editor window to insert the text body into");
    MessageBox.Show("The editor type was not word, so the add-in cannot continue");

    Some good articles on binding

    I will let you know when the issue with the Office 2010 PIA installed is fixed. Enjoy!

  • Akash Blogging......

    Updating Recipients using Outlook Object Model


    One of my customers was migrating his Exchange Client Extension code to an Outlook add-in for Outlook 2010 and wanted to modify the recipient using Outlook Object Model(OOM) and ran into issues. What is the problem? In Exchange Client Extension you could hook into events like IExchExtMessageEvents::OnCheckNames and IExchExtMessageEvents::OnChecknameComplete and then from this event you would get an IExchExtCallBack interface. Using the IExchExtCallBack interface you could use the functions GetRecipients and SetRecipients to modify the recipient collection.

    The BIG question is, how can this be done using OOM?

    Unfortunately there is nothing in the Outlook Object Model that allows you to modify a recipient. We do have a workaround of first reading the existing recipients, removing the existing recipients, building a new recipient list with the changes and then adding it back to the message.

    Below is some sample C# code that demonstrated this. In this sample I first delete all the recipients from the message, build a fresh list and then add them back to the message and finally a tweak to get the UI to update.

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    this.Application.Inspectors.NewInspector +=
    new Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);

    private Outlook::MailItem mailItem = null;

    void Inspectors_NewInspector(Outlook.Inspector Inspector)
    mailItem = Inspector.CurrentItem as Outlook::MailItem;
    if (mailItem != null) {
    mailItem.BeforeCheckNames += new Outlook.ItemEvents_10_BeforeCheckNamesEventHandler(mailItem_BeforeCheckNames);

    void mailItem_BeforeCheckNames(ref bool Cancel)
    // In order to be able to add recipients, set their addressEntries, and have them display, we need to
    // 1) Remove ALL recipients from the message
    // 2) Re-add them, and set their address entries
    // 3) To get the UI to update, add and remove a final recipient

    // Step 1: remove all recipients
    int Count = mailItem.Recipients.Count;
    while (Count > 0) {
    Count = mailItem.Recipients.Count;

    // Step 2: re-add them, and set their address entries
    string[] RecipentAddresses = { "test1", "testdl", "test2" };

    for (int i = 0; i < RecipentAddresses.Length; i++)
    Outlook::Recipient recip = mailItem.Recipients.Add("test2");
    int addrType = recip.Type;

    Outlook::AddressEntry ae = Application.Session.AddressLists["Global Address List"].AddressEntries[RecipentAddresses[i]];
    recip.AddressEntry = ae;

    // need to set recipient type back to old value after re-adding
    recip.Type = addrType;

    // Step 3: (only needed in some event callbacks)
    // Now addresses have changed, but sometimes the UI doesn't update until
    // we add and remove a final recipient.
    // This workaround may not be needed in the BeforeCheckNames event, but is
    // needed in some other events if updating the recipients



  • Akash Blogging......

    Problems installing the Office 2010 PIA’s using the Microsoft Office 2010 Primary Interop Assemblies Bootstrapper Package


    Have you tried using the Microsoft Office 2010 Primary Interop Assemblies Bootstrapper Package? Did you not run into any issues? Were you able to install the PIA’s with the default package? I was not so lucky!

    One of my customer had created an add-in for Outlook 2010 and had included the Microsoft Office 2010 Primary Interop Assemblies Bootstrapper Package as part of his prerequisites for the add-in.The machine on which the add-in was being installed on did not have the PIA’s for any of the Office product installed. When the Setup.exe for the add-in was run, it still did not install the PIA’s. Why?

    After banging my head for quite a while I discovered that the componentcheck.exe was causing the issue. It always returned a value of 1. What does that mean? It means that componentcheck.exe was finding a PIA component on the machine! What was it finding when none of the PIA’s were installed?

    Componentcheck.exe checks for the following components and if it finds any one of them it returns 1.

    • Excel
    • InfoPath
    • Outlook
    • PowerPoint
    • Visio
    • Word
    • Project
    • Forms 2.0
    • Graph
    • Smart Tag
    • Office Shared

    In my case Office.dll was always there on the machine and hence componentcheck.exe was returning a value of 1. How do I get my add-in setup to install the PIA’s?

    The easiest solution is not to use the componentcheck.exe and always force the installation of the PIA’s. How can that be done? Easy…just modify the product.xml and remove the nodes for 1) PackageFile that relates to ComponentCheck.exe 2) The entire InstallChecks section as it is not needed any more 3) The BypassIf  install Condition related to PIAInstallAction and then rebuild you setup.

    Below is how the altered product.xml would look after the modification:

    <?xml version="1.0" encoding="utf-8" ?>

    Copyright (C) Microsoft Corporation. All rights reserved.

    <Product xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper" ProductCode="Microsoft.Office.PIARedist.2010">
    <DependsOnProduct Code="Microsoft.Net.Client.3.5" />
    <DependsOnProduct Code=".NETFramework,Version=v4.0,Profile=Client" />
    <PackageFile Name="o2010pia.msi" HomeSite="Office2010PIARedistMSI"
    <Commands Reboot="Defer">
    <Command PackageFile="o2010pia.msi" Arguments="/quiet" EstimatedInstalledBytes="7000000"
    <FailIf Property="AdminUser" Compare="ValueEqualTo" Value="false" String="AdminRequired" />
    <ExitCode Value="0" Result="Success" />
    <ExitCode Value="1641" Result="SuccessReboot" />
    <ExitCode Value="3010" Result="SuccessReboot" />
    <DefaultExitCode Result="Fail" FormatMessageFromSystem="true" String="GeneralFailure" />

    The not so easy way to do it would be to write your own componentcheck.exe and build your own logic to return 1 or 0. The source for the componentcheck.exe for office 2010 is not available but as a starting point you can use something that was available for Office 2007. The Component IDs of the Redistributable Primary Interop Assemblies for Microsoft Office 2010 can be found here.

Page 1 of 1 (3 items)