Sunday, August 09, 2009

Pos .Net Series, Post #3 – Plug and Pray Issues

This is the third post in a series on my initial experiences with using Microsoft Pos .Net. The first post can be found here.

It turns out the Plug and Play feature of Pos .Net is a bit thorny.

Originally this post was going to tell you about what a great feature it would be, if I could get it to work.

Then, it was going to about what a great feature it is, and how I made it work… after I had a break-through earlier this week.

Now, sadly, we’re back to how great it would be if it worked.

If you’re interested, you can read about my troubles in my Pos .Net forum posts on the topic;

Issue #1 – DeviceAddedEvent Won’t Fire

Issue #2 – Epson Service Objects Won’t Work

About the Plug and Play Feature

The plug and play feature in Pos .Net should do two things;

    Notify your application when a device is connected or disconnected, giving you ‘hot swappable’ devices and allowing you to notify the user when a device is accidentally unplugged.

    Allow you to use a device with ‘zero configuration’.

No one talks much about the second point, but it’s obvious if you look at the pattern displayed in the sample code, which is;

    Get notified of a device being connected.
    Instantiate the device object.
    Open (claim, enable) and use the device.
    Get notified of a device being disconnected.
    Close and stop using the device.

You’ll note that no where in there was there anything about configuration screens, asking the user or administrator about which port the device is on or anything like that… you plug in the device and it just works, just like on your desktop PC with consumer devices.

The way the system works is;

    When you instantiate the PosExplorer object in Pos .Net it begins listening to the Windows based Plug and Play events.

    When a plug and play ‘connect’ event is received, it attempts to match the hardware id’s for the newly connected device to an installed service object. If a matching service object is found and the device is not already thought to exist (i.e calling PosExplorer.GetDevices() prior to the event would not have returned this device) then the DeviceAddedEvent event is raised.

    When a plug ‘disconnect’ event is received, it determines if the hardware id’s for the connected device match an existing active service object and if so raises the DeviceRemovedEvent.

In order for this to work (automatically), you need two things;

    A native Pos .Net service object installed.
    The service object must expose a hardware id value that matches the device you want to use it with.

This means the system has three flaws. Firstly, it won’t work with legacy service objects, such as OPOS drivers. Secondly, it won’t with a native Pos .Net service object unless the service object developer embedded a hardware id (which often isn’t the case). Finally, it assumes a 1:1 mapping between service object and hardware, so any ‘generic’ service objects won’t expose hardware id’s because they work with ‘any compatible’ device.

However… Microsoft thought ahead and all is not lost (yet).

Mapping Service Objects To Devices

So what do you do if you want to enable Plug and Play but your service objects don’t support it ? Simple, you create an xml configuration file that maps a range of hardware id values to a service object.

The contents and layout of the file is specified in the Pos .Net Sdk Documentation but let’s have a look at a sample while we’re discussing it;

<PointOfServiceConfig Version="1.0"> 
  <ServiceObject Type="PosPrinter" Name="TM-T88III"> 
    <HardwareId From="USB\VID_0451&amp;PID_1428&amp;REV_0100" To="USB\VID_0451&amp;PID_1428" /> 
    <HardwareId From="USB\VID_04B8&amp;PID_0202&amp;REV_0101" To="USB\VID_04B8&amp;PID_0202" /> 
  <ServiceObject Type="PosPrinter" Name="TM-T88IV">
    <HardwareId From="USB\VID_04B8&amp;PID_0202&amp;REV_0100" To="USB\VID_04B8&amp;PID_0202&amp;REV_0999" />
    <HardwareId From="USB\VID_04B8&amp;PID_0202" To="USB\VID_04B8&amp;PID_0202" />

I’ve got another post on how to find the values needed and create your own configuration files here.

A couple of quick notes; You must encode the & character, that is used commonly in hardware ids, as &amp; just like you would in any xml document.

Also make sure you don’t do what I did and get your from and to hardware ids around the wrong way… that’s a sure fire way to ensure the mapping won’t work.

Using a configuration file like this allows you to use plug and play with legacy OPOS service objects, Pos .Net service objects that don’t expose hardware id’s and even map multiple hardware id’s to the same service object.

To make the file active, you must save it to the Control Configurations directory created by the Pos .Net install. This is usually;

C:\Program Files\Common Files\microsoft shared\Point Of Service\Control Configurations

But the only way to get the exact file location is to read the registry key;


Your configuration file will be read each time the PosExplorer class is instantiated, so if you edit or replace it with a newer one, you will need restart your application or at least cause it to re-create the PosExplorer object before the new content will be used.

Typically, you’d install or upgrade the configuration file when you install or upgrade your application software.

Snatching Defeat from the Jaws of Victory

So that sounds great, doesn’t it ? Plug and play lets your users connect and use devices just by plugging them in, and now that you can configure any device to work automagically using a configuration file there’s nothing left to worry about, right ?

