Monday, August 31, 2009

In Defence Of Microsoft

I’m sick of hearing people bag Microsoft for Vista, Windows 7 or Windows in general.

You read one article that says Vista is bad and no one should upgrade to it because it’s incompatible with a lot of old applications. People get all up in arms about older applications that don’t work and how Vista is useless as a result. Next, you read an article that says Windows is bloated with too much legacy code for backwards compatibility and asking why Microsoft doesn’t make a clean break and ship an OS that is entirely new, has no legacy code and therefore only works with new applications. After all, Apple did that so why can’t Microsoft ?. The answer to that question has to be, “Because people like you keep writing articles saying not to upgrade to an OS with only 70% application compatibility… how do you think the press and users would react to an OS with zero compatibility ?”.

Not to mention the fact that Vista has been out for years now, and was available to most ISV’s and IHV’s long before it shipped, so there’s no excuse for not having a Vista compatible version of your product, except perhaps if your application was written in DOS and performs direct memory access or other low-level functions that might not be allowed. In that case, it’s past time for a re-write anyway.

Of course Apple did create a new OS that wouldn’t run any older apps (at least not without virtualisation)… but they didn’t get hammered the same way as Microsoft, presumably because of the different ways the brands are perceived. Although, the difference in the size and type of markets they’re each in might also have had something to do with it.

Application incompatibility also lead to Microsoft being taken to task by the EU. Microsoft changed the kernel to make it better, more secure. This should have been a win for the consumer. Of course "Microsoft changed the kernel to make it better, more secure. This should have been a win for the consumer." this broke existing security applications that required access to the kernel that arguably no software should have had in the first place, and then the EU got involved. Some conspiracy nuts claimed this was a deliberate attempt by Microsoft to use their ‘monopoly’ to put other companies out of business. This is of course nonsense, Microsoft isn’t big player in the security space, with the exception of the security it builds into it’s own products, and it had no reason to put anyone else in that space out of business. Most of the security focused Microsoft products like Windows Defender and OneCare are free or mostly free/cheap anyway. Not to mention that one of the main benefits of Windows is the ecosystem that has been built around it and that includes all the third party security suites.

Regardless, the EU got upset and started insisting that Microsoft re-open the kernel. Excuse me ? A private company should be forced to make it’s product worse, less secure, because it’s the interest of the consumer to have more choice ? I’d rather NOT have to choose between a hundred different security suites, and even if I do I’d feel a lot better knowing the underlying OS was as secure as possible anyway. Besides, more choice doesn’t necessarily make the consumer happier.

Don’t even get me started on the whole Internet Explorer bundling issue. No one is telling GM they have to offer customers wheels manufactured by Ford or going after Apple because iTunes, the largest online music store, is tied directly to the proprietary and Apple-owned iTunes software and iPod device.

Then you get those people that complain Vista is slow. Yes, it is generally slower than XP on the same hardware (although rumour has it on some really modern PC’s the reverse is true). However on any recent PC Vista is not so slow that it’s unusable. Even if you disagree, you have to admit that generally Windows 95 was slower than 3.1, 98 was slower than 95, 2000 was slower than 98, XP slower than 2000. At least assuming you were running hardware the same age as the older OS. Vista being slower than XP is hardly a surprise or a reason not to use it on modern hardware.

Microsoft probably won’t appreciate this, but Windows 7 will probably be the first Microsoft OS that is faster than it’s predecessor. Of course you still get people blogging about how, in performance tests, Windows 7 is faster than Vista but still slower than XP for Y test. So everyone complained that Vista was too slow, ignoring any other improvements it had, and now that Microsoft is shipping a new OS that has all those other improvements and is faster as well and we’re still complaining ?

"A classic case of damned if you do and darned if you don’t."No matter what they do, or who they side with, they can do no right. Just like the compatibility mode issue in Internet Explorer 8. At first compatibility mode was going to be the default, and everybody complained because they wanted the standards to take priority to make development easier. So Microsoft changed their stance and turned compatibility mode off by default, and then everybody complained that a lot of old sites wouldn’t work properly unless the user manually switched to compatibility mode, which was likely to make the user unhappy with the site they were visiting, even if they understood how to switch modes. A classic case of damned if you do and darned if you don’t.

