Incorporating Pocket Outlook Data into Your Microsoft .NET Compact Framework-based Applications

 

Larry Roof

April 2003

Applies to:
    Microsoft® .NET Compact Framework 1.0
    Microsoft Visual Studio® .NET 2003

Summary: Learn how to use the InTheHand Pocket Outlook .NET component. (18 printed pages)

Download InTheHandPocketOutlook.msi.

Contents

Introduction
The Pocket Outlook Object Model
Accessing POOM from .NET Compact Framework
Working with Tasks
Working with Contacts
Summary

Introduction

Microsoft® Pocket Outlook is a set of applications that is included as part of the software bundled with every Pocket PC. This set of applications includes the Calendar, Contacts, Inbox, Notes and Tasks applications.

While functionally these applications operate full and well in a standalone fashion, they are designed for use in conjunction with their larger, better-known desktop equivalent, Microsoft Outlook. Between these two platforms of PIM applications resides ActiveSync, which natively handles synchronizing data between Microsoft Outlook and the Pocket Outlook applications.

From the development point of view, Pocket Outlook offers two opportunities. First, it provides a repository of specific data: contacts, appointments and tasks. Second, it comes with automatic synchronization that allows you to be worry free of how this data moves between a device and its associated PC.

The Pocket Outlook Object Model

Applications access Pocket Outlook data through the Pocket Outlook Object Model, or as it is more commonly referred to, POOM. This COM-based library provides an object hierarchy that simplifies the process of creating, modifying and displaying appointments, tasks and contacts.

The problem is that unlike Microsoft eMbedded Visual C++® or Microsoft eMbedded Visual Basic®, applications that target the .NET Compact Framework don't natively have access to COM libraries, like POOM.

As with all Microsoft .NET Compact Framework to COM situations, the workaround is to create a non-COM dynamic link library, or DLL. This DLL acts as a go between for your .NET Compact Framework application and the COM object. The DLL is written using eMbedded Visual C++, which as I've already mentioned can directly access COM objects, including POOM. The DLL exposes a standard .NET Compact Framework friendly interface that in turn can be PInvoked from your application.

Now, if at this point you haven't already guessed, this isn't a trivial process. It requires a detailed understanding of eMbedded Visual C++, the Pocket Outlook Object Model, creating DLLs and PInvoking DLLs from a .NET Compact Framework application. Given the right amount of time and effort, you probably could struggle through this on your own. Luckily, there are two sources of aid that can significantly shorten this process: the POOM sample on the GotDotNet Web site and the Pocket Outlook .NET component offered by InTheHand.

The POOM Sample

The POOM sample demonstrates creating a DLL written in eMbedded Visual C++. You learn how to call this DLL from a .NET Compact Framework-based application. While somewhat limited in functionality, offering access to contacts only, it does show the key points and concepts behind leveraging POOM from a .NET Compact Framework-based application.

One downside of this sample is that it is written completely in C—either C++ or C#. Converting the .NET CF component to Visual Basic .NET isn't a trivial task and converting the C++ DLL to anything else is not an option.

You can download this POOM sample.

InTheHand's Pocket Outlook .NET

The second option available to .NET CF developers is the Pocket Outlook .NET component from InTheHand, a software development shop that specializes in .NET Compact Framework. Pocket Outlook .NET is a set of .NET Compact Framework classes that allows full read/write access to the Appointments, Contacts and Tasks features of Pocket Outlook.

Unlike the GotDotNet sample application, Pocket Outlook .NET is a library DLL, which can be added to your .NET Compact Framework projects, providing a robust object hierarchy. This greatly simplifies incorporating POOM into your applications.

The Pocket Outlook .NET library supports data binding so you can quickly build PIM enabled applications using standard .NET Compact Framework components such as the DataGrid and ComboBox.

From my point of view, Pocket Outlook .NET is the way to go when you need to work with Pocket Outlook data. It's easy to use, offers the right set of features and is priced right for even the smallest of development shops. This is a cool product. In fact, all of the examples and tutorials in the remainder of this whitepaper utilize Pocket Outlook .NET.

For more information on this product see www.inthehand.com.

Accessing POOM from .NET Compact Framework

