Windows Mobile Device Emulator Programmability - Just Needs a Find-Emulator Function

You Can Take it With You

Syndication

News

  • Don't miss the next Windows Mobile Webcast... Unit Testing for Mobile Devices: http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032382824&EventCategory=4&culture=en-US&CountryCode=US.

When you install Visual Studio 2008, you automatically get an updated version of the Windows Mobile Device Emulator (version 3) and Device Emulator Manager. As you may know, the new Device Emulator Manager exposes a programmable interface; the programmable interface allows you to write desktop computer applications that can programmatically access all of the interactive features of the Device Emulator Manager. These features include connecting an emulator, cradling an emulator, resetting the emulator, and so on.

The emulator features are intuitive and easy to use; basically each of the emulator functions corresponds directly to a Device Emulator Manager menu options. The one thing that is a bit of a challenge is getting access to a specific emulator.

The Device Emulator Manager organizes the emulators hierarchically: the Device Emulator Manager contains Categories which contain SDKs which contain Emulators. To reach an emulator you have to loop through the levels above it; there's no way to access an emulator directly.

What makes reaching a specific emulator a minor challenge is that the Device Emulator Manager API does not provide standard enumerators over the collections representing each level of the hierarchy. Another factor is that the API is implemented as COM Automation interfaces and uses COM HRESULTS (error codes) to indicate status changes such as end-of-data.

When using the API from .NET, the .NET interoperability layer interprets these non-zero HRESULTS as errors and translates them into COMExceptions. As a result, when looping through a collection, you have to catch a COMException to handle the end-of data. Similarly, the API indicates an empty collection by throwing a COMException when you attempt to access the first member of the collection. So your looping code ends up looking a bit verbose because of the layers of try/catch required.

The solution is to have a FindEmulator function that encapsulates all of these details so that you can easily get right to the emulator of interest.

My goal is to have a utility that allows you to work with the emulators using code like the following...

// Would generally be declared at the class level
IDeviceEmulatorManager _demManager;
DEMUtility _demUtility;

 

// Create once
_demManager = new DeviceEmulatorManagerClass();
_demUtility = new DEMUtility(_demManager);

 

// Now can just search for emulators by name
IDeviceEmulatorManagerVMID theEmulator = _demUtility.FindEmulator("Windows Mobile 5.0 Pocket PC Emulator");
if (theEmulator != null)
{
  EMULATOR_STATE state = theEmulator.get_State();
  if (state == EMULATOR_STATE.EMU_NOT_RUNNING)
    theEmulator.Connect(); // start emulator
  if (state != EMULATOR_STATE.EMU_CRADLED)
    theEmulator.Cradle(); // cradle to start ActiveSync
}

I've written a simple DEMUtility class that supports using the emulators as shown above.

You basically create an instance of the DEMUtility class passing a reference to a IDeviceEmualtorManager (top-level interface of the DEM Automation API). Once you've done that you can search for individual emulators by calling the DEMUtility class' FindEmulator function and passing the emulator's display name (name that appears in the Device Emulator Manager's interactive display). Each emulator is also identified by a GUID called a VMID. If you know the VMID for a particular emulator, you can pass the VMID to FindEmulator in place of the name.

Here's the implementation of the DEMUtility class

class DEMUtility
{
  const int END_OF_DATA = -2147024637;
  const int E_ENUMSDK_NOT_LOADED = -2147209216;
  const int E_ENUMSDK_INVALID_ENUMVMID = -2147209215;
  const int E_ENUMVMID_NOT_LOADED = -2147209214;
  const int E_ENUMVMID_INVALID_VMID = -2147209213;

  IDeviceEmulatorManager _emulatorManager;

  public DEMUtility(IDeviceEmulatorManager emulatorManager)
  {
    if (emulatorManager == null)
      throw new ArgumentException("Must provide a valid IDeviceEmulatorManager Reference", "emulatorManager");
    _emulatorManager = emulatorManager;
  }