Despite all this, tens of thousands, if not hundreds of thousands of users (including myself) installed Vista (and IE 8), found it to be perfectly workable or even better than that and got on with our lives.

Now you might think I’m a Microsoft fan-boy. I guess you could be right, I use Windows on all my PC’s and the company I work for primarily uses Microsoft tools, operating systems etc. But I wasn’t always this way. When I was ten or twelve years old I was no less a geek and I used to walk around my school playground with my friends saying how useless Windows was and how Microsoft had a lot to answer for. After all, they brought the evils of the user interface to the PC, and clearly the command line was far superior. I dreamed and spoke of how one day I would create my own OS that would rival Microsoft Windows and since it would be technically better in every way no doubt they would wither and crumble before me. Of course I grew up in the following fifteen odd years, and so has Windows. I realise now that Windows and the other Microsoft products are actually really good most of the time, that they’re complex systems (out of necessity) that are never going to perfect for all uses, and the products have improved anyway.

Besides, while I don’t want Windows to stagnate and die, it’s actually not the most important piece of software I use. I don’t really care about the OS…  I bet you think I’m going to say the web has made it irrelevant, but I’m not. I don’t like the web, web browsers or web development much either. It’s applications and development components that are important, whether it’s a browser, a web server, a game, a word processor, an IDE, a compiler and framework, a database engine, a messaging system, a graphics editor, a document reader or whatever. The OS is primarily there to make it easier to write applications, to abstract away hardware, task switching, memory management and so on. Computers are tools, to be used to achieve things whether that’s creating a business document, sharing information or entertaining someone. The OS is a tool to make it easier for developers to write the software to achieve these things, and to provide a user interface so users can start and manage their applications. Beyond that, it holds little interest.

Even if I am a fan-boy, at least I’m prepared to listen to other arguments. There are those that will reject anything to do with Microsoft on principle, it wouldn’t matter if they had the best system technically, and it was free, and it was open source, it would still be produced by Microsoft and therefore evil. These people will even twist statistics in their favour, like suggesting that a 41% adoption rate of Windows 7 is somehow a failure despite that fact that if this number holds true it would out do the adoption rate for XP.

I’ve tried non-Microsoft, open source and Linux based systems. I haven’t gotten very far with them. Perhaps I’m just too stupid. I tried to use MySql in a project once. I"I’ve tried non-Microsoft, open source and Linux based systems. I haven’t gotten very far with them. Perhaps I’m just too stupid." downloaded MySql to find the version I’d got had no GUI and I had to do everything including creating tables from the command line. I found that too time consuming, so I spent more time looking for a GUI. I eventually found one with great recommendations, but there was no compiled version available for download. I had to go looking for a C compiler (I wasn’t writing in C and didn’t have one), then figure out how to compile the GUI application. When I finally managed that, it didn’t work. The GUI came up and seemed fine but it got weird errors when actually trying to do anything, I discovered by reading the source it was effectively shelling out the command line programs instead of using a library to integrate to the database engine itself. I’m not sure what was wrong, but I can only presume the version of the GUI I had was incompatible with the version of the MySql command line applications I had, so I gave up and decided Sql Express would do.

I’ve also looked at trying to port the Point of Sale application I work on to Linux. We want a small embedded version of it, and we planned to use CE and the compact framework. Unfortunately CE isn’t Microsoft’s best work and is in desperate need of a major update, but they don’t seem to be doing this. The compact framework isn’t a whole lot better and I can’t even find any reference to a 4.0 version, so I looked at Linux and Mono as an option. Mono has grown a lot since I last looked and it seemed like it might finally be possible to do the port… but then I realised there is no Message Queue system. Technically, Message Queue isn’t part of  .Net, it’s part of Windows (so the Mono team haven’t built it), and as far as I can tell there isn’t a Linux equivalent. At least, not one single one I can trust that ships in every distribution of Linux, and that’s another question… which Linux do I use ? Wireless driver support on Linux is also apparently a problem (although much improved in recent years). Suddenly CE doesn’t seem so bad again.

