Subscribe: C# on the SmartPhone
Added By: Feedage Forager Feedage Grade B rated
Language: English
activesync  code  desktop  device  devices  gps  mobile  net  new  roam  sql  string  today screen  windows mobile  windows 
Rate this Feed
Rate this feedRate this feedRate this feedRate this feedRate this feed
Rate this feed 1 starRate this feed 2 starRate this feed 3 starRate this feed 4 starRate this feed 5 star

Comments (0)

Feed Details and Statistics Feed Statistics
Preview: C# on the SmartPhone

C# on the SmartPhone

Updated: 2017-11-23T06:04:08.294-08:00


The Importance of SqlCeCommand.Parameters


One popular post on this blog discussed the reasoning behind the SqlCeCommand.Parameters functionality in the .NET SQL libraries. Since the original post back almost two years ago (August 14th, 2006), I have used other SQL libraries in other languages including Java and Python. They also provide parameterized queries in addition to the traditional text based queries. Thus, this design is quite common.Although you might be tempted to write your queries using string.Format and SqlCeCommand.CommandText, it is much better to let the SQL library interpret your parameters automatically. Ilya Tumanov, a member of the .NET Compact Framework Team, commented on my original post with a list of advantages that are worth repeating:Yes, parameterized query is a preferred way. Benefits are: No need to create bunch of string objects all the time (in your code). No need to convert parameters from binaries to strings (in your code). No need to parse strings to get binaries back (in SQL CE). No locale/format specific issues as binary is format less and locale independent. No need to redo each command from scratch, prepared execution plan can be used with just different parameters. Works for all data types including binary/image.Performance benefits from using parameters range from significant to really huge.The reasoning behind this post is to emphasize the red bullet point above. Recently, I have been receiving emails from users of the MyExperience tool who have tried to run the program on devices that are using non-English language versions of Windows Mobile. For the most part, MyExperience uses parameterized queries. I painstakingly went over every query a few years ago and made sure of that. Unfortunately, I missed a spot and this was the cause of the incompatibility.The offending query looked something like this:sqlCmd.CommandText = string.Format("SELECT VersionId FROM Versions WHERE VersionName='{0}' AND VersionNumber='{1}' AND VersionModifiedDate='{2}'", vName, vNumber, vDate);A keen reader may note that this query is region specific because it includes a DateTime object. The String.Format method was formatting the date based on the regional configuration of the device. This seemed to be incompatible with the date format that SQL Server Mobile was expecting. To fix this, I updated this code to read:sqlCmd.CommandText = "SELECT VersionId FROM Versions WHERE VersionName=@VName AND VersionNumber=@VNumber AND VersionModifiedDate=@VModDate";sqlCmd.Parameters.Add("@VName", mev.VersionName);sqlCmd.Parameters.Add("@VNumber", mev.VersionNumber);sqlCmd.Parameters.Add("@VModDate", mev.ModificationDate);Thus, I kept the data in binary format which is, as Ilya pointed out, region/locale independent.[...]

Operation Could Not Be Completed. Device Is Not Connected.


When attempting to debug one of my Windows Mobile applications this evening, I ran into this error:

The operation could not be completed. The device is not connected.

The error occurred after I right clicked on a project in my solution and selected Debug->Start new instance. After a bit of Googling, I determined that the root cause of this message (in my case) was that my project was referring to content that was not actually on my local disk. Earlier in the day I had moved some XML files outside of the project directory, which my project still erroneously referred to. Once I deleted links to these files in my project, I was able to successfully debug my application.

There is an msdn blog post about this here. Apparently, you may receive this error message for reasons beyond what I experienced above.

SqlCeEngine.Upgrade() causes SqlCeException "The operation completed successfully."


