Windows Desktop (XP/Vista) and Windows Mobile have the benefit of being a well defined application platform, if you write an application to run on Windows Vista then you know that the same application will also run on another PC running Vista, if you write a Windows Mobile 6 Professional (Pocket PC) application then you know that the same application will also run on other WM 6 Professional devices (assuming that you have catered for different screen resolutions, DPI, orientation etc…) – the point being that the underlying API set for the “platform” is very well defined – this isn’t the case on Windows “Embedded” CE.
CE 6.0 is an operating system that can be customized by developers by choosing the set of underlying o/s components they need for their device, this in turn drives the exposed API set for a specific operating system image. There isn’t a concept of a “Standard Windows CE Platform” (unless you consider Windows Mobile to be that standard platform) – Application developers don’t know whether an application they have written for one custom Windows CE platform will run on another platform since the underlying components and therefore API’s are probably going to be different across the devices.
This isn’t strictly true of course – in many respects the .NET Compact Framework does add an application compatibility layer to the operating system at two levels, the first is the .NET Compact Framework and exposed assemblies/classes – since the Compact Framework isn’t componentized you know for sure that a .NET Compact Framework application written for one device will run on another device that includes the framework (assuming that the application doesn’t p/invoke out to operating system specific APIs). The second level of compatibility is the underlying dependencies that are added to the operating system through adding the .NET Compact Framework to a Windows CE operating system image, knowing that the .NET Compact Framework is on an embedded device gives you a known set of native code APIs to call on the operating system.
So how do you know whether your application is going to run on a device ? – one way to find out is to copy the application (and support files) to the device and run the application, this could give one of two results, either the application crashes with an “Invalid Operation” error message, or appears to run correctly – I say “appears” to run, it’s possible that you haven’t tested all code paths within the application, or didn’t dynamically load a DLL that calls into missing operating system functions (and then causes the application failure).
An application developer may well build and test their application on a specific configuration of the CE 6.0 operating system – once the application is written the import tables of the application and support binaries could be used to build a list of needed DLLs and exposed functions (take a look at “Dumpbin /imports”) – this list could then be compared against a specific platform by writing an o/s ‘checker’ tool – this tool would need to be Win32, C/C++ and not rely on any specific o/s technologies beyond reading a text file [containing the list of DLL’s and functions], the utility could read the name of a DLL and the names of exposed functions and try loading the DLL (LoadLibrary) and then check to see if the exposed function was there (GetProcAddress) – if all DLL’s exist, and all functions return with a valid address then you are in business. Of course, the alternative is to get a list of known operating system components (SYSGENs) needed by your application and provide this to the company building the embedded device.