As I've already mentioned, there are two ways to access POOM from the .NET Compact Framework. The first, involves creating your own native-code DLL. Detailing that approach is outside of the scope of this whitepaper because of its complexity.

The second approach makes use of the Pocket Outlook .NET component from InTheHand. All of the examples and tutorials that follow make use of this component. You'll need to download and install it to follow along or utilize any of the techniques demonstrated in the remainder of this whitepaper.

Working with the Pocket Outlook .NET Component

Once you've downloaded and installed the Pocket Outlook .NET component, there are a few steps that you need to perform in order to make use of this component within your .NET Compact Framework-based applications:

  1. Adding a reference to the Pocket Outlook .NET component
  2. Importing the Pocket Outlook namespace
  3. Defining the OutlookApplication object

Adding a reference to the Pocket Outlook .NET component

To accomplish this first step, do the following:

  1. With your project open, in the Solutions Explorer window right-click the References folder.

  2. From the popup menu, select Add Reference . . .

  3. The Add Reference dialog will display. From the list at the top of this dialog, select InTheHand.PocketOutlook.

  4. Click the Select button. The InTheHand.PocketOutlook component will be added to the Selected Components window at the bottom of the dialog as shown in Figure 1.

  5. Click the OK button, which will add the reference to your project.

    Figure 1. Adding a reference to Pocket Outlook .NET component

Importing the Pocket Outlook namespace

The second step that you need to perform is to add an Imports statement at the top of your form module. To accomplish this, perform the following steps:

  1. Open the code window for your form.
  2. Navigate to the top of that code window.
  3. Add the single line of code, shown in Listing 1 to the module.

Listing 1. Importing the Pocket Outlook namespace.

Imports InTheHand.PocketOutlook

Defining the OutlookApplication Object

The third step that you need to perform is to declare a variable for the OutlookApplication object. This object is the interface to the Pocket Outlook object model. You must always include it in your application.

Listing 2 provides an example of declaring a variable for this object. Typically, this declaration will occur at the module or project level of your application, so that the OutlookApplication is available through a broad scope.

Listing 2. Declaring the OutlookApplication object variable

[at the module level]
Dim poApplication As New OutlookApplication

NOTE   When this line of code executes, your application automatically logs into the Pocket Outlook data source. Unlike working with POOM directly, where you need to login before performing any task, the InTheHand Pocket Outlook .NET component performs this step for you.

Obtaining Help on the Pocket Outlook .NET Component

The installation package for the Pocket Outlook .NET component includes a help file titled Object Model Documentation. The installation process creates a shortcut to this document. To access this documentation, perform the following steps:

  1. Click the Start menu.
  2. From the Start menu, select Programs.
  3. From Programs, select InTheHand.
  4. From InTheHand, select Pocket Outlook .NET Wrapper.
  5. From Pocket Outlook .NET Wrapper, select the shortcut to Object Model Documentation.

This help system provides an overview of the object hierarchy provided through the Pocket Outlook .NET component. It's not intended as a how-to guide, but rather as a reference. If you're looking for how-to material, then the rest of this whitepaper is for you, starting with how to work with Pocket Outlook tasks.

Working with Tasks

The Pocket Outlook .NET component provides the ability to work with three facets of the Pocket Outlook data: tasks, contacts and appointments. We'll start our discussion of this component with tasks.

From the developer's point of view, tasks can be used for a variety of purposes. For example, they could be used within a maintenance application to record follow-up work to be completed. In a delivery system, tasks could be used to note items for the next delivery. A CRM application could record steps to perform for a particular customer.

At the core of the task functionality provided through the Pocket Outlook .NET component from InTheHand is the Tasks property and the Task object. We'll look at each of these items in greater detail next.

The Tasks Property

The Tasks property of the OutlookApplication object provides access to a collection of the tasks that reside on a device. In actuality, the Tasks property is the Tasks folder, provided through POOM. This property links through to an Items collection that contains all of the tasks.

We'll see several examples later in this section where the Tasks property, along with its Items collection is used to retrieve tasks.

The Task Object

You work with individual tasks through the Task object. Commonly used properties of this object are shown in Table 1. Frequently used methods of the Task object are shown in Table 2.

