Welcome to MSDN Blogs Sign in | Join | Help

Ryan's Look at Outlook Programmability

new Outlook.Application
Application Shutdown Changes in Outlook 2007 Service Pack 2 Beta

As part of the performance improvements we’ve made for Outlook 2007 SP2 beta, we’ve changed the way Outlook manages the lifecycle of the application. In the past, Outlook followed the best practices for Component Object Model (COM) servers and allowed clients of the Outlook server to control the lifecycle of Outlook. This caused a significant end-user side effect: often the user could not close Outlook because of lingering external references. This is confusing and frustrating for our users, and many users would often use Task Manager to terminate the Outlook process.

As a result of strong and long-standing customer feedback about the need to close Outlook and have Outlook stop running, Service Pack 2 changes the way Outlook closes, ensuring that the user’s intent to close Outlook is respected. These changes mean the way the Outlook COM server shuts down has changed significantly, which may impact solutions using the Outlook object model outside of the Outlook process.

Impact for Add-ins: None

If you’ve written an in-process add-in for Outlook this change does not affect you. The lifecycle of in-process add-ins and in-process COM references in Outlook 2007 has always been the same as the lifecycle of the application. When the user closes the last Outlook window and Outlook starts to shut down, add-ins are disconnected and references are released.

Add-ins can use the Quit event on the Application object to determine when Outlook will be closing down. After the Quit event is raised, add-ins will have their OnDisconnection method called, and then the add-in and Outlook will close.

Impact for Cross Process Solutions

Before Outlook 2007 SP2, Outlook would check for external (out of process) references on the COM Server objects and wait for those references to be released before Outlook would close. This would enable solutions that were depending on Outlook data to keep Outlook running until the references were released. This is common behavior for COM servers, but is unexpected behavior for end users, who expect that an application will close when they close the last window of the application (or at least reasonably soon after they close the last window).

Starting with Outlook 2007 Service Pack 2, Outlook will ignore external COM references when determining if Outlook should exit. When a user closes the last Outlook window, Outlook will start exiting the process: this involves raising the Quit event on the Application object, disconnect all add-ins, disconnecting external references, persisting in-memory changes to the disk, and then exiting. All external COM references will be disconnected immediately after the Quit event is raised on the Application object.

Because of the way COM works, when Outlook releases the external references, those objects become disconnected objects in cross process solutions. When a solution attempts to use the disconnected reference, an error will result from any call to the object (RPC_E_DISCONNECTED). Solutions that are not designed to handle this error may crash or otherwise misbehave. This will occur any time a solution attempts to use an object reference after Outlook has closed.

To work correctly with the new behavior in Outlook, your solution should listen for the Quit event on the Application object. When that event is raised, stop any work in progress using Outlook data, and release all Outlook references. Any remaining references after the solution returns from the Quit event will be disconnected.

While handling the Quit event, a solution should return from the event as quickly as possible. While a solution is working in the Quit event, Outlook may appear hung to the user and the operating system and the user may forcibly terminate Outlook instead of waiting for it to finish closing.

If your solution needs to access data from Outlook after the process has shutdown, it can do so by starting the process up again in UI-less mode by calling CoCreateInstance(). However, you should attempt to design your solution such that data from Outlook is only collected while Outlook is running. I’ll be blogging about an example of how to design a solution that works this way in an upcoming blog post.

Special Cases

While the text above describes the default, we realize that there are customers and solutions which will be negatively impacted by this change until the solution can be updated. To restore the old behavior, administrators can set a registry key to force Outlook to wait for all external references to be released before closing.

This registry key applies to Outlook 2007 SP2 beta, the registry key may change for the final release of SP2.

[HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Outlook\Options\Shutdown]
“AllowShutdownWithExternalReferences”=dword:00000000

We’ve also done work to ensure that when a solution uses CoCreateInstance and Outlook isn’t running, the right things happen. In those cases, Outlook will remain running in “headless mode” without any visible user interface. If the user launches Outlook, a new Outlook window will appear in the same session Outlook was already using. If the user closes that window, even though the process was started by a solution, Outlook will exit in the same manner as it would if the application was started by the user.

Summary

As part of a larger overall performance improvement effort in Outlook 2007 Service Pack 2, the team has invested a significant amount of time to improve the experience around closing Outlook. We’ve also made changes to ensure that Outlook boots faster and is more responsive all around.