There are of course hundreds of thousands of open source products, many built on Linux and MySql. I’m not saying those products are rubbish or no good, I’m just saying that Microsoft software also offers something… often something you don’t get with non-Microsoft products (including a long history of backwards compatibility, ensuring your own applications will typically work with the next release). People often tout Linux as superior to Windows and point to some specific instance (or with no evidence at all to backup their claims). I once saw that said Linux could serve files to Windows clients on a Windows network faster than a Windows server. That sounds pretty funny and you have to start asking yourself why anyone would use Windows if it’s so poor… and the answer is because it isn’t. That article focused on one metric, performance, in one area, file sharing. There was no discussion or administration, management, configuration, security, support for different kinds of networks and so on.

Microsoft isn’t perfect, and nor is Windows or any of their other products but neither are Apple, Google, or any of their products. Nor is Linux or any of the companies that develop and distribute it, but Microsoft are the ones with the most and most vocal detractors. Mostly people just take shots at Microsoft because they’re there, and they’re big. I guess it’s tall poppy syndrome.

So anyway, if you haven’t tried Vista just because you’ve heard it’s bad or got a negative reputation, then why not give it a look and make up our own mind instead of following everyone else like a sheep. Failing that, wait for Windows 7 and give it ago… it seems to be significantly better anyway, just ignore all those nagging ninny’s who insist on rubbishing it because it’s based on Vista or because it’s not quite as fast as XP. Make your own choice. You don’t have to like it, but you should have your own opinion and not parrot someone else's.


Technorati Tags: ,,,

Sunday, August 30, 2009

Pos .Net Series, Post #5 – (TPG and Epson) Device Specific Issues

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


In my last post I discussed how the UPOS specification, and by extension Pos .Net (and OPOS) are supposed to provide device independence, but fail due to differences in service object implementation. In this post I am going to discuss some of the specific differences I have found with the hardware I have available.

Epson vs. Epson

I had a TM-T88III and a TM-T88IV both of which are Epson printers (the T88III has since died). Neither of these devices supported plug and play even when configured to using an xml file, and must be setup using the Epson SetupPOS program.

When you configure the TM-T88III there is relatively little to configure, except for port names and so on. When configuring the TM-T88IV, however, you get an option to say whether or not bitmaps stored in the printer using the SetBitmap command are stored in NVRAM or0 not. Event though the Epson TM-T88III also has NVRAM and can store and print images, it’s service object doesn’t support this setting. The TPG printer I have also doesn’t appear to have any option to use NVRAM.

There is also no way to determine how this setting is configured via the Pos .Net interfaces. This means you have no idea whether you need to call SetBitmap every time your application starts, or only when the image changes.

Not setting the image (with SetBitmap) often enough could mean your application won’t print images when you expect it to. Setting it too often could cause corruption to the memory or use up all it’s write cycles, depending on the type of memory used, and will cause an unnecessary performance hit to your application anyway.

There’s also a significant performance difference between the OPOS and native Pos .Net drivers from Epson, and sadly the native Pos .Net ones seem to be slower on the Open and Claim methods.

Epson vs. TPG

I also have a TPG A779, and this has distinct differences in implementation to the Epson TM-T88IV.

When calling SetBitmap on the Epson, it appears you can send any bitmap you want and the service object will convert it to the format required by the printer. The TPG printer, however, will throw an exception for any bitmap that isn’t a 1 bit per pixel monochrome bitmap (which is harder to create via a System.Drawing.Image object than you might expect).

Additionally, the SetBitmap method in the Epson service object will throw an exception if the extension of the image file isn’t .bmp, while the TPG one doesn’t seem to have this requirement.