Table 1. Commonly used properties of the Task object

Property Description
Body the text of the notes accompanying a task
Categories the categories for which a task is assigned
Complete whether the task is complete
DateCompleted the date that a task was completed
DueDate the date that a task is due
Importance the importance of a task
IsRecurring whether a task is a single instance or recurs
Oid the unique identifier for a task
ReminderSet whether to remind the user of the task
StartDate the date that a task starts
Subject the subject for a task

Table 2. Commonly used methods of the Task object

Method Description
Copy creates a copy of an existing task
Delete deletes a task
Display displays a task using the native Task interface
Save saves modifications to a task

While these tables might serve you well for reference, a set of practical examples follows that provides detailed examples of commonly performed task-related operations.

Retrieving All Tasks

One of the most common functions involving tasks is the retrieving of a task(s). You can retrieve tasks in several ways:

  • As a collection of all tasks
  • As a subset of all tasks
  • As a single task

We'll start by looking at how to retrieve all tasks, as it is a frequently used approach and it is the easiest method for retrieving tasks. Listing 3 provides a simple example of retrieving all of the tasks that are resident on a device.

Listing 3. Retrieving all of the tasks

Imports InTheHand.PocketOutlook

[at the module level]
Dim poApplication As New OutlookApplication
Dim myTasks As OutlookItemCollection

Private Sub btnLoad_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles btnLoad.Click

' Retrieve all of the tasks.
  myTasks = poApplication.Tasks.Items

End Sub

The key parts to this example are:

  • The Imports statement that must be located at the top of a module
  • The declaration statement for the OutlookApplication object
  • The declaration of the OutlookItemCollection object, which can hold a collection of any Outlook items. In our case, it will hold a collection of tasks.
  • Loading the collection of tasks from the OutlookApplication object, poApplication, into the OutlookItemCollection, myTasks

At this point, the collection myTasks contains a set of task objects, one for each task that is resident on your test device. You can loop through this collection to propagate a ListBox or ComboBox, view specific task information or reference a specific task within the collection.

Retrieving Select Tasks

There will be times when you need to retrieve specific tasks. This may be either a subset of tasks or even a single task. This is easily accomplished using the Restrict method of the Items collection.

Listing 4 demonstrates retrieving a subset of tasks. This example retrieves only those tasks with the Category of "demo".

Listing 4. Retrieving select tasks

Imports InTheHand.PocketOutlook

[at the module level]
Dim poApplication As New OutlookApplication
Dim myTasks As OutlookItemCollection

Private Sub btnSelect_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles btnSelect.Click
  
  Dim strCategory As String
  Dim strQuery As String

' Retrieve the selected tasks.
  strCategory = "demo"
  strQuery = "[Categories] = " & ControlChars.Quote & strCategory & _
    ControlChars.Quote
  myTasks = poApplication.Tasks.Items.Restrict(strQuery)

End Sub

Much of the preparatory work is identical to that required to retrieve all of the tasks. You still need to add the Imports statement, declare the OutlookApplication object variable and declare the OutlookItemCollection variable.

The code used to select only the tasks we're interested in is located near the bottom of Listing 4. There we build a query string, which is nothing more than the WHERE part of a SQL SELECT statement. This query string is subsequently used with the Restrict method to retrieve only those tasks in which we're interested.

NOTE   You can restrict tasks based upon any property provided through the Task object.

Displaying a Task

One of the cool features provided through POOM is the ability to display Pocket Outlook data in its native application interface. That's to say, just like it would appear to the user had they gone into the Task application and selected to view a particular task.

POOM includes a method called Display, which is provided through the Pocket Outlook .NET component. Listing 5 demonstrates working with this method.

Listing 5. Displaying a task

Imports InTheHand.PocketOutlook

[at the module level]
Dim poApplication As New OutlookApplication
Dim myTasks As OutlookItemCollection

Private Sub btnDisplay_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles btnDisplay.Click
  
  Dim myTask As Task

' Retrieve all of the tasks.
  myTasks = poApplication.Tasks.Items

' Display the first task.
  myTask = myTasks.Item(0)
  myTask.Display()

End Sub

As with the two previous examples, you start by adding the Imports statement, declaring the OutlookApplication and OutlookItemCollection variables.

