How to make PocketPC development hard on yourself
One of my favorite “features” of the .NET Compact Framework is its compatibility with the regular .NET Framework. I love the idea of writing the same code to execute on multiple platforms (can you hear the snickers from the Java crowd?).
Deployment and debugging support for the Compact Framework are pretty impressive, but still not as easy as a desktop application. So when I started work on my PocketPC “Drawing Web File” viewer program, I started with a desktop WinForms application project. I figured I could create all of the file parsing and image manipulation logic in a shared library which would be referenced by the two GUI applications (one for the desktop, one for the PocketPC). So I added a Class Library project to my solution. Then I added a Smart Device project, and chose the Windows Application option on the second page of the wizard (this phrase is in italics, in an attempt at foreshadowing). I wrote some simple drawing classes in the library, then used them in both GUI apps. Both GUI's ran the code as expected. Cool!
So then I continued to flesh out the details of the library, using only the desktop GUI for testing and debugging. Once the library was at a point I was happy with, I started to work on the PocketPC GUI application. And that is where the nightmare began. Code that had just been working fine on the desktop app was now failing on the PPC app. It didn't make sense. I could compile the PPC app and the library with no errors. But then during runtime, I would get “method not found” type exceptions. Apparently I was calling methods (or more often, method overloads) that did not exist in the Compact Framework. This was completely foreign to me, since I was accustomed to the strongly typed .NET environment always finding those kinds of problems at compile time.
I finally realized that the class library project had references to the System.* assemblies in the .NET Framework installation folder, while the Smart Client Windows Application project had references to the System.* assemblies in the Compact Framework installation folder. So I then manually removed the standard references from the class library, and added them back, using the files in the Compact Framework folder. That seemed to improve the situation a bit - I started to get compile time errors in the Smart Client project, which helped me identify the incompatible code, but things still didn't seem to work as expected.
After a little bit of googling, I discovered the key: when developing a shared class library, you must use the Smart Device Class Library project template NOT the “normal” Class Library template. The Smart Device project type is “retargetble” (or something along those lines), which means it automatically associates with the correct shared assemblies based on the target platform: PocketPC or desktop. But wait, on initial inspection, there IS no Smart Device Class Library project template! There is just “Smart Device Application”. But... what was that about a second page of a wizard? Ah. You need to choose Smart Device Application, which then launches a second page, which allows you to choose between “Windows Application” or “Class Library”. After rebuilding my shared library project using the Smart Device Class Library template, all my mysterious problems went away. I now had full intellisense which told me exactly which methods and overloads were available on the Compact Framework.
So, to make a completely unnecessarily long story short: when building a Compact Framework application that is going to share code with a .NET Framework (proper) application, make sure to use the Smart Device Class Library project type.