Getting sign in/sign out status via Office Communicator 2007 SDK

When using the Office Communicator 2007 SDK, you need to make sure that OC is running and signed in before you use classes from the SDK.  I often get email from developers new to the OC SDK who are getting errors when they try to debug their first applications.  For example, if OC 2007 R2 is not running on the client machine, you’ll get the following COMException when you try to create a instance of the Messenger class:

“Creating an instance of the COM component with CLSID {8885370D-B33E-44B7-875D-28E403CF9270} from the IClassFactory failed due to the following error: 80040111.”

Or, if Office Communicator is running but the user has not signed in, you’ll get the following error trying to access your instance of the Messenger class:

“Exception from HRESULT: 0x8100031E” (an error code that translates to not logged on if you refer to the OC SDK documentation).

So, how do you make sure OC 2007 R2 is running and signed in before you enable your OC SDK features (and disable them when that status changes)? 

This video shows as example of this in a simple console application:

Chris – Added video.

To see if Office Communicator is running, read the HKEY_CURRENT_USER\Software\IM Providers\Communicator\UpAndRunning value via code:

    1:          static bool IsCommunicatorRunning()
    2:          {
    3:              return Convert.ToInt32(Microsoft.Win32.Registry.CurrentUser
    4:                              .OpenSubKey("Software").OpenSubKey("IM Providers")
    5:                              .OpenSubKey("Communicator").GetValue("UpAndRunning", 1)) == 2;
    6:          }

If this registry value is 2, OC is up and running and you’re able to create instances of Messenger class.  Messenger class can be used to wire up events to track changes to Office Communicator or the sign in status of the local user and query the initial sign in status of the local user.  For example, the following code does just that:

    1:          private static Messenger _messenger;
    2:          private static bool _signedIn = false;
    4:          static void Main(string[] args)
    5:          {
    6:              if (IsCommunicatorRunning())
    7:              {
    8:                  _messenger = new Messenger();
   10:                  _messenger.OnAppShutdown += new DMessengerEvents_OnAppShutdownEventHandler(_messenger_OnAppShutdown);
   11:                  _messenger.OnSignin += new DMessengerEvents_OnSigninEventHandler(_messenger_OnSignin);
   12:                  _messenger.OnSignout += new DMessengerEvents_OnSignoutEventHandler(_messenger_OnSignout);
   14:                  if ((_messenger.MyStatus & MISTATUS.MISTATUS_ONLINE) == MISTATUS.MISTATUS_ONLINE)
   15:                  {
   16:                      _signedIn = true;
   17:                  }
   18:                  else
   19:                  {
   20:                      _signedIn = false;
   21:                  }
   23:                  Console.WriteLine("\nPress Enter key to exit the application.\n");
   24:                  Console.ReadLine();
   26:                  _messenger.OnAppShutdown -= new DMessengerEvents_OnAppShutdownEventHandler(_messenger_OnAppShutdown);
   27:                  _messenger.OnSignin -= new DMessengerEvents_OnSigninEventHandler(_messenger_OnSignin);
   28:                  _messenger.OnSignout -= new DMessengerEvents_OnSignoutEventHandler(_messenger_OnSignout);
   30:                  Marshal.ReleaseComObject(_messenger);
   31:                  _messenger = null;
   32:              }
   33:          }

The following line sets the initial value of the _signedIn by using Messenger.MyStatus and the & operator, evaluating to true if the local user is in any of the online states (any value other than Offline or Unknown including Online, In a Call, etc.):

    1:                  if ((_messenger.MyStatus & MISTATUS.MISTATUS_ONLINE) == MISTATUS.MISTATUS_ONLINE)

The _signedIn value is kept up to date via the Messenger class events for signed in status:

    1:          static void _messenger_OnSignout()
    2:          {
    3:              _signedIn = false;
    4:          }
    6:          static void _messenger_OnSignin(int hr)
    7:          {
    8:              if (hr == 0)
    9:              {
   10:                  _signedIn = true;
   11:              }
   12:          }
   14:          static void _messenger_OnAppShutdown()
   15:          {
   16:          }

Note: OnSignOut will always fire before OnAppShutdown, so setting _signedIn to false during OnSignOut is enough to keep your application up to date.

If you’d like to try this code out for yourself, you’ll need to download the Office Communicator 2007 SDK and setup a UC development environment.

More details, tips and tricks on UC development can be found in the Programming for Unified Communications book.