  public IDeviceEmulatorManagerVMID FindEmulator(string nameOrVmid)
  {
    string categoryName;
    string sdkName;
    string emulatorName;
    string emulatorVMID;

    if (string.IsNullOrEmpty(nameOrVmid))
      throw new ArgumentException("Must provide a non-null, non-empty emulator name or VMID", "nameOrVmid");

    try
    {
      _emulatorManager.Reset();
      while (true)
      {
        categoryName = _emulatorManager.get_Name();
        IEnumManagerSDKs sdkEnum = _emulatorManager.EnumerateSDKs();
        sdkEnum.Reset();
        try
        {
          while (true)
          {
            try
            {
              sdkName = sdkEnum.get_Name();

              IEnumVMIDs vmidEnum = sdkEnum.EnumerateVMIDs();
              vmidEnum.Reset();
              try
              {
                while (true)
                {
                  try
                  {

                    IDeviceEmulatorManagerVMID tempEmulator = vmidEnum.GetVMID();
                    emulatorName = tempEmulator.get_Name();
                    emulatorVMID = tempEmulator.get_VMID();

                    if (emulatorName == nameOrVmid ||
                        emulatorVMID == nameOrVmid)
                      return tempEmulator; // If name or VMID matches, return

                  }
                  catch (COMException ex)
                  {
                    // Indicates no emulator
                    if (ex.ErrorCode == E_ENUMVMID_INVALID_VMID ||
                      ex.ErrorCode == E_ENUMVMID_NOT_LOADED)
                      break;
                    else
                      throw ex;
                  }
                  vmidEnum.MoveNext();
                }
              }
              catch (COMException ex)
              {
                // End of data
                if (ex.ErrorCode != END_OF_DATA)
                  throw ex;
              }
            }
            catch (COMException ex)
            {
              // Indicates empty SDK
              if (ex.ErrorCode == E_ENUMSDK_NOT_LOADED)
                break;
              else
                throw ex;
            }
            sdkEnum.MoveNext();
          }
        }
        catch (COMException ex)
        {
          // End of data
          if (ex.ErrorCode != END_OF_DATA)
            throw ex;
        }
        _emulatorManager.MoveNext();
      }
    }
    catch (COMException ex)
    {
      // API signals end-of-data with a No More Data HResult.
      if (ex.ErrorCode != END_OF_DATA)
        throw ex;
    }

    return null; // No match found
  }
}

I know the FindEmulator function looks a bit unusual but that's due to needing to handle the various COMExceptions along the way. There's really no simpler way to loop through the DEM hierarchy.

To use the Device Emulator Manager automation features or the DEMUtility class you need to add a reference to %Program Files%\Microsoft Device Emulator\1.0\Microsoft.DeviceEmulatorManager.Interop.9.0.dll using the "Browse" tab on the Add Reference dialog. You also need to add using statements (imports for VB) to the Microsoft.DeviceEmulatorManager.Interop and System.Runtime.InteropServices namespaces.

A "How Do I?" video and a MSDN paper on using the Device Emulator Manager automation features will be available shortly.

BTW: If anyone needs the DEMUtility class source code in Visual Basic .NET, let me know via feedback to this blog entry and I'll post that version of the code as well.

As always, questions are welcome.


Posted Oct 30 2007, 08:45 AM by jim-wilson

Comments

Michael N wrote re: Windows Mobile Device Emulator Programmability - Just Needs a Find-Emulator Function
on 06-24-2008 12:45 AM
Hi,

I think my question is along the same lines ares you article. I need to write a .NET WinForms application that will include the emulator from the SDK so that the end user can preview content in the Pocket IE web browser before publishing. Do you know if I can access the emulator through an API and if so perhaps you might also know what the impact of licensing might be? Is there a (emulator) redistributable for this type of application.

Thank you in advance.
Mike
Jim Wilson wrote re: Windows Mobile Device Emulator Programmability - Just Needs a Find-Emulator Function
on 06-24-2008 7:40 AM
Michael;

There are stand-alone emulator images available but configuring their installation correctly on a computer that doesn't have Visual Studio installed is a challenge to say the least.

I'm actually in Redmond (I live in NH) working on a project today. I'll talk to a couple of people on the emulator team and see if they can provide some insight into the best way to proceed.

I'll follow up here as soon as I have some info.

Jim

Add a Comment

(required)  
(optional)
(required)  
Remember Me?