I am building a simple desktop-based command-line analysis tool for a set of .SDF files that were collected on various mobile devices for a research project. Unfortunately, I am having issues connecting to these .SDF files from my tool (each of which are stored locally on my desktop hard drive). The problem seems to be that the version of SQL Compact Edition used on the mobile devices is different from the one I have installed on my desktop.First, when connecting to one of the .SDF files from my desktop analysis tool, I receive the exception:System.Data.SqlServerCe.SqlCeInvalidDatabaseFormatException was unhandledMessage="The database file has been created by an earlier version of SQL Server Compact. Please upgrade using SqlCeEngine.Upgrade() method."Source="SQL Server Compact ADO.NET Data Provider"I now catch this exception and call the recommended SqlCeEngine.Upgrade() method, so my code looks like this:SqlCeConnection sqlConnection = GetConnection(pathToDatabase);try{sqlConnection.Open();}catch (SqlCeInvalidDatabaseFormatException e){Console.WriteLine("The database " + pathToDatabase + " appears to be an old version, running Upgrade()");Stopwatch sw = Stopwatch.StartNew();SqlCeEngine sqlCeEngine = new SqlCeEngine(GetConnectionString(pathToDatabase));string newPathToDatabase = GetUpgradedDatabasePath(pathToDatabase);string newConnectionString = GetUpgradedConnectionString(pathToDatabase, newPathToDatabase);sqlCeEngine.Upgrade(newConnectionString);sw.Stop();Console.WriteLine("Upgraded the database in " + sw.ElapsedMilliseconds / 1000.0f + " secs");sqlConnection = GetConnection(newPathToDatabase);sqlConnection.Open();}The SqlCeEngine.Upgrade() call takes about one minute, afterwards it throws a very confusing exception:System.Data.SqlServerCe.SqlCeException was unhandledMessage="The operation completed successfully."Source="SQL Server Compact ADO.NET Data Provider"Figure 1: One of the most confusing exception messages I've ever received.At first I thought I should just catch this exception and carry on normally (as the exception says that the operation did indeed complete successfully); however, after some experimentation I noticed that the new, upgraded .SDF file built by the Upgrade() command is automatically deleted right before this exception is thrown so there is no upgraded .SDF file to connect to. Thus, it appears that the SqlCeException is valid but that the message is just wrong. I have attempted to use both the SqlCeEngine.Upgrade() call (which upgrades the database in place) and the SqlCeEngine.Upgrade(newConnectionString) call (which makes a new database). Both fail with the same exception.Figure 2: Note how the upgraded database appears in the filesystem momentarily before being automatically deleted just before the Upgrade() method throws an exception.Any help here would be most appreciated. Has anyone else encountered this error? Note, I also posted this to the SQL CE newsgroup here.Update July 6th, 8:04PM: One workaround for this problem is to use the old v3.1 libraries in your desktop program. Thus, rather than use the .NET tab in the "Add Reference" dialog in Visual Studio, you would select "Browse" and then browse to the 3.1 libraries. For me, this is "C:\Program Files\Microsoft SQL Server Compact Edition\v3.1" Thankfully, Microsoft was smart enough to allow both sets of dlls on a machine (e.g., their 3.5 installation did not overwrite the 3.1 installation) as I also have a folder entitled "C:\Program Files\Microsoft SQL Server Compact Edition\v3.5" with the v3.5 libraries.[...]

Storage Card Path Identification


I responded to a thread on Google Groups about the "correct" way to identify the Storage Card path on Windows Mobile devices back in February 2007 (link). According to the Windows Mobile Team Blog, you should use FindFirstFlashCard (link). I've used it successfully on a variety of HTC WM5 SmartPhone devices, however, this issue has recently cropped up as a (potential) issue for one of our MyExperience tool users. The crux of the problem is that you cannot assume \Storage Card\ will be the default path for the storage or flash card on your Windows Mobile device, which is why FindFirstFlashCard is necessary. For example, on the Fujitsu LOOX PocketPC, the storage card path is \SD-MMCard\. The problem seems to be that either some device manufactuers don't properly support the FindFirstFlashCard method or that certain libraries on the device do not use FindFirstFlashCard and improperly assume the storage card is at \Storage Card\. More investigation is needed.

The code I use in MyExperience (actually, the Roam library which MyExperience relies on):

public static String GetFirstFlashCardPath()
Win32FindData win32FindData;
IntPtr intPtr = FindFirstFlashCard(out win32FindData);
String path = win32FindData.cFileName;