The TPG printer can be setup to use plug and play if you create an appropriate xml file to map the hardware id’s to the service object, but the Epson one cannot because of the additional configuration it requires. That having been said, even the TPG doesn’t work exactly as expected when configured for plug and play, and has some odd issues around the claim functionality if the device is disconnected and reconnected after it has been claimed.

My current code also has issues with the TPG printer when trying to set the alignment for text. The code works perfectly with the Epson TM-T88IV for left, right and centre aligned, but with the TPG all text is left aligned. The TPG printer can print text in the other alignments, as my code has worked with it in the past, but I have changed some thing I can’t figure out that has broken it with the TPG device… this shouldn’t be possible though, it should work with both printers or neither.

The Epson service objects work fine when you are logged into"The TPG service objects throw an exception if the Windows user account is not at least a power user." Windows as a non-administrative user, however the TPG service objects throw an exception on open if the user account is not at least a power user. For most retail environments, even power user is too permissive for most staff, and this can cause you a problem at deployment time.

Also, as an aside, while both printers appear to print very quickly once started the Epson ones take a lot longer to start and stop printing than the TPG ones. I suspect this is because of work done in the service object at print start and end, possibly something to do with opening ports or some such.

These are just the differences I’ve found between three devices and service objects in the same device class. No doubt if I had more devices to test with I would find even more differences.

The worst differences are those where one service object throws an exception when another service object doesn’t. That will usually cause your system to either stop with an unhandled exception, or best case scenario, report the exception to the user and give them the option to retry the print or not… which is useless since reprinting will result in the same error (and possibly an incomplete receipt), and failing that the user is still going to the get error every time they print.

The morale of the story is… even though you’re using Pos .Net or OPOS, always test your system with a specific device and service object before telling a customer to purchase and install it.


Friday, August 28, 2009

Flicker Free Painting

There are two common issues that can cause your windows to ‘flicker’ while being painted. Turning on double buffering on the form and some child controls will help sort some of the issues but not all.

Hans Passant over at the Microsoft forums has found a neat little hack that will assist with some of the other issues, on Windows XP and Vista. Check out his post here;

Flicker-free Painting


Thursday, August 27, 2009

I Will Never Write Code Again…

Ok, that’s a lie, but it’s how I felt after reading a couple of posts on Eric Lippert’s blog (Fabulous Adventures In Code).

If you haven’t read Eric’s blog, you really should, it’s fantastic. At least it is when he’s not destroying your faith that any program will ever work.

The two posts in question are;

Events and Races

Locks and exceptions do not mix

The lock one was completely new information to me, simply because I had never investigated the IL generated by the .Net compilers or thought about it deeply enough.

Most of the event stuff I already knew, except for the two cases where an event handler could be called after it had been removed from the event (for details of the second one, see the comments where it’s pointed out this can happen even in single-threaded code).

While both instances make perfect sense when laid out in black and white, and I understand the reasons for them, it’s just more evidence that writing code is easy, writing good code is hard.

This is why a real programmer is never certain or sure about anything. When asked if a program works, or what a piece of code does, they will always respond with should, might, probably, I expect and other non-absolute terms. A programmer that tells you something WILL work is either naive, or lying.

Have a great day !


Wednesday, August 26, 2009

Reading A Text File

Today I had to read the content of a text file, and send that content to a service running on another server (using an existing client library to communicate with the server).

Doesn’t sound hard does it ? Well, as I’ve said before, nothing is ever easy.

To be more specific about the problem, I needed to read a .sql file containing a script that applied various schema updates, then execute the script using the ExecuteNonQuery method of a connection object.

Still doesn’t sound difficult does it ?

Now I won’t go into the details, but suffice to say I had the content provided to me as a byte array and therefore needed to convert it to a string so I could execute it.

The first problem was I assumed the byte array contained ASCII characters, but in fact it contained unicode. That was simple enough, I just used the System.Text.UnicodeEncoding.Unicode.GetString() method.

Unfortunately that wasn’t the end of it, I now had two problems;