At the bottom of Listing 5 you'll see that we first retrieve all of the tasks. From this collection of tasks, we extract a single task, the first, into a Task object variable. This object provides the Display method, which in turn is called to display the selected task.

Adding a Task

Adding a new task is a three-step process. First, a new task needs to be created. Second, the new task needs to be configured. Third, the new task needs to be saved. Listing 6 demonstrates adding a task.

Listing 6. Adding a task

Imports InTheHand.PocketOutlook

[at the module level]
Dim poApplication As New OutlookApplication

Private Sub btnAdd_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles btnAdd.Click
  
  Dim myTask As Task

' Create a new task.
  myTask = poApplication.CreateTask

' Configure the task.
  With myTask
    .Body = "This is a sample task."
    .Categories = "demo"
    .DueDate = Today.Date
    .Importance = Importance.High
    .ReminderOptions = ReminderOptions.Dialog
    .ReminderSet = True
    .StartDate = Today.Date
    .Subject = "sample task"

' Finally, save the task.
    .Save()
  End With

End Sub

As with all of the previous examples, you start by adding the Imports statement, declaring the OutlookApplication and OutlookItemCollection variables.

At the bottom of Listing 6 you'll see the three steps that I described. First, the CreateTask method of the OutlookApplication object is used to create our new task. Second, properties of the new task are loaded. Third, the Task object's Save method is called to save the task.

Modifying a Task

Modifying a task is similar to adding a task, only instead of creating a new task you load a Task object with an existing task. Listing 7 shows how to modify a task.

Listing 7. Modifying a task

Imports InTheHand.PocketOutlook

[at the module level]
Dim poApplication As New OutlookApplication
Dim myContacts As OutlookItemCollection

Private Sub btnModify_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles btnModify.Click
  
  Dim myTask As Task

' Retrieve all of the tasks.
  myContacts = poApplication.Tasks.Items

' Modify the first task.
  myTask = myTasks.Item(0)
  With myTask
    .Body = "This is updated content."
    .Save()
  End With

End Sub

Once again, we start by adding the Imports statement, declaring the OutlookApplication and OutlookItemCollection variables. At the bottom of Listing 7 you'll see where the task is first retrieved (along with all other tasks) and then loaded into the Task object. At this point, you can modify any of the Task object's properties. Finish the modification process by calling the Task object's Save method.

NOTE   All of the examples demonstrated in this section are included in the Tasks project that is available to download. You will need to download and install the Pocket Outlook .NET component from InTheHand to work with this sample.

Working with Contacts

The second type of Pocket Outlook data that is useful to developers is contacts. Contacts offer developers a variety of application opportunities. They provide an easy way to incorporate contact data into a mobile application without the overhead of having to roll your own contact code.

As with tasks, contacts provide a Categories property, which is useful in identifying contacts that apply specifically to your application. Contacts are accessed through the Contacts property and the Contact object of the Pocket Outlook .NET component. Each of these items is covered in the following section.

The Contacts Property

The Contacts property of the OutlookApplication object provides access to a collection of contacts that are resident on a device. This property provides an interface to the Contacts folder within POOM, within which resides the contacts.

Several of the examples presented in this section demonstrate the use of the Contacts property along with its Items collection in working with contacts.

The Contact Object

All work with contacts themselves is handled through the Contact object. Commonly used properties of this object are shown in Table 3. Frequently used methods of the Contact object are shown in Table 4.

Table 3. Commonly used properties of the Contact object

Property Description
Body the notes accompanying a contact
BusinessAddressCity the city portion of the contact's address
BusinessAddressState the state portion of the contact's address
BusinessAddressStreet the street portion of the contact's address
BusinessFaxNumber the fax number for the contact
BusinessTelephoneNumber the business number for the contact
Categories the categories for which the contact is assigned
CompanyName the name of the contact's company
EmailAddress1 the email address for the contact
FileAs how the contact is filed; typically last name first
MobileTelephoneNumber the contact's cell phone number

NOTE   This is only a small subset of the properties provided by the Contact object. The properties detailed in Table 3 are the ones that I've found to be the most useful within a normal mobile business application. Your applications may benefit from the use of the remaining properties and as such, you should familiarize yourself with complete property list through the Pocket Outlook .NET documentation.