if (String.IsNullOrEmpty(path))
throw new ResourceNotFoundException("
Could not find a flash card on this device");

return path;

The full code is available here.

Preview of Windows Mobile 6.1 Standard


There is a nice rundown of the new features in Windows Mobile 6.1 Standard (i.e., the WM flavor with no touch screen) on PocketNow, which includes screenshots and a video. The interface aesthetic is definitely improving but it's still no iPhone. Pocket IE still seems rather sluggish (though its Deepfish like zoom capability is long overdue). Perhaps WM7 will begin to treat the Internet as a fundamental part of the mobile experience (like the iPhone does) rather than an add-on or a way to access mail.


Installing Windows Mobile Device Center on Windows Server 2008


I struggled for about an hour installing Windows Mobile Device Center on Windows Server 2008. Here's so you don't have to:

1. My first real lead was that Windows Mobile Device Center requires Windows Media Player to be installed. Yes, requires. How did I know that? Well, it certainly wasn't from this incredibly vague error message when running the WMDC installer: "The update could not be installed because at least one Windows component required by Windows Mobile Device Center is missing." Fortunately, I found a few links on the web talking about this, mainly this one.
2. So, the key is adding Windows Media Player to Windows Server 2008; however, the download page for Windows Media Player doesn't include releases for Windows Vista much less Windows Server 2008. The key is to turn on the "Desktop Experience" of your Windows Server installation. Instructions on how to do that are here.
3. After reboot, you should be able to successfully install WMDC.

Fixing a Gray ActiveSync


As a Windows Mobile developer, I typically work with multiple WM devices that I continuously plug in and out of our USB ports as I'm testing software. Sometimes, this confuses ActiveSync. For example, say my WM device is plugged into my desktop, ActiveSync is green. All is good. I unplug the phone to test something (e.g., GPS sensor) and walk around. Five minutes later, I stop the GPS software and plug my phone back into my desktop. However, now ActiveSync stays gray. Rather than restarting, which is what I usually do in this situation (though I hate restarting cause I usually have a 100 windows open), I do the following:
  1. Open ActiveSync and Task Manager.
  2. In Task Manager, click on the Applications tab. Select "Microsoft ActiveSync." Select "End Task."
  3. Now click on the Processes tab. Select the "wcescomm.exe" and then press the "End Process" button. Do the same thing for "WCESMgr.exe" if it's there.
  4. Unplug your device from the computer
  5. Go to Start Menu->All Programs and relaunch ActiveSync.
  6. Wait until ActiveSync starts and then plug your phone back in.

SystemState StateChanged Subscription Must Occur on UI Thread?


I posted the following to the .NET CF newsgroup this morning:

The Microsoft.WindowsMobile.Status.SystemState class offers a great way to track a number of interesting and useful device system states (e.g., incoming phone calls, battery strength, etc.). However, recently I observed that the SystemState.Changed += new ChangeEventHandler(OnSystemStateChanged) subscription must be made from the UI thread. Has anyone else run into this? I attempted to write a console app that uses many of these system state notifications; however, none of the events were actually occurring. Once I switched to a form-based application, everything worked great.

Is this documented somewhere? If so, I couldn't find it. I am programming in .NET CF 2 for Windows Mobile 5.0 devices.

Chris Tacke responded with,

Most of those events come from windows messages being posted at a low level (FileSystemWatcher works int he same way too). If you never call Application.Run, no message pump is ever created, so no windows messages are ever dispatched.

I don't think I've ever seen it documented, but if you walk through the aygshell source code in Platform Builder (which a lot of these come from eventually), you'll see that's how they work. I agree that it's a poor choice, but it's how it was implemented. The workaround is a very long, tedious process (again, we've done it for file system notifications) of reimplementing the entire listening system, creating a hidden window for your app or implementing a Run() that doesn't take a Form (like we did in the SDF).

Image Download in .NET CF


Even though it seems more popular to use the WebClient class to download a single image or two, that class is not available on .NET CF. Nonetheless, it's easy enough with WebRequest and WebResponse.

//grab icon
Uri uri = new Uri("valid url to image");
HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream imageStream = httpResponse.GetResponseStream();
Bitmap buddyIcon = new Bitmap(imageStream);

//save icon as jpeg
string iconFilePath = Path.Combine(FullContactsPath, contact.UserId + ".jpg");
buddyIcon.Save(iconFilePath, ImageFormat.Jpeg);

Security Manager for WM5


Though the Device Security Manager PowerToy for Windows Mobile 5.0 has been available since June 6th, 2006, it's such an important application that it deserves mention even a year after its release. For one thing, it allows developers to easily bypass the incessant prompting that occurs every time a binary is changed and loaded on the device. And for two, it allows you as a developer to test different security policies on one device.

The website says:

Device Security Manager helps developers test various security policies for Windows Mobile devices. It is designed as a desktop application that ships w ith a preset list of “security configurations”. A security configuration can be thought of as a template, which contains a collection of individual policies and settings. For example, a security configuration could define policies such as whether unsigned applications are allowed to execute, whether RAPI is disabled etc. Using this tool, the developer can provision a Windows Mobile device with different configurations, and then test the application’s behavior under these configurations. This tool can be used either on an emulator or an unlocked Windows Mobile device.

Force Closing the CameraCaptureDialog


The camera API in .NET CF 2 offers a great improvement over .NET CF 1, which had no common interface to the device's camera (you needed to work with the OEM's directly to obtain a reference to their camera driver information). The CameraCaptureDialog class in .NET CF 2 can be used to capture still photographs or video (with or without audio) in a few lines of code. However, like many of the more "advanced" features in the .NET CF 2 library, not all of the OEMs have correctly implemented the managed camera functionality on their devices. For example, one common complaint on discussion boards is not being able to close the camera after invoking it with the CameraCaptureDialog.ShowDialog() method--CameraCaptureDialog.Dispose() does not work. Thus, on some devices, the camera application stays open sucking up memory and disturbing your window z-order even after calling Dispose().The code below provides a fix to this issue. It relies on a FindWindow P/Invoke to grab the handle to the device's camera application and a DestroyWindow P/Invoke to force it to close. Note that the Cingular 2125 device (which is where I tested this code) always appends [Photo] or [Video] to the camera title (no matter what title you set yourself). Thus, I have a function called GetCameraCaptureDialogTitle that appends that right suffix depending on the capture mode (e.g., video or photo).//Open the camera capture dialogCameraCaptureDialog cameraCaptureDialog = new CameraCaptureDialog();string windowTitle = GetCameraCaptureDialogTitle(cameraCaptureDialog);DialogResult dr = cameraCaptureDialog.ShowDialog();if (dr == DialogResult.OK){ string capturedFileName = cameraCaptureDialog.FileName; //do stuff with file!}cameraCaptureDialog.Dispose();//sometimes the camera capture dialog does not close automatically//we look for the window title and force close it ourselvesIntPtr ptr = WindowUtils.FindWindow(windowTitle);Debug.WriteLine(string.Format("Found window '{0}' with ptr={1} ", windowTitle, ptr));if (ptr != IntPtr.Zero){ //force the camera closed WindowUtils.DestroyWindow(ptr);}Here are the helper functions:private string GetCameraCaptureDialogTitle(CameraCaptureDialog dlg){ if (dlg.Mode == CameraCaptureMode.Still) { return string.Format("{0} [{1}]", dlg.Title, "Photo"); } else { return string.Format("{0} [{1}]", dlg.Title, "Video"); }}[DllImport("coredll.dll", SetLastError = true)]public static extern IntPtr DestroyWindow(IntPtr hWnd);[DllImport("coredll.dll", SetLastError = true)]public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);public static IntPtr FindWindow(string windowTitle){ return FindWindow(null, windowTitle);}Please e-mail me or post a comment if you have any questions. Also, I use this trick in the MyExperience tool--the source for which can be found here and is open sourced under the BSD license.Finally, moving beyond CameraCaptureDialog, it would be nice if .NET CF provided events for when a new image or video is captured on the device (e.g., a NewMediaCapturedEvent would be cool to have at the SystemState level if not in the CameraCaptureDialog as well). Furthermore, .NET CF 2 does not allow you to take images/video automatically without user intervention. This feature might be useful for taking timer-based pictures (e.g., for those times when you want to take a self/group portrait but have no one around to take the picture for you). Marcus Perryman has C++ code that turns a Windows Mobile device into a wireless webcam using using DirectShow (see this post). It would be cool to have this fully fleshed out in managed code.[...]

WM5 Maximum Storage Card Capacity


Most of the Windows Mobile 5 devices that I've used including the T-Mobile MDA, SDA, and Cingular 2125 use miniSD flash storage. The Samsung Blackjack, however, uses microSD. With ever-increasing storage capacities available in these formats, I was curious if there was an upper capacity bound on WM5 devices. It looks like the internets are mixed on this one.

This post by Mike Calligaro on the Windows Mobile blog points out that most cards and card readers available (at least on Jan 1st, 2007) follow the SD Spec 1.1, which maxes out at 2 gigabytes. Here's an excerpt,

"Up to 2G, the only negative to larger storage cards is that they cost more. They don't burn any more power than smaller ones and they're not inherently any slower than smaller ones. I've used 2G cards in my Windows Mobile devices, and they work fine. Unfortunately, 4G and larger cards aren't likely to work yet.

Most cards and card readers out there follow the 1.1 version of the SD specification. That spec maxed out with 2G cards. There's a new 2.0 version of the spec that allows for larger cards, but Windows Mobile currently doesn't support SD 2.0. Even though we don't explicitly support SD 2.0, it's possible for our OEMs to add support themselves (I don't know if any have). So if you've got a Windows Mobile device that's able to read 4G SD cards, you don't have to call me a liar. Ignorant, yes. Liar, no."

Riki commented on this blog entry, however, and said:

"The maximum capacity of SD card is 2GB under SD 1.1 of SD spec; however, by using FAT32, many SD 1.1 host devices can use 4GB SD cards. SD 1.0/1.1 uses traditional “Byte Addressing” scheme which limits the maximum capacity to 4GB while SD 2.0 adopts “Sector Addressing” scheme."

So it looks like when purchasing new SD memory for a WM5 device, you should go with 2 gigabyte cards--those are guaranteed to work. However, some devices may support 4 gigabytes and up, especially if the OEM implemented the SD 2.0 Spec.

On a related note, my advisor found two programs that turn a WM5 device into a USB SD reader. I haven't used either of these, so I cannot comment on them:

Configuring the GPS Intermediate Driver


I recently purchased the QSTARZ Bluetooth GPS Receiver Model BT-Q818 to play around with some location-aware research ideas I've had. First, the GPS receiver worked out-of-the-box after following the configuration instructions in the directions (or see this post on the Windows Mobile team blog). I tested it both on my Cingular 2125 SmartPhone and Cingular 8125 Pocket PC Phone. Second, it works amazingly well with the new Windows Live Search--I can get smooth map scrolling, hybrid maps, and real time traffic overlays on my phone automatically centered on my current location. To configure Windows Live on WM to use GPS, open Live Search->Menu->Settings and then set the GPS COM port (in my case, COM6). Then, open Map and make sure that Menu->Center on GPS is checked.I was anxious to start my own hacking. I knew that Windows Mobile 5 shipped with the GPS Intermediate Driver framework, unfortunately I did not realize that this is an unmanaged API. However, both the Windows Mobile 5 SDK and the Windows MObile 6 SDK ship with sample code that provides a managed wrapper around that native GPS API. On my computer, these two samples can be found in:C:\Program Files\Windows Mobile 6 SDK\Samples\Smartphone\CS\GPSC:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Samples\Cs\GpsUnfortunately, neither of these samples worked for me immediately. I don't have a WM6 device, so I'll focus on the WM5 sample. The sample includes the Microsoft.WindowsMobile.Samples.Location GPS wrapper API and a small test app called GpsSample. To get the sample to work, you must configure the GPS Intermediate Driver, which requires either editing the registry or, alternatively, running the "GPS Intermediate Driver Control Panel." See Configuring the GPS Intermediate Driver on msdn. Well, where can I find this control panel? As the msdn link points out, many OEMs hide the application icon. On my Cingular 8125 Pocket PC Phone, this was certainly the case. Here's what I did to unhide it:On the desktop, open Start->All Programs->Microsoft Visual Studio 2005->Visual Studio Remote Tools->Remote Registry EditorConnect to your Windows Mobile device in the Remote Registry EditorFind the path: HKEY_LOCAL_MACHINE\ControlPanel\GPS SettingsDelete any "Redirect" or "Hide" keys under HKEY_LOCAL_MACHINE\ControlPanel\GPS Settings.Then, on my Pocket PC device, I opened Settings->System and there was a GPS icon. Click on that icon and choose an unused COM port. This is the COM port that your GPS applications are going to communicate through--the GPS intermediate driver talks to the hardware directly and serves as a virtual device sending data out this COM port. I selected COM0. Then select the Hardware tab and choose the GPS hardware port. On my device, I setup GPS to communicate via COM6 (at the highest baud rate possible). Then on the third and final tab ("Access"), make sure that Manage GPS Automatically is selected. After doing this, I reran the WM5 managed GPS sample and it worked great :)Successfully configured GPS Intermediate Driver on Pocket PC PhoneWell, what if you have a SmartPhone? According to Jason Fuller on the Windows Mobile Team blog, the SmartPhone does not have the GPS Intermediate Driver Control Panel (see his post here). You can, however, manually configure the GPS Driver by modifying the registry. Again, using the Remote Registry Editor found in the Visual Studio Remote Tools directory:[HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver] "IsEnabled"=dword:00000001[HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers]"CurrentDriver"="BT GPS" [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\BT GPS]"CommPort"="COMX:" where X = the hardware COM p[...]

Wallpaper, Screenshots, and Application Switching


To get around some of the Today Screen API limitations (see this post for a Today Screen rant), I've played around quite a bit with programatically switching the wallpaper on a WM device. However, there a number of problems with this approach, most significantly: changing the device wallpaper is slow and once the device has been signaled that the wallpaper has been updated, it does not actually redraw the wallpaper until the desktop is visible (e.g., the desktop is the top level window). For more about this issue, see my .NET CF newsgroup post. Nonetheless, changing the device wallpaper is one of the easiest ways to display ambient information.A project at Intel Research required that a screenshot be taken of a specified application, cropped, and displayed as the wallpaper on the device. However, as mentioned above, setting the wallpaper on a user's device can be an intrusive operation--not only can it take between 10-30 seconds but the wallpaper update does not actually happen until all applications are minimized making the desktop visible.I created a little test application which fulfills our requirements and attempts to avoid disrupting the user by waiting to execute until the device is idle. Here's how it works:Waits for device idleFinds handle to specified application (based on its window title)Switches from current app to specified application (saving current foreground window handle)Takes screenshotCrops screenshot (if necessary)Sets background wallpaper to screenshotMinimizes all open applications so phone background refreshesAfter background refresh, restores state of open applicationsReturns to saved foreground window handlePuts device back to sleepYes, it's hacky but I could think of no better way to do this. Note that in this case it was not possible to create a Today Screen plug-in.Download the source code and the binary. You should be able to compile and deploy as long as you have the Smart Device Framework 2.0 from the OpenNETCF team installed. This sample will probably work with the SDF 2.1 as well but I haven't tested it. Alternatively, you can download the binary zip file and add those .dll references to the source code project. I've also added this sample code to the samples directory in Roam (see SourceForge). Roam is a Windows Mobile open source library which provides functionality like a SQL connection pool, power management functions, and a whole slew of UI code.Note: this code has been tested on the Cingular 2125 and the T-Mobile SDA device. In addition, I also ran it on the Cingular 8125 Pocket PC Phone and everything worked except for the wallpaper changing code--this is because Roam's wallpaper changer methods only work on the SmartPhone.[...]

Programming the Today Screen, A Rant


I find the Today Screen APIs (and lack thereof) to be one of the great failures in the design of the Windows Mobile framework. Many times in my mobile computing research, I have looked enviously at the Today Screen as prime real estate for ambient display of information and novel interactions. From an HCI perspective, it should be one of the most configurable components on the WM platform--it is, after all, a part of the display that the user glances at nearly every time they open/use their phone be it to check the time or simply to make a phone call. That is why, of course, Microsoft themselves include Today Screen plug-ins for calender information, text messages, emails. Microsoft has also recently recognized the value of ambient information on the desktop--Vista now ships with the Gadget Bar, which displays information about stocks, weather, email, traffic, etc. in an ambient manner.

This same functionality should be available on WM. Unfortunately, not only are these plug-ins difficult to develop for Windows Mobile (e.g., they hook into a rather archaic Windows messaging scheme, cannot be C#/VB, and cannot easily be animated) they also require that the user modify their Today Screen settings by selecting a new configuration XML file. This latter point sounds harmless; however, it requires some effort to allow the user to maintain their current Today Screen look and feel with the addition of the new plug-in (even if this plug-in is a one line text output). They must copy over the XML into each of their existing Today Screen profiles--otherwise the plug-in will not be visible. I've seen some developers simply ship their plug-in with a fresh Today Screen XML file that is meant to overwrite the user's existing profile; however, unless the XML file has the exact same plug-ins specified, the user may miss out on a plugin they've previously installed (or a layout they've established via Settings->Home Screen->Home screen layout).

Note: I speak only out of my own personal experience and watching others in my lab attempt to play around with Today Screen functionality. Though I haven't used WM6, it does not appear that this functionality has been improved with that release--perhaps WM7?

Measuring Time on .NET CF 2


If you develop code on both the desktop with the full .NET and on the mobile platform with .NET CF, you have to be careful with the behavioral differences of some classes. DateTime is one such class. On the desktop, DateTime.Now is capable of 10 millisecond resolution (at least on WinXP and Vista). On the mobile platform, however, DateTime.Now only has a resolution of 1 second. Quite the difference if you're using DateTime.Now as an easy way to timestamp data. Note that this also includes the DateTime.Now.Ticks, which on the desktop is measured in 100-nanosecond units but is only at the 1-second level in Windows Mobile. So, what are the alternatives?The most straightforward method may be Environment.TickCount (which is different from DateTime.Ticks). Environment.TickCount represents a 32-bit signed integer containing the amount of time in milliseconds that has pass since the last time the computer was started. The problem with TickCount, however, is that it is only a 32 bit value. Therefore, if the system runs continuously (e.g., no restarting) for 24.9 days the TickCount value will reach int.MaxValue and then wrap to int.MinValue, which is a negative value. Then, for the next 24.9 days, Environment.TickCount will increment from int.MinValue to 0 and start the cycle all over again.Alternatively, you can P/Invoke QueryPerformanceCounter and QueryPerformanceFrequency. The QueryPerformanceCounter function retrieves the current value of the high-resolution performance counter, if one exists, on the computer. The QueryPerformanceFrequency function retrieves the frequency of the high-performance counter, if it exists. The frequency cannot change while the system is running. The frequency is also platform dependent. I'm not sure if any mobile device ships with a performance counter that offers higher resolution than Environment.TickCount but it is worth experimenting with. Here's what MSDN has to say about "high resolution timers"If a high-resolution performance counter exists on the system, you can use the QueryPerformanceFrequency function to express the frequency, in counts per second. The value of the count is processor dependent. On some processors, for example, the count might be the cycle rate of the processor clock. The QueryPerformanceCounter function retrieves the current value of the high-resolution performance counter. By calling this function at the beginning and end of a section of code, an application essentially uses the counter as a high-resolution timer. For example, suppose that QueryPerformanceFrequency indicates that the frequency of the high-resolution performance counter is 50,000 counts per second. If the application calls QueryPerformanceCounter immediately before and immediately after the section of code to be timed, the counter values might be 1500 counts and 3500 counts, respectively. These values would indicate that .04 seconds (2000 counts) elapsed while the code executedHere's the code to use the QueryPerformanceCounter in .NET CF 2 on Windows Mobile.public static class PerformanceUtils{[DllImport("coredll.dll", EntryPoint = "QueryPerformanceCounter")]private static extern bool QueryPerformanceCounter(out long count);[DllImport("coredll.dll", EntryPoint = "QueryPerformanceFrequency")]private static extern bool QueryPerformanceFrequency(out long countsPerSecond);//these two variables are initialized in the PerformanceUtils static constructorpublic static readonly long Frequency;public static readonly long FrequencyInMs;static PerformanceUtils(){if (QueryPerformanceFrequency(out Frequency) == false){ throw new Exception("The high resolution timer is not available on this device.");}FrequencyInM[...]

Announcing Roam


Roam is a .NET CF 2 open source library for Windows Mobile devices that I've been developing off and on for the past year or so. A majority of the development has been driven off my own needs as a SmartPhone developer and HCI researcher. Although the source code is hosted on SourceForge and released under the BSD license (link), I have not had a chance to write a webpage or formal documentation. Thus, I've held off on advertising it on newsgroups/forums. I thought I would mention it here because I believe the source code could be of some use to my readers. Note that Roam requires OpenNETCF's Smart Device Framework (SDF 2.0) library. They just recently released SDF 2.1, I'm not sure if Roam is compatible or not...Currently, the Roam library is broken down into four namespaces: Roam, Roam.Common, Roam.SqlCe, and Roam.UI. Each of these namespaces are compiled into their own assembly to save space.Roam: contains media related functionality (e.g., sound player, camera media sniffer), pocket outlook related code (e.g., semi-robust SMS sending system), and low level device related utility classes (e.g., power notifications, storage card utilities, device id)Roam.Common: contains code that is not-specific to Windows Mobile (i.e., this .dll also runs on the desktop). The largest subnamespace in this library is the Collections classes which include a HashSet, a Tree, a PriorityQueue, and a ReadOnlyHashtable among other things.Roam.SqlCe: contains code relevant to SQL Server Mobile / Compact Edition. Currently, only two classes exist: SqlCeConnectionManager which offers thread safe connection pooling using a singleton paradigm and SqlCeWrapper which also offers thread safe access to the database by wrapping the SqlCeConnection object.Roam.UI: this is the largest assembly in the Roam project. It contains many of the UI controls I've needed over the past year and were not included in .NET CF (e.g., scrollable label) I've developed a fairly simple drawing architecture that many of my custom UI classes use. Currently, Roam.UI contains custom controls for image buttons, radio list boxes, check box lists, key filtered lists, numeric text boxes and scrollable labels. In addition, Roam.UI features a set of utility classes that wrap P/Invoke calls to draw rounded rectangles, change the device's wallpaper, etc.Below are two brief demos of Roam.UI custom controls: the TextBoxFilteredList and the ScrollableLabel. Note that the embedded videos below are hosted on YouTube which changes the aspect ratio and overall quality. :( The original source videos can be found here and here.[...]

Deprecated Features In Windows Mobile 6


Channel9 Wiki has a list of deprecated API features in WM 6 that should no longer be used.


Windows Mobile Platform Growth


A Microsoft developer posted about why he loves to work on Windows Mobile on the Windows Mobile Team Blog. In it he details the massive growth the Windows Mobile platform has experienced in the past few years:

I’ve talked a lot about not understanding marketers. It’s even harder to understand accountants (even though I’m married to one…). For some reason, our accountants think that the “year” starts in July and ends in June. Well, in the first half of this “year” (in the accounting sense), we sold over five million phone units. Last “year” we sold 150% more units than the year before. And in that year we sold 150% more units than the one before it. Weird accounting speak aside, we’ve been growing at 150% for a couple of years now. That’s easy to do if you’re small. But we’re not small. Exciting times.


SMS Toolkit


A colleague pointed me to MSR India's SMS Toolkit. I haven't had a chance to check it out but it looks very cool.

The Indexer Name


Any guesses why the following class won't compile? public class SuperSimpleIndexerClass{__public double this[int index]__{____get { return 0; }__}__public double Item__{ ____get { return 0; }__}}It has to do with the way indexers are internally represented in C#. By default, indexers have the name "Item." Thus, the indexer property and the explicit Item property will have a naming collision. We can fix this problem by providing the following attribute. public class SuperSimpleIndexerClass{__[System.Runtime.CompilerServices.IndexerName("TheItem")]__public double this[int index]__{____get { return 0; }__}__public double Item__{ ____get { return 0; }__}}Now, this indexer will have the name TheItem.[...]

Windows Mobile 6 != Windows CE 6


Microsoft is once again attempting to clarify the difference between Windows Mobile and Windows CE. Sue Loh on the Windows CE Base Team blog states:

Windows Mobile 6 does NOT run the CE 6 OS.
Technically the OS version # in WM6 is 5.02; it's an advancement of the OS (5.01) that was in WM5. Certain CE6 OS features have been ported to WM6. But the kernel VM architecture we've been discussing here does NOT apply to Windows Mobile 6.


Oh No, Not Again, ActiveSync


My ActiveSync posts (e.g., ActiveSync Sit & Spin) are the most visited blog entries on this site by nearly an order of magnitude. It's clear that many others have encountered the same problems as I. ActiveSync 4.5 beta, however, was working very well for me--in fact, flawlessly. So, perhaps I should not have been so eager to upgrade to the full release. Now, my current problem could be completely coincidental with my upgrade--I'd been running 4.5 for two straight days without experiencing a any problems. However, yesterday I plugged in my Cingular 2125 WM5 SmartPhone and a dialog box popped up that read "The software you are installing for this hardware: SmartPhone USB Sync has not passed Windows Logo testing to verify its compatibility with Windows XP." (see Figure 1 below)Figure 1: Windows Logo Testing DialogIf you click "STOP Installation" the SmartPhone device will not be recognized by your computer; thus, you must press "Continue Anyway." In my two years of SmartPhone development, I have never seen this dialog (not sure if it is related to ActiveSync 4.5 or not). After selecting "Continue Anyway," ActiveSync opened and properly synchronized my SmartPhone. However, after unplugging the phone and plugging it in again, I received another dialog box--this one was a bit more alarming: "One of the USB devices attached to this computer has malfunctioned, and Windows does not recognize it." (see Figure 2 below)Figure 2: USB Device Not RecognizedAfter this point, no amount of restarting (either my computer or device) would fix this issue. I'm not sure if Figure 2 is related to Figure 1 at all, but it seems likely. Interestingly, my other WM5 device (a Pocket PC Phone) still synchronized fine.I was able to fix the problem by:Unplugging device from computerUninstalling ActiveSync 4.5Restarting ComputerReinstalling Activesync 4.5Plugging device back inUnfortunately, it only took me about three hours to get this right. Troubleshooting included a hard reset on my SmartPhone, thus losing all of my installed programs of which there are many. I don't believe the problem is on the device side, however, so a hard reset is probably not required (in fact, after my hard reset, plugging in my device would still cause the Figure 2 dialog to pop up).[...]

ActiveSync 4.5 Released


You can download ActiveSync 4.5 here. The readme.doc includes an overview of new features, a select few are below.
  • Feature: A device can stay connected to cellular and wireless networks while also connected to PC.
    • Benefit: Enables the device to receive incoming VoIP calls and MMS messages when it is connected to a PC.
  • Feature: An integrated troubleshooter utility is included.
    • Benefit: The utility scans your PC and device to identify problems that can affect the use of your device with the PC.
  • Feature: Overall stability has been improved.
    • Benefit: Enhances the reliability of connecting devices and syncing.
  • Feature: USB support has been improved.
    • Benefit: ActiveSync 4.5 provides the fastest USB transport between your PC and your mobile device to date.
There's also a plethora of exchange related features, but I don't use those so I'm not sure how useful they are.

What's New in Windows Mobile 6


Jim Wilson has posted an article "What's New for Developers in Windows Mobile 6" on msdn (link). Note that the difference between WM 5 and WM 6 is much less substantial than the difference between WM 2003 (WM4) and WM5. This is, in part, more due to the transition between .NET CF 1 and .NET CF 2 imo. Nonetheless, Here is a quick summary of the new WM 6 features I'm most interested in:

Update 02-15-2007: According to this post on the Windows Mobile Team Blog, the Windows Mobile 6 SDK won't be out until March 1st with a "refreshed" version on May 1st.