I’m interested in your feedback on this new shutdown logic, and any thoughts or questions about how we can continue to improve this experience in the next Outlook release. Please leave a comment on this post and let me know what you have to say.

Use the Right Events for the Right Cases

One of the problems I often hear about from Outlook developers is that the sequencing of a particular event isn’t ideal for what they are trying to do. While sometimes this can be a hole in the Outlook platform, more often than not it’s because the developer isn’t using the best event for the scenario they are trying to build. Outlook often has multiple events that fire related to particular actions in the UI, and choosing the right event is important to ensure data consistency.

For example, recently I was helping a partner team who wanted to examine the contents of a meeting request when the user has actually sent the request. During this event, they would compare the state of the meeting in their system against the meeting that the user was sending, and fix up any inconsistencies in their database. The developer had found the AppointmentItem_Send event in the object model, and naturally presumed that was the right event to use. However, they started to notice that inconsistencies were occurring between items in Outlook and their database. Multiple-client issues aside, the problem is because of the event they used.

The Item_Send event fires when the user clicks the Send button on sendable items (Meeting requests, e-mail messages, etc). However, there are cases where the user can back out of sending the item after they click the send button. In this particular case, when a meeting is changed, the user is sometimes given a choice to send the updates to added/removed recipients, or to all recipients. If the user clicks cancel on this dialog, the send is canceled even though the Send event has fired.

To work around this issue, I instructed the developer to listen for the Application_ItemSend event instead. This event fires after the user has committed to sending the message and ensures that the recipients on the item reflect the state of the item after the inspector has been closed.

Likewise, there is a Close event on each of the item classes, as well as a Close event on the Inspector object. To ensure that you inspect the contents of the item after all edits have occurred, catching the Inspector_Close event will provide you with the best chance to see that information. After Item_Close has fired, there is still a chance the user will back out of the changes (for example, if they click No to save their changes).

There are times where using the Item_Close and Item_Send events are very useful though. For example, if you want to be able to cancel the event and prevent the item from being closed or sent, these events have a Cancel parameter which can be set to True to prevent the action from occurring. The more deterministic events on the Inspector and Application object are not cancelable, because that would affect their determinism.

Using WPF in Outlook Folder Home Pages

One common question developers have asked is how they can extend the view area of Outlook to display additional information related to the contents of a folder.  Our solution to this problem is to use a Folder Home Page along with the Outlook View control to enable you to customize the look and feel of a folder, while still displaying folder information.

One example of an Outlook folder home page that ships with Outlook is the Outlook Today page, which is accessible by clicking on the top most folder in your default store.

Lately, developers have been interested in how they can leverage some of the new .NET Framework 3.5 enhancements like WPF in this space. Hülya Pamukçu has recently posted an article over on the CSD End-to-End Team Blog about this very subject.  In the article Hülya covers how to host WPF controls inside a folder home page and how to leverage the Outlook View Control in the space at the same time.

Command Line Parameter Changes in Outlook

As part of SP3 for Outlook 2003 (and included in SP1 for Outlook 2007) we’ve made a change to the way command line parameters are parsed to ensure Outlook is always doing the right thing.  As part of this change, a less common way of attaching files to new e-mail messages through command line parameters with Outlook may be broken in some solutions.

Previously, Outlook under some circumstances would handle an implicit command line parameter without a switch. For example, if a command line argument was provided without a switch, and was a path to a folder in the file system, Outlook would treat the argument with an implicit /select switch flag, displaying that folder in the Explorer window.  If the argument was a path to a file on the file system, Outlook would use an implicit /a switch and attach the file to a new message.

As part of making sure that our command line parameters were handled in a predictable manner, we removed the implicit logic in these service packs.  You must now explicitly specify the appropriate switch before the path to a folder to display or file to attach.  If a solution calls Outlook using an argument without a switch or with an invalid set of switches, the following error is displayed:

clip_image002

For more information on the valid command line switches that are supported by Outlook, take a look at our online documentation for command line switches.

There are a few applications that I’m aware of that have already run into this problem.  I wanted to blog about it and make sure everyone knew what was going on and how to fix a solution that no longer works as expected. Command line parameters should always be preceded by a command line switch specifying what to do with the parameter.