1. The command still wouldn’t execute, I got an error from Sql Server saying incorrect syntax near ‘’. but if I viewed the string with the text debug visualiser, copied it to Sql Server Management Studio and executed it there, it worked fine.

2. I realised I couldn’t rely on a .sql file using any particular encoding, it would depend on who last edited the file with which application and which configuration as to what encoding had actually been used.

It turns out the cause of problem #1 was the solution to problem #2.

Although I couldn’t see it in my decoded string, there was a 4 byte header that specified the encoding format. A quick Google for how to read a text file in various encodings gave me some sample code which I rewrote for clarification and placed into a static method on a utility class in one our shared libraries. Here’s the code;

/// <summary>
/// Converts a byte array (usually read from a text file) to text, based on the encoding provided by the first 4 bytes of the file.
/// </summary>
/// <remarks>
/// <para>Supports ASCII, Utf8, Ucs21e, Ucs41e, Ucs161e, Utf 16, Ucs2 and Ucs4 encodings.</para>
/// <para>The string returned is stripped of the header, as well as decoded using the relevant encoding.</para>
/// </remarks>
/// <param name="data">A byte array containing the data to convert to text.</param>
/// <returns>A string containing the decoded text from the specified byte array.</returns>
public static string ByteArrayToText(byte[] data)
{
  System.Text.Encoding encoding = null;
  int startOffset = 0;
  if (data.Length >= 4 && (IsUtf8Header(data) || IsUcs21e41eOr161eHeader(data) || IsUtf16OrUcs2Header(data) || IsUcs4Header(data)))
    encoding = System.Text.Encoding.Unicode;
  else
  {
    encoding = System.Text.Encoding.ASCII;
    startOffset = 4;
  }
  return encoding.GetString(data, startOffset, data.Length - startOffset);
}
private static bool IsUcs4Header(byte[] data)
{
  return (data[0] == 0 && data[1] == 0 && data[2] == 0xfe && data[3] == 0xff);
}
private static bool IsUtf16OrUcs2Header(byte[] data)
{
  return (data[0] == 0xfe && data[1] == 0xff);
}
private static bool IsUcs21e41eOr161eHeader(byte[] data)
{
  return (data[0] == 0xff && data[1] == 0xfe);
}
private static bool IsUtf8Header(byte[] data)
{
  return (data[0] == 0xef && data[1] == 0xbb && data[2] == 0xbf);
}


You can then get your file contents however you like, so long as the result is a byte array, and pass it to the ByteArrayToText function and it will return a string with the content decoded correctly and the encoding header removed.



This code should also work in the Compact Framework 3.5.






Sunday, August 23, 2009

Red Five Labs

Check it out ! Red Five Labs have an SDK that lets you convert .Net Compact Framework applications to run on the Symbian S60 OS, for use on Nokia and Samsung phones. Very cool.

Red Five Labs

Pos .Net Series, Post #4 – Device (In)dependence

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


The primary reason for the UPOS standard and Pos .Net is to make the applications using them device independent.

This is to say that an application that uses these technologies doesn’t have to worry about the peculiarities of any specific piece of hardware, that responsibility is moved to the developer of the service object. Hopefully that developer is also the hardware vendor, so they full understand the capabilities and requirements of their device and they provide a single known service object rather than having many different third parties create their own, leaving application developers with the decision of which one to use.

In order for us to achieve device independence there is one golden rule;

The same (application) code must produce the same result and output with all devices and service objects.

Anything short of that, and you are back to worrying about whether a particular device will work with your application and hard coding exceptions to the known rules. For example, if one service object throws an exception that isn’t thrown by another under the same circumstances the device independence is now broken.

In the above case, if you tested your solution with the service object that didn’t throw an exception then you’d never know you needed to handle it until one of your customers happened to use the second service object… at which point they get an unhandled exception, your software crashes and despite it not really being your fault you’re the one that looked bad because you said any UPOS/Pos .Net device would work. At best you handle the exception anyway, which prevents the error, but still leaves the device unusable, you fail to receive input from the device or you fail to output to the device properly. None of the scenario’s is really much better because, in short and from your customers perspective, your software didn’t work.