Sigh. Wrong.

Despite all this some service objects, notably those in the Epson OPOS ADK for .Net, still won’t work in plug and play mode.

The Epson devices require xml configuration details to be provided in a global configuration file at; %ProgramData%\Microsoft\Point Of Service\Configuration\Configuration.xml. If this file doesn’t exist or doesn’t contain the expected entries, then the service object will throw an error with the message

The information is not described in XML.

when you call the Open method of the device.

This xml configuration is created by running the SetupPOS utility provided by Epson with their ADK. If you configure a device using this utility, then PosExplorer.GetDevices() always returns the device regardless of whether or not it is actually connected, turned on etc. Because the device ‘always exists’ as far as Pos .Net is concerned, the DeviceAddedEvent won’t be raised because Pos .Net thinks you already know about the device.

A second problem I am personally having is with the second USB pos printer I have, a TPG peripheral. In this case I can get the plug and play event to work, and I can successfully open the device in the event, but I cannot use the device – I am told that it is disabled, even though my code explicitly enables the device first.

I’m not able to debug or test this on my development PC because I can’t physically connect the printer to it, so it’s likely this is a bug of mine rather than a problem with the TPG service object or Pos .Net itself.

I’ve also tried using the OPOS test applications with the TPG device, and they have some very strange behaviour. While they do seem to work once the printer is connected, if I disconnect the printer and reconnect after I have it claimed and enabled I can still print to it (good); but I can also call Claim and DeviceEnabled again and they succeed.  This leads me to suspect that perhaps the device is no longer claimed for exclusive access even though I can print to it. Not good at all !

Plug and Play Isn’t Enough

One last word of warning.

Even if you successfully get plug and play working with your devices, you must still support the other method of loading devices, calling PosExplorer.GetDevices(). This would usually be done on start-up.

This is required for the following reasons;

    The DeviceAddedEvent event is only raised for devices connected AFTER the PosExplorer instance the event is published on was created. If the device is already plugged in and turned on when you create PosExplorer, you won’t get the event.

    You may still find your users buy a device that doesn’t natively support plug and play and that you haven’t pre-configured to support it, and of course they will still expect to be able to use that device with your software. By calling PosExplorer.GetDevices() you can still access and locally configured non PnP devices.

Technorati Tags: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

Windows Live Tags: Plug,Pray,Play,troubles,forum,topic,Issue,DeviceAddedEvent,Fire,Epson,Service,Objects,Work,Feature,Notify,devices,user,zero configuration,configuration,code,Instantiate,Open,Close,administrator,port,system,PosExplorer,events,event,GetDevices,DeviceRemovedEvent,expose,legacy,OPOS,Microsoft,contents,Documentation,PointOfServiceConfig,Version,ServiceObject,PosPrinter,Name,HardwareId,files,Control,Configurations,directory,Program,Common,Point,location,HKEY_LOCAL_MACHINE,SOFTWARE,POSfor,ControlConfigs,Defeat,Jaws,Victory,mode,ProgramData,error,message,method,SetupPOS,printer,development,instance,flaws,users,hardware

WordPress Tags: Plug,Pray,Play,troubles,forum,topic,Issue,DeviceAddedEvent,Fire,Epson,Service,Objects,Work,Feature,Notify,devices,user,zero configuration,configuration,code,Instantiate,Open,Close,administrator,port,system,PosExplorer,events,event,GetDevices,DeviceRemovedEvent,expose,legacy,OPOS,Microsoft,contents,Documentation,PointOfServiceConfig,Version,ServiceObject,PosPrinter,Name,HardwareId,files,Control,Configurations,directory,Program,Common,Point,location,HKEY_LOCAL_MACHINE,SOFTWARE,POSfor,ControlConfigs,Defeat,Jaws,Victory,mode,ProgramData,error,message,method,SetupPOS,printer,development,instance,flaws,users,hardware

Blogger Labels: Plug,Pray,Play,troubles,forum,topic,Issue,DeviceAddedEvent,Fire,Epson,Service,Objects,Work,Feature,Notify,devices,user,zero configuration,configuration,code,Instantiate,Open,Close,administrator,port,system,PosExplorer,events,event,GetDevices,DeviceRemovedEvent,expose,legacy,OPOS,,contents,Documentation,PointOfServiceConfig,Version,ServiceObject,PosPrinter,Name,HardwareId,files,Control,Configurations,directory,Program,Common,Point,location,HKEY_LOCAL_MACHINE,SOFTWARE,POSfor,ControlConfigs,Defeat,Jaws,Victory,mode,ProgramData,error,message,method,SetupPOS,printer,development,instance,haven,flaws,users,hardware

1 comment:

  1. Hello Admin,
    Awesome Post! I like writing style, how you describing the topics throughout the post. I hope many web reader will keep reading your post at the end, Thanks for sharing your view.
    DOT NET Course Chennai|DOT NET Training Institute in Chennai