Edit: This change was included as part of Outlook 2007 RTM, not just SP1 as I originally stated.

Why are you still using ECEs?

Stephen Griffin is asking this question over on his blog. If you're using Exchange Client Extensions and haven't been able to port your solution over to an add-in (for a reason other than budget concerns or legacy support), now would be a good time to chime in and let him know why.

Common Properties on Outlook Controls

If you’ve started to take advantage of the new Outlook controls on form regions in Outlook 2007, you may have noticed something strange. None of the controls have common properties you would expect all controls to have: Visible, Width, Height, Top, Left, etc. You might be thinking we missed some obvious test case here, but you’d be wrong.

These properties do in fact exist on the controls. However, because of a complexity of COM and Office dependencies, the properties do not show up in the type library exposed by Outlook.

Each of the Outlook controls (they all start with Olk in the type library) also implement the Control interface from fm20.dll. This interface includes all common properties, including Height, Width, Top, Left, Name, Parent, TabIndex, TabStop, Visible and more.

If you are using a language that supports late binding for COM objects, you can just reference the property directly and everything will work as expected.

If you’re writing managed code, or other code which requires explicit definitions of the properties, you will need to cast the control object to the Control interface from fm20.dll to read or write these properties. For example, if you’re writing in C#, you would need to do something like the following:

using Outlook = Microsoft.Office.Interop.Outlook;
using MSForms = Microsoft.Vbe.Interop.Forms;

public void BeforeFormRegionShow(Outlook.FormRegion FormRegion)
{
    // Find OlkButton1 and make it invisible
    MSForms.UserForm canvas = FormRegion.Form as MSForms.UserForm;
    Outlook.OlkCommandButton button1 =
        canvas.Controls.Item("OlkButton1") as Outlook.OlkCommandButton;
    //button1.Visible = false; // can't do this, it doesn't compile
    MSForms.Control ctrlButton1 = (MSForms.Control)button1;
    ctrlButton1.Visible = false; // this works!
}

We tried to find a way to combine these two interfaces together, but because Outlook doesn’t have a dependency on the Microsoft Forms library, it wasn’t feasible to make it work right. There is at least a work-around for developers who need to access these properties.

You can also access additional Outlook-specific properties on controls by casting the control to the OlkControl interface in Outlook. This interface provides you with the ability to control layout settings for how the control will behave on the form. These properties can be set either at runtime or design time, as long as you set them before the layout is calculated (which occurs just after BeforeFormRegionShow).

Microsoft Office System Developer Conference 2008

I just noticed that the official site for the 2008 Microsoft Office System Developer Conference has gone live. For the first time this year, the conference is open to the public, so any and all Office System developers can attend. The conference will be in sunny San Jose, Feb 10-13, 2008 (and the weather should be a welcome change from Seattle's rainy Feburary weather).

The converence will provide an oppertunity for architects, developers, industry experts, and Microsoft insiders to come together to discuss developing solutions around the Office System. Should be a good event for everyone with an interest in developing solutions for the current and next generations of the Office System.

Registration will open in October. For more details about the event, check out www.odc2008.com.

Outlook 2007 GDI Leak Hotfix

If you are running Office Outlook 2007 and Windows Vista together, you might be running into the Windows GDI limit and experiencing issues with Outlook. After your Windows Vista-based computer has been running for an extended period of time, with Office Outlook 2007 running, Outlook may stop updating the screen correctly. For example, you may experience any of these symptoms:

  • Parts of the Outlook window become blank
  • Parts of the Outlook window become transparent
  • Views are draw incorrectly or incompletely
  • Icons may disappear
  • Toolbars may disappear

These symtoms are more likely to occur if you are running the Outlook Appointments gadget, 3rd party Outlook gadgets that query for calendar appointments, or a program that synchronizes your calendar.

You can confirm that Outlook has hit the limit on GDI objects by using Task Manager to view the number of GDI objects in use by Outlook.exe.  To do this, follow these steps:

  1. Press CTRL+ALT+DEL.
  2. Click Task Manager.
  3. Click the Processes tab.
  4. Click View, then Select Columns.
  5. Check GDI Objects and click OK.
  6. Click the outlook.exe process, and scroll to the GDI Objects column.

By default, Windows Vista limits processes to 10,000 GDI objects.  If Outlook is shown as using close to 10,000 objects, then this issue may be the cause of the symptoms you are seeing.

Workarounds:

To work around this issue, you can a) log off Windows, and then log on to the computer again, or b) restart the Outlook process. It may be necessary to force quit Outlook if the process does not shut down normally. To do this, follow these steps:

  1. Press CTRL+ALT+DEL.
  2. Click Task Manager
  3. Click the Processes tab.
  4. Click the outlook.exe process
  5. Click End Process, and then click End process.
  6. Launch Outlook again from the Start menu.