Table 4. Frequently used methods of the Contact object

Method Description
Copy creates a copy of an existing contact
Delete deletes a contact
Display displays a contact using the native Contact interface
Save saves modifications to a contact

While you will find both of these tables are useful for reference, the following sections, along with the examples, provide a quick-start approach to incorporating contact data into your applications.

Retrieving All Contacts

While it's unusual that your application will want to retrieve a list of all contacts, that is unless you're creating a Contact application knockoff, I'm still going to start this section by showing you how this is accomplished. As with tasks, you can retrieve contacts in several ways:

  • As a collection of all contacts
  • As a subset of all contacts
  • As a single contact

Listing 8 demonstrates how to retrieve all contacts. Please note, that depending upon the number of contacts you have resident on a device that this could result in a sizeable collection.

Listing 8. Retrieving all of the contacts

Imports InTheHand.PocketOutlook

[at the module level]
Dim poApplication As New OutlookApplication
Dim myContacts As OutlookItemCollection

Private Sub btnLoad_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles btnLoad.Click

' Retrieve all of the contacts.
  myContacts = poApplication.Contacts.Items

End Sub

The key parts of this example are:

  • The Imports statement that must be located at the top of a module
  • The declaration statement for the OutlookApplication object
  • The declaration of the OutlookItemCollection object, which holds a collection of any Outlook items. In this example, it's a collection of contacts.

Loading the collection of contacts from the OutlookApplication object, poApplication, into the OutlookItemCollection, myContacts

At this point, the collection myContacts contains a set of contact objects, one for each contact that resides on the test device. As with any collection, you can loop through the collection to access individual contacts and view specific contact information.

Retrieving a Range of Contacts

With contacts, it is more common that you will need to retrieve a subset of all contacts, rather than retrieving all contacts. This subset might be comprised of only those contacts that begin with the letter "A", or even as restrictive as a single contact.

Retrieving a subset of contacts is easily accomplished with the use of the Restrict method of the Items collection. Listing 16 demonstrates the use of this method. In this example, only contacts that begin with the letter "A" are returned.

Listing 9. Retrieving a range of contacts

Imports InTheHand.PocketOutlook

[at the module level]
Dim poApplication As New OutlookApplication
Dim myContacts As OutlookItemCollection

Private Sub btnSelect_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles btnSelect.Click

  Dim strA As String = "A"
  Dim strB As String = "B"
  Dim strQuery As String

' Retrieve contacts that begin with the letter A.
  strQuery = "[FileAs] >= " & ControlChars.Quote & strA & _
    ControlChars.Quote
  strQuery = strQuery & " AND [FileAs] < " & strB & _
     cmbPrefix.Items(cmbPrefix.SelectedIndex + 1) & ControlChars.Quote

  myContacts = poApplication.Contacts.Items.Restrict(strQuery)

End Sub

Much of the preparatory work is identical to that required to retrieve all contacts. You still need the Imports statement and to declare both the OutlookApplication and OutlookItemCollection objects.

The interesting code appears at the bottom of Listing 9. Here we build a query string, which restricts the contacts returned to only those that begin with the letter "A". Applying this string to the Restrict method provides just the contacts that we're interested in.

NOTE   You can restrict contacts using any of the properties provided through the Contact object. While typically this will be the FileAs property, you are by no means limited to it alone.

Displaying a Contact

As you have already seen with tasks, POOM provides the ability to easily access and leverage the native application interface of a data type through your application. The user sees a contact, displayed in the typical contact interface.

This functionality is provided through the Display method of the Contact object. Listing 10 shows an example of this technique.

Listing 10. Displaying a contact

Imports InTheHand.PocketOutlook

[at the module level]
Dim poApplication As New OutlookApplication
Dim myContacts As OutlookItemCollection

Private Sub btnDisplay_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles btnDisplay.Click
  
  Dim myContact As Contact

' Retrieve all of the contacts.
  myContacts = poApplication.Contacts.Items

' Display the first contact.
  myContact = myContacts.Item(0)
  myContact.Display()

End Sub