The same applies to input and output differences when exceptions aren’t thrown. If you have a service object for each of two different"I won’t tell a customer a particular device will work until I’ve tested it, even if I'm told it’s compliant." printers, and both report they have the capability to print bitmaps (or anything else) then both must implement ALL of the bitmap printing methods, since there is no CapRecMemoryBitmap or CapRecSetBitmap. It’s no good for a service object to say it supports printing bitmaps but then only implement one of the mechanisms available for printing them.

The problem is that UPOS and Pos .Net only seem to get us half way to true device independence. UPOS provides a common set of interfaces and architecture for using devices. Pos .Net provides implementations of these interfaces and ways of discovering installed devices, Plug and Play support etc.

These specifications and implementations allow us to find and use devices in a common way that seems device independent, until you start testing with different hardware and service objects. Both systems are (necessarily) dependent on service objects for a lot of implementation detail and it would appear the UPOS specification doesn’t go far enough in describing expected behaviour. Either that, or service object developers aren’t good at following it.

In my next post I’ll discuss some of the differences in behaviour that I’ve discovered with just the very limited set of hardware I have available for testing, and why I won’t tell a customer a particular device will work until I’ve tested it, even if it says it’s UPOS/OPOS/Pos .Net compliant.


Sunday, August 16, 2009

Creating Xml Configuration Files For Pos .Net Plug and Play Support

This post is about how to create an xml file that enables Plug and Play for Pos .Net devices that don’t natively support it. For details on the Plug and Play system see my previous post.

I’m not going to cover the actual format of the xml file you need to create as it’s well documented in the SDK help.

What I will help with is how to locate the values you need to embed in the file.

Locating Hardware Ids



There are two ways to locate hardware ids for plug and play devices, either using Device Manager or Pos .Net logging (which is often easier).

Using Device Manager

The first is using Device Manager in Windows to locate the values. The easiest way to open Device Manager is to right click My Computer and choose Manage.

OpeningDeviceManager1

Then in the management console that appears, click on Device Manager.

OpeningDeviceManager2

Now for the hard part… you need to locate your device in the tree on the right. Often devices will appear either under Human Interface Devices or Universal Serial Bus Controllers. It sometimes helps to expand these nodes and then disconnect and reconnect the device to see if you can spot the entry being added.

If not, right click on each one and choose properties to see if the device has any values that identify it as the one you want.

DeviceProperties

Once you’ve found the device you’re interested in open it’s property window and go to the details tab. In the Property drop down list select Hardware Ids.

devicehardwareids

These are the values you need for your from and to hardware id attributes. See the Tricks and Traps section of this post for common gotcha’s.

Using Pos .Net Logging

This is sometimes easier than using device manager because you don’t have to hunt for the right device in a list.

First, you must enable Pos .Net Logging.

Once you’ve enabled it you need to run a program that will create an instance of the PosExplorer class. You can write your own, use one of the SDK samples, use your real application or a third party utility.