Update Information

This issue is related to a similar issue reported with Explorer.exe showing similar symptoms. The fix for both issues is the same, and is avaialble from http://support.microsoft.com/kb/932406.

Outlook 2007 PIA Documentation Online

Are you a managed add-in developer for Outlook 2007, who's been wondering where the documentation on the Outlook 2007 PIA might be?  Well look no further, because the Outlook 2007 Primary Interop Assembly Reference is now avaialble on MSDN.  No longer will you need to use the VBA reference shipped with Outlook 2007 when writing your managed code. This reference provides help context and information on the classes, properties, methods, events, and interfaces provided in the Outlook PIA.

Even better, if you are using Visual Studio 2005 or Visual Studio 'Oracs' you can get an integrated help experience for Outlook object model types simplying by placing the cursor on an Outlook type (for example, Items.IncludeRecurrences) and pressing the F1 key. For this to work, you do need to make sure Visual Studio is configured to try online help, either through the "Try local first, the online" or "Try online first, then local" setting in the Visual Studio help engine.

One advantage of the help being online on MSDN is that you can provide feedback and ratings on individual topics in the PIA reference by clicking the "Click to Rate and Give Feedback" link at the top of each help article. If the article really helps you out, give it 5 stars.  If you're still stuck and need more information, write a constructive comment that indicates how we can better help solve your needs.

Why does my Outlook event seem to stop working

Wes has a good post over on his blog explaining another common problem that a lot of Outlook solution developers run into:

Imagine we have some code in an Outlook addin that looks similar to code below. Does anyone see anything wrong with it? It simply places a button on the menu bar and shows a message box when the button is clicked. The code works for sometime but then all of a sudden the button mysteriously stops working. What gives? 

using Office = Microsoft.Office.Core;
using Outlook = Microsoft.Office.Interop.Outlook;
...
void SetupCommandBar(Outlook.Application application)
{
    Office.CommandBar menu = 
application.ActiveExplorer().CommandBars.ActiveMenuBar; Office.CommandBarButton button = menu.Controls.Add(
Office.MsoControlType.msoControlButton, Type.Missing, Type.Missing, Type.Missing, true)
as Office.CommandBarButton; button.Caption = "Click Me!"; button.Click +=
new Office._CommandBarButtonEvents_ClickEventHandler(button_Click); }
void button_Click(Microsoft.Office.Core.CommandBarButton Ctrl,
ref bool CancelDefault) { System.Windows.Forms.MessageBox.Show("Clicked Button!"); }

The button stops working due to the mystical powers of the .Net garbage collector. If we look closely we notice that the button object is locally scoped in the SetupCommandBar function, thus once we execute that function the button object is free to be cleaned up. However, until the button object is actually destroyed by the garbage collector the button click event will fire and the button will work. Due to the non-deterministic nature of the garbage collector we have no idea how long the button will work. In my simple testing it seemed to work for a little while but if you want to speed up the process add a call go GC.Collect in the button_Click callback.

The easiest fix for this problem is to change the scope of the button object to be a member variable of enclosing class. By doing this we ensure that the button object stays alive and works until we are ready for it to stop working.

Mysterious Errors When Using Form Regions from Managed Code Add-ins

I've been noticing some feedback lately where a number of developers were having problems working with the controls on their form region.  Usually, these problems manifested as Outlook's object model returning null values back when trying to access the Controls collection of the UserForm object in the Microsoft Forms 2.0 library (which was accessed from the FormRegion.Form property).

This can be especially frustrating, because it looks like you've done everything right, and Outlook is just giving you back something that is totally wrong. Turns out, that isn't quite the case.