As with the two previous contact examples, you need to add the Imports statement and declaration of both the OutlookApplication and OutlookItemCollection variables into your module.

At the bottom of Listing 10 you'll see that we first retrieve all of the contacts. You could use a subset of the contacts or even a single contact as the starting point. I've chosen to demonstrate all contacts here because it's the easiest to understand.

From this collection of contacts, we extract a single contact, the first, into a Contact object of its own. It's through this Contact object that we gain access to the Display method, which in turn is called to display the selected contact.

Adding a Contact

Adding a contact is a three-step process. First, create a new contact. Second, configure the contact. Third, save the contact. Listing 11 demonstrates adding a contact.

Listing 11. Adding a contact

Imports InTheHand.PocketOutlook

[at the module level]
Dim poApplication As New OutlookApplication

Private Sub btnAdd_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles btnAdd.Click
  
  Dim myContact As Contact

' Create a new contact.
  myContact = poApplication.CreateContact

' Configure the contact.
  With myContact
    .Birthday = CDate("01/01/1960")
    .Body = "This is a sample contact."
    .BusinessTelephoneNumber = "888-555-0001"
    .Categories = "demo"
    .CompanyName = "Acme"
    .Email1Address = "joe.acme@acme.com"
    .FileAs = "Acme, Joe"
    .FirstName = "Joe"
    .LastName = "Acme"
    .Title = "President"

' Finally, save the contact.
    .Save()
  End With

End Sub

As with all of the previous contact examples, you need to start by adding the Imports statement and declaring the OutlookApplication and OutlookItemCollection variables.

At the bottom of Listing 11 you'll see the three steps I described. First, the CreateContact method of the OutlookApplication object is called to create our new contact. Second, the properties of the new contact are configured. Third, the Contact object's Save method is called to save the contact.

Modifying a Contact

Modifying a contact is similar to adding a contact, only instead of creating a new contact you load a Contact object from an existing contact. Listing 12 demonstrates this process.

Listing 12. Modifying an existing contact

Imports InTheHand.PocketOutlook

[at the module level]
Dim poApplication As New OutlookApplication
Dim myContacts As OutlookItemCollection

Private Sub btnModify_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles btnModify.Click
  
  Dim myContact As Contact

' Retrieve all of the contacts.
  myContacts = poApplication.Contacts.Items

' Modify the first contact.
  myContact = myContacts.Item(0)
  With myContact
    .BusinessTelephoneNumber = "888-555-0001"
    .Save()
  End With

End Sub

As with all of the previous contact examples, we start by adding an Imports statement and declaring the OutlookApplication and OutlookItemCollection variables. At the bottom of Listing 19, you'll find where the contact is first retrieved. In this example, all of the contacts are retrieved, but only the first contact is loaded into the Contact object. From this point, you are free to modify any of the Contact object's properties. We finish the modification process by calling the Contact object's Save method.

NOTE   All of the examples demonstrated in this section are included in the Contacts project that is available to download. You will need to download and install the Pocket Outlook .NET component from InTheHand to work with this sample.

Summary

The data stored within Pocket Outlook offers developers a tremendous opportunity. This repository of contact, appointment and task data can be leveraged from your mobile solutions written using the .NET Compact Framework-based application.

Applications access Pocket Outlook data through the Pocket Outlook Object Model. To access this COM-based library you must either create a non-COM dynamic link library or turn to a third-party component such as Pocket Outlook .NET from InTheHand.

Where to go for Additional Information

Articles

A Growing Sense of POOM

Programming with eMbedded Visual Basic and the Pocket Outlook Object Model

Programming Your Own Contacts Application with eMbedded Visual Basic

Newsgroups

microsoft.public.dotnet.framework.compactframework—information on developing applications with the .NET Compact Framework

microsoft.public.pocketpc.developer—information for Pocket PC developers

Web sites

Information Sites

MSDN Mobile and Embedded Developer Center

Devbuzz.com

Training and jump-starting programs

Larryroof.com—offers training and project consulting in designing and developing mobile applications. Services offered include five-day training courses in the .NET Compact Framework, Microsoft SQL Server™ CE and the Pocket Outlook Object Model, customized training programs, and combinations of training and project consulting to aid you in quickly implementing effective mobile solutions.