Once you have a suitable application running, connect your device. Wait a few seconds, then open the log file with notepad or another text file editor. The log file will be created in your windows temporary file folder (specified by the %TEMP% environment variable), unless you have changed the location. Again, unless you’ve changed the default settings, the log file will be called PosFor.Net(today's date and time).txt.

Go to the end of the file and then search or scroll upwards looking for the text

Searching for SO's with the following hardware id's:

The two lines immediately following this will contain the hardware id’s for the device you just connected. Here’s a portion of a sample log file;

[7/22/2009 3:28:53 PM     10  INFO     PhysicalDeviceInfo.WndProc]  Received DBT_DEVICEARRIVAL message
[7/22/2009 3:28:53 PM     10  INFO     PhysicalDeviceInfo.WndProc]  DevicePath is: \\?\USB#VID_04B8&PID_0202#J5UF019152#{5DD901C0-BCF4-11D1-9738-008029E6A5B3}
[7/22/2009 3:28:53 PM     14  INFO     PhysicalDeviceInfo.ProcessPnPEvent]  Starting processing PnP events.
[7/22/2009 3:28:53 PM     14  INFO     PhysicalDeviceInfo.ProcessPnPEvent]  Dequeued PnP Event - updating device list.  Total devices: 74
[7/22/2009 3:28:53 PM     14  INFO     PhysicalDevice]  Created PhysicalDevice for DevicePath: \\?\USB#VID_04B8&PID_0202#J5UF019152#{5DD901C0-BCF4-11D1-9738-008029E6A5B3}
[7/22/2009 3:28:53 PM     14  INFO     PhysicalDeviceInfo.ProcessPnPEvent]  Added new device to device list: USB\VID_04B8&PID_0202\J5UF019152(\\?\USB#VID_04B8&PID_0202#J5UF019152#{5DD901C0-BCF4-11D1-9738-008029E6A5B3})
[7/22/2009 3:28:53 PM     14  INFO     PhysicalDeviceInfo.ProcessPnPEvent]  Finished updating device list.  Total devices: 75
[7/22/2009 3:28:53 PM     14  INFO     PhysicalDeviceInfo.ProcessPnPEvent]  Firing DeviceAdded event
[7/22/2009 3:28:53 PM     14  INFO     Explorer]  Entering OnDeviceAddedEventHandler()
[7/22/2009 3:28:53 PM     14  INFO     Explorer]  Entering GetDevicesByHardwareIds(). Searching for SO's with the following hardware id's:
[7/22/2009 3:28:53 PM     14  INFO     Explorer]     Id: USB\VID_04B8&PID_0202&REV_0100
[7/22/2009 3:28:53 PM     14  INFO     Explorer]     Id: USB\VID_04B8&PID_0202
[7/22/2009 3:28:53 PM     14  INFO     Explorer]  Found a match: TM-T88IV Type: PosPrinter From: USB\VID_04B8&PID_0202&REV_0100 To: USB\VID_04B8&PID_0202&REV_0999
[7/22/2009 3:28:53 PM     14  INFO     Explorer]  Leaving GetDevicesByHardwareIds()
[7/22/2009 3:28:53 PM     14  INFO     Explorer]  1 matching service objects found.
[7/22/2009 3:28:53 PM     14  INFO     Explorer]  Firing a DeviceAddedEvent for service object name=TM-T88IV, type=PosPrinter

Locating Service Object Names

Hopefully you can locate your service object names in the documentation or readme files provided with your service objects.

Failing that you can use the Service Object Manager published by Sean Liming or you can write your own code.

To use the Service Object Manager, download it and run it, then click the Get Service Objects button which will load the list of installed service objects in the displayed list box.

ServiceObjectManagerSONames

To write your own code, you just need to create an instance of PosExplorer, call GetDevices() and then enumerate the returned collection looking at the ServiceObjectName property of each item;

PosExplorer posExplorer = new PosExplorer();
DeviceCollection devices = posExplorer.GetDevices();
foreach (DeviceInfo deviceInfo in devices)
{
  Console.WriteLine(deviceInfo.ServiceObjectName);
}
Console.ReadLine();


Tricks and Traps



Common traps to avoid are;

When putting any value into the xml file that contains an & (commonly used in hardware id values) or other character that is illegal in xml, ensure you encode it properly. For example, & becomes &amp;

When putting in your from and to hardware id’s, ensure you get the them the correct way around, that is the ‘fromid’ needs to be ‘less than’ the ‘toid’ as far as the computer is concerned. Device manager often shows them in reverse order. A good rule of thumb is the longer hardware id should be the ‘to’ id.

Installing and Using Your Xml File



To install a file, once you have one, you need to place it in the Pos .Net Control Configurations directory, which 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;

HKEY_LOCAL_MACHINE\SOFTWARE\POSfor.NET\ControlConfigs

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.




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

Windows Live Tags: Configuration,Files,Plug,Play,Support,devices,system,Hardware,Device,Manager,Manage,management,tree,Often,Human,Interface,Universal,Serial,Tricks,instance,PosExplorer,Wait,notepad,text,folder,TEMP,environment,location,portion,INFO,PhysicalDeviceInfo,WndProc,DBT_DEVICEARRIVAL,message,DevicePath,ProcessPnPEvent,events,Event,PhysicalDevice,Explorer,OnDeviceAddedEventHandler,GetDevicesByHardwareIds,Found,Type,PosPrinter,From,objects,DeviceAddedEvent,Service,Object,documentation,Sean,code,GetDevices,collection,ServiceObjectName,DeviceCollection,DeviceInfo,Console,WriteLine,ReadLine,Common,example,needs,File,Control,Configurations,directory,Program,Point,HKEY_LOCAL_MACHINE,SOFTWARE,ControlConfigs,Controllers,easier

WordPress Tags: Configuration,Files,Plug,Play,Support,devices,system,Hardware,Device,Manager,Manage,management,tree,Often,Human,Interface,Universal,Serial,Tricks,instance,PosExplorer,Wait,notepad,text,folder,TEMP,environment,location,portion,INFO,PhysicalDeviceInfo,WndProc,DBT_DEVICEARRIVAL,message,DevicePath,ProcessPnPEvent,events,Event,PhysicalDevice,Explorer,OnDeviceAddedEventHandler,GetDevicesByHardwareIds,Found,Type,PosPrinter,From,objects,DeviceAddedEvent,Service,Object,documentation,Sean,code,GetDevices,collection,ServiceObjectName,DeviceCollection,DeviceInfo,Console,WriteLine,ReadLine,Common,example,needs,File,Control,Configurations,directory,Program,Point,HKEY_LOCAL_MACHINE,SOFTWARE,ControlConfigs,Controllers,easier


Blogger Labels: Configuration,Files,Plug,Play,Support,devices,system,Hardware,Device,Manager,Manage,management,tree,Often,Human,Interface,Universal,Serial,Tricks,instance,PosExplorer,Wait,notepad,text,folder,TEMP,environment,location,portion,INFO,PhysicalDeviceInfo,WndProc,DBT_DEVICEARRIVAL,message,DevicePath,ProcessPnPEvent,events,Event,PhysicalDevice,Explorer,OnDeviceAddedEventHandler,GetDevicesByHardwareIds,Found,Type,PosPrinter,From,objects,DeviceAddedEvent,Service,Object,documentation,Sean,code,GetDevices,collection,ServiceObjectName,DeviceCollection,DeviceInfo,Console,WriteLine,ReadLine,Common,example,needs,File,Control,Configurations,directory,Program,Point,HKEY_LOCAL_MACHINE,SOFTWARE,ControlConfigs,Controllers,easier

How to Enable Logging in Pos .Net

The easiest way to enable logging in Pos .Net is to download my Pos .Net Plug and Play Configuration Utility and use it’s user interface to configure the logging registry settings.

PosDotNetPnpConfig4

If you want to configure logging manually, you need to edit the registry on the PC. Once you start the registry editor go to;

HKEY_LOCAL_MACHINE\SOFTWARE\POSfor.NET\Logging

Once there change the value of the Enabled setting to 1 to turn logging on, or 0 to turn logging off. Once the setting is changed to 1 log files will be created as soon as the next PosExplorer class instance is created.

Log files will be created in the folder specified by the Location value. By default this is set to %temp% which is expanded at runtime to the folder set in the TEMP environment variable.

You can also edit the Name setting to set the prefix for the log file name. The log files will start with the specified name, followed by the date, and then followed by a sequential number if multiple files are created within the same day.


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>
  <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" />
  </ServiceObject>
</PointOfServiceConfig> 


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;



HKEY_LOCAL_MACHINE\SOFTWARE\POSfor.NET\ControlConfigs



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