If you've added a reference to the 'Microsoft Forms 2.0' type library, you might have added the wrong reference to your project. On some computers, you'll find two different listings for the forms type library in the Add Reference dialog:

Depending on which reference you select, you'll either get a reference properly associated with the Primary Interop Assembly provided by Office, or you'll get a reference with a Visual Studio generated interop assembly. Unfortuatnely, the VS generated interop assembly incorrectly maps some elements of the type library to elements in the interop assembly.  This ultimately means that when you are using this reference, you'll end up calling into a different property or method than your code appears to be calling, which causes various strange exceptions and errors.

You can easily determine which reference you are using by selecting the reference and looking at the properties of the reference. If you've added the self-generated IA reference, the properties will look like this:

Notice that the reference has "Copy Local" set to True, and that the Path is not pointing at the Global Assembly Cache (GAC) but rather to the location of my solution.  This indicates that I'm using a self-generated interop assembly, and that I may be running into issues.

If you've added the correct reference to the PIA, then you'll see properties that look like this instead:

This time around, you'll see the Path is pointing into the GAC, and the "Copy Local" property is False. This indicates the PIA is being used, and everything should work normally.

If you find your project is using the incorrect reference, you should remove the reference and add a new reference.  Unforutnately, there is no way to determine which reference is the "right" reference from the Add References dialog.  You'll simply need to use trial and error and double check after adding the resource to make sure you've picked the right one.

The Take-away: Make sure you are using the right interop assembly when working with custom forms or form regions from your managed code solution.  Using the Visual Studio generated interop assembly can cause mysterious errors in your solution that you may not catch right away.

New Outlook Team Blog

We've just rolled out the new Outlook team blog, which is the "one-stop-shop for tips, tricks, and rants directly from the Outlook product team."

Don't worry though, my blog won't be going away.  I'll continue to blog about Outlook programmability, custom forms, and other developer-centric parts of Outlook.

Outlook 2007 Performance Update

If you've been watching other blogs, or the recently published KB articles, you probably have seen this already, but I thought I'd point it out for the rest of you.  Last week we released an update for Outlook that fixes some issues that we were not able to fix for Outlook 2007 RTM.  Included in this fix are a couple of performance tweaks which help out some of the performance problems users were reporting when running with a large PST or OST file and Outlook 2007.

More details of the update are avaialble in the associated KB article: http://support.microsoft.com/kb/933493.

Direct link to the patch download here.

This won't fix everyone's performance problem, but it does make several common causes for performance issues in Outlook 2007 less of an issue.

Warning:  If you're using Outlook 2007 with Business Contact Manager, you should read this article first.  There is a follow up patch you need to install to maintain the full functionality of Business Contact Manager.

Outlook and Internet mail support

OK, so this might be a bit off-topic from my regular blog posts, but since I am working on the Internet mail experience for the next release of Outlook, I wanted to hear from some of you about your experiences using our Internet mail account types (POP and IMAP).

In Outlook 2007, we did some improvements to make these account types work better.  For example, in IMAP we now allow you to configure your Sent Items folder to actually live on the IMAP server instead of in a local PST file.

Back to the questions however:

  • How could we improve your experience using Outlook for Internet mail?
  • What do other clients do that you'd like to see Outlook do?
  • Do you use Outlook on more than one computer with your Internet accounts?

Of course, if you have other suggestions or comments you'd like to add about our Internet mail support, then you can add those to the comments as well.  I'll make sure to read them all and reply as approriate.

PDF Preview Handler for Outlook/Vista

If you're running Windows Vista, or Outlook 2007 on either Vista or Windows XP, you're probably wondering just how long you have to wait until you can use the preview capabilities of your new operation system or Outlook client to view PDF documents.

While I still haven't seen an official solution to the problem from Adobe or any of the other typical PDF reader component companies, I have found a few answers online.  There are a couple of different downloads that will solve your problems, depending on the PDF reader you favor.

  • Foxit: Tim Heuer has partnered with Foxit software to create Foxit PDF Preview Handler, which works with Foxit Reader.
  • Acrobat: I've created a similar freeware component that works with Adobe Acrobat Reader 7.x or later.  If you favor using Adobe Acrobat, take a look at my PDF Preview Handler.

If you know of another solution to the problem, add a comment here so other users can find a solution for their PDF previewing problems.

More Posts Next page »
Page view tracker