Thursday, August 14, 2008
If you're using the sample code from Alex Feinman's MSDN article on hosting ActiveX controls, then you might be interested to know that we've found and fixed a bug in it.  The original code doesn't properly clean up and destroy the native control instances, so the native destructor is never called and you leak objects.  For many things like Media Player, where you create one control and use it for the life of your app it's not much of a problem, but if you're creating and disposing a lot of controls in your app, it is a problem.

The fixed file is available here [AxHost.zip (7.89 KB)]
8/14/2008 10:40:38 AM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Wednesday, August 13, 2008
Today I saw two separate posts on pretty much teh same question.  How can you determine if the foreground window changes in a WinMo application?  Moreover, how can you determine if the new foreground window is your own, or in some other process?  My initial thoughts were to do some work in the Form's Deactivate event, but that would lead to having to plumb it into every Form, and then you'd still need special case handlers for MessageBoxes and Dialogs and it would be an unmaintainable pain in the ass. I decided to put some time aside this afternoon and see if I could come up with a better solution, and what I came up with is outlined in a new article entitled 'Determining Form and Process Changes in Windows CE'.

8/13/2008 6:14:58 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Tuesday, August 12, 2008
We've been getting a lot of inquiries lately about our plans for releasing the SDF built for Visual Studio 2008 and against CF 3.5, so I'll lay out our current status and short-term plan.

I realize we're a bit late in releasing a version for Studio '08.  Now you might say to yourself "how hard can it be?  Just open the solution in Studio '08, let it upgrade, recompile and release."  Sure, it could be that simple if we wer content with just tossing it out there, but we're not.  With the move to Studio '08 we decided to take advantage of some of the new tools we have.  First we migrated the entire SDF source tree from Vault to TFS.  Vault worked just fine, but we wanted to take advantage of TFS and integrate both continuous integration, automated testing and test-driven development into the product. 

That mean rearchitecting the solution and projecy layouts and then writing tests.  Lots of tests.  Of course writing tests leads to finding bugs, which then leads to fixing bugs.  We started by looking at reported bugs but also looking at some use cases and testing classes we know get the most use.  We have no delusion that we're going to have even close to full code coverage (or even 50%) by our next release, but we want to get off on the right foot and at least have some coverage for the next release.

Of course we've also added some new features like the OpenNETCF.Net.Mail namespace and all of this takes time.  As of right now we have less than 40 hours of test writing left to hit our release milestone.  Once we hit that, we then have to build the Help and installation package and release.  My hope is to have something ready in early September, but that's not a guarantee.  We know you want the release - we do - we just want to make sure it's right.

An ancillary question that also comes up is "when will we be releasing a version compiled for CF 3.5?"  As of right now we have no plans to release a CF 3.5-targeted version of the SDF.  Yes, you read that right.  We have no plan for a CF 3.5 release.  "Why is that?" you might ask, after all CF 3.5 is the latest and greatest, right?  Sure, it is, and we think that when possible you should use it.  However the SDF has historically been used by developers using older versions of the CF and is already rolled out in a *lot* of CF 2.0 projects.  If we moved to 3.5, none of those 2.0 project would be able to use the SDF without recompiling themselves.  If we moved to 3.5, then we'd also be tempted to use 3.5 features, which would then even make the source incompatible with 2.0 and a recompile wouldn't even be an option. I, for one, don't really want to leave all of those CF 2.0 developer's high and dry. 

Since CF 3.5 assemblies are unusable in CF 2.0 projects, but CF 2.0 assemblies can be used without a problem in CF 3.5 applications it makes the decision pretty simple.  If we stay with CF 2.0 as a target, then far more people can use the library.  If you absolutely must have it built targeting CF 3.5, you can always recompile the source yourself.

8/12/2008 12:03:11 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Thursday, August 07, 2008
    Microsoft has released SQL Server Compact 3.5 SP1, providing support for the ADO.NET Entity Framework and 64-bit desktops.

8/7/2008 9:40:05 AM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Friday, August 01, 2008
It seems that every time I work on a project I get near the end and have to deal with actual deployment of the application and things go south.  Let's face it, Microsoft's wceload application sucks - and that's being generous. It's limited, it's got no object model, and it's behavior has changed over time without any of those changes being documented.

In a recent project I was trying to silently install an application to a directory that would change depending on the target hardware becasue different devices have their storage media named differently.  I wanted to do this without changing or having multiple CAB files, since the application was no different. Achieving this with wceload, I am convinced, is utterly impossible so I put on my reverse-engineering hat, downloaded the CAB spec (cabfmt.doc), and went to work.  Now, a few month later, and with the help of Alex Feinman, we've created a new product called the Windows CE CAB Installer SDK.  In addition to a new product, we went with a new pricing model as well.

The SDK comes with full source,  unit and integration tests designed for running under mstest, samples for generating compressed and uncompressed CAB (the SDK supports both), a template for creating custom installer DLLs and both VB and C# examples of using the SDK.

The main workhorse of the SDK is the WinCEInstallerFIle class, which looks like this:



An example of a custom installer looks like this (just to give you a flavor of how it works):

using System;

using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using OpenNETCF.Compression.CAB;

namespace System.Runtime.CompilerServices
{
public class ExtensionAttribute : Attribute
{
}
}

namespace ONCFInstall
{
public delegate void FileProgressHandler(int progressPercent);

public static class Extensions
{
public static string Find(this List list, string findString)
{
foreach (string file in list)
{
if (string.Compare(file, findString, true) == 0)
{
return file;
}
}
return null;
}
}

public class CustomCABInstaller : WinCEInstallerFile
{
private int m_fileCount = 0;
private CommandLineArgs m_args;

public event FileProgressHandler FileProgress;

public CustomCABInstaller(string cabFileName, CommandLineArgs args)
: base(cabFileName)
{
m_args = args;
SkipFileNames = m_args.SkipFiles ?? new List();
PathStringReplacements = m_args.PathStringReplacements ?? new Dictionary();
SkipOSVersionCheck = m_args.SkipOSVersionCheck;
}

/// /// List of file names to skip during installation /// public List SkipFileNames { get; set; }

/// /// List of path replacement strings /// public Dictionary PathStringReplacements { get; set; }

/// /// If true, the installer will not check to ensure the target meets the installer's version requirements
///
public bool SkipOSVersionCheck { get; set; } public override void OnInstallBegin() { m_fileCount = 0; } public override void OnTargetOSVersionCheck() { // check to see if we should skip the OS version check if (!SkipOSVersionCheck) { base.OnTargetOSVersionCheck(); } } public override void OnInstallFile(ref FileInstallInfo fileInfo, out bool skipped) { // check to see if it's a name we should skip if (SkipFileNames.Find(fileInfo.FileName) != null) { Utility.Output(string.Format("Skipping file '{0}'", fileInfo.FileName)); skipped = true; return; } // do any path replacements foreach (KeyValuePair val in PathStringReplacements)
{
fileInfo.DestinationFolder = fileInfo.DestinationFolder.Replace(val.Key, val.Value);
}

Utility.Output(string.Format("Installing '{0}' to '{1}'", fileInfo.FileName, fileInfo.DestinationFolder));

base.OnInstallFile(ref fileInfo, out skipped);

if (FileProgress != null)
{
FileProgress((++m_fileCount * 100) / FileCount);
}
}
}
}

8/1/2008 3:42:52 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
Today OpenNETCF announces a new pricing model that is going to be somewhat of a social experiment.  Our latest product - the Windows CE CAB Installer SDK - is being released under a "value-based" pricing (VBP) model.  In this model we're letting the customer determine how much they pay for a product based on how much value they feel it provides them.

The general idea is that we believe that most developers are honest, understand the value of time and have varying perceptions on the value of a software package.  For example a college student writing some quick utility for her personal use might find that the product saved a little time, but that she doesn't have a whole lot of expendable cash.  To her, $10 may be a reasonable representation of the value that our product brought to the solution.  On the other hand a developer working on an enterprise solution might find that the product saved his team several days of internal development and testing.  He knows the cost of his developers' time and the opportunity cost of letting them work on other product features instead of implementing what our product does.  For him $1,000 is a reasonable value.

In both cases we agree.  Software certainly doesn't always hold the same value to everyone.  We've all purchased software that we use a lot, and we feel that it was a great deal for what we paid for it.  We've all also bought software that maybe got used once or twice and that we know wasn't worth what we paid for it. Since the only person that can reasonably determine the value of the software is the customer themself, we've decided to let them pay based on their perceived value of the software.  Instead of purchasing the product, or some quantity of the product, customers will instead purchase a quantity of $5 "value units."  The number of units they purchase is completely up to them.

So now the college student can pay $10 for the exact same software that some company might pay $1,000 or more for.  If you're unsure if the software will meet your needs you can pay a small amount to give it a try - after all there is value in the effort alone.  If you determine that it does solve a problem for you and indeed does have value, you can always come back and purchase more value units.  What about bug fixes and upgrades?  New features and fixes are added value, so simply come back and purchase the number of value units that you feel represent the feature or fix.

Sure, I suspect that there will be a few people who take advantage of the model.  People who know that it saved them days of work but decide to pay in only $5.  The hope, however, is that those people will be the exception.  Software is never complete - there are always more features to add and bugs to fix.  What drives our ability to add those features and make those fixes is cash flow. We feel that if most people pay what they truly feel is the value of the product, then it will provide us enough revenue to continue working on it, and if the model works for this product, it may well spread and be applied to some of our other products as well.

8/1/2008 3:00:38 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Wednesday, June 04, 2008

We've been working for a couple months now at migrating some of our projects from our older SourceGear Vault source code repository to Microsoft's Team Foundation Server.  I've been perfectly happy with Vault - it's a great, inexpensive code repository - but we wanted to start doing test driven design and adding continuous integration into the mix.  One would think that since that's what TFS is all about that this would be pretty simple, right?  Hardly.

TFS may work out of the box for desktop developers, but when it comes to doing device work you quickly end up in a tar pit of problems, which is only compounded when you're new to TFS to begin with.  In my opinion a root of these problems is that the Visual Studio IDE is not using msbuild.exe and mstest.exe for doing device project builds and tests.  This is evidenced by the fact that you can create a device project with unit tests and they all run just happily from the IDE, but if you open a command windows and use msbuild with your solution it fails miserably.

I consider this a major failure on the part of the Visual Studio for Devices (VSD) team.  You see TFS doesn't launch Studio to build your solution, it uses msbuild.  So to just get the solution to compile you have to learn how TFS works and make modifications.  Oh, and once it's compiling that certainly doesn't mean that unit tests will actually run.  We've hit several snags along the way on that too.

Fortunately for us, I have a good friend and long-time colleague, Tim Bassett, who is big into CI and TDD, has a lot of experience with TFS and is considering hanging out his own shingle. He just has no experience doing device development (well not really any since the days of eVB when we worked together).  So we formed a kind of symbiotic relationship with him helping us getting our server working and running and us helping him develop some products that will benefit any other hapless suckers who think that maybe automating builds and testing for device development might be useful.  If you're in that boat, take a look at what he's got. Ask him questions.  Help him help us improve the experience of using TFS for device work. And if you ever have the ear of anyone on the VSD or CF team, tell them they should be dogfooding this stuff so they can feel our pain and that yes, unit tests for native code *is* necessary.

 

6/4/2008 11:36:47 AM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Tuesday, June 03, 2008

For some time now we've offered "support and maintenance" as an option when purchasing our flagship Smart Device Framework product.  If I recall correctly, the price is something like $240 for a year.  In the entire time we've offered it I can probably count the number of sales of that option on one hand - it's way less than 1% of the people who bought the extensions.

I had a call from a prospective customer asking about the feature and it clued me in to what most people's thought process is.  He asked "why should I buy maintenance for $240 when I can just buy each new version for $50.  It's less expensive to just re-buy."

Ah, on the surface that may seem true, and like a good deal.  But here's the value in buying maintenance:

Right now we're in the process of moving the SDF to Studio 2008.  In the process we're also moving to using Team Foundation Server as a back end and integrating unit testing and continuious integration.  In this process we're shaking out quite a few bugs (take a look at our online bug database to see what we're up to).  People with maintenance agreements can request the source for these fixes at any time.  They also get source drops for all service packs (no one else does).  Those without maintenance must wait until the next release or service pack to take advantage of these fixes.

There is one exception to this rule.  We feel that if you've gone through the task of finding it and reporting it, we owe you so if you are the first to find and report a bug, we'll provide you the fix immediately upon fixing it. 

6/3/2008 12:48:33 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [2]  | 
 Thursday, May 29, 2008

We're just about to release a new version of Padarn, out ASP.NET Web Server for Windows CE.  This version brings SSL support as well as Basic and Digest authentication.  Another part of this release was trying to keep the footprint reasonably small.  Here's a screen shot of all of the assemblies needed for the entire engine implementation:

padarnfootprint.PNG

So yes, we have an ASP.NET web server with SSL and authentication support and it's just 305KB - and half of that is for SSL alone.

 

5/29/2008 12:26:56 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Wednesday, May 28, 2008

Since the Compact Framework doesn't have support for App.Config file, we created our own implementation that follows the full framework model.  It requires that the config file be named “MyApp.exe.config” (which is how it works on the desktop) with a subset of the desktop functionality and it's worked well for some time.  Until recently that is.

Yesterday I set out to create some unit tests for some of our OpenNETCF.Rss namespace objects.  Well the FeedEngine object requires information from an app.config file on construction, so I figured it would be simple - I'd just add an app.config file to the test project and mark it as a DeploymentItem.  After a little investigation I found that the calling assembly for a device unit test is SmartDeviceTestHost.exe, which by default runs out of \Program Files\SmartDeviceTest on the target device.  That means that to use your own app config file from a unit test it would need to be named SmartDeviceTestHost.exe.config. 

Interestingly (or frustratingly, depending on when you asked me yesterday), this test host deploys *its own* version of a config file with the same name with some info on what framework it’s running against.  The test framework just heavy-handedly overwrites any existing file rather than merging its contents into the existing one, and it overwrites *after* it deploys all of the test pieces, so you can’t just merge its contents into your own app config and use it.

As a workaround I actually modified the OpenNETCF implementation for app config files.  I didn't really want to, but the only other solution I could think of was to write code that would open the MS-deployed version and do a manual merge in the unit  test code before the test is run, and that seemed like a much uglier route. The OpenNETCF Configuration implementation now looks for a file named MyApp.exe.config.unittest before looking for MyApp.exe.config and uses the "unittest"-suffixed version if it’s there.  I then modified my TestBase class (from which all of my unit tests derive) to add this:

 

 

        [TestInitialize]

        public virtual void TestInitialize()

        {

            CopyTestConfigFile();

        }

 

        private void CopyTestConfigFile()

        {

            // copy the config file to the test host folder

            string src = Path.Combine(TestContext.TestDeploymentDir, "SmartDeviceTestHost.exe.config");

            string dest = Path.Combine(TestHostFolder, "SmartDeviceTestHost.exe.config.unittest");

            if ((File.Exists(src)) && (!File.Exists(dest)))

            {

                File.Copy(src, dest);

            }

        }

 

        public string TestHostFolder

        {

            get

            {

                return  Path.GetDirectoryName(

                        Path.GetDirectoryName(

                        Path.GetDirectoryName(

                        Assembly.GetCallingAssembly().GetName().CodeBase)));

            }

        }

 

Now I simply add SmartDeviceTestHost.exe.config to the unit test project, mark it as a deployment item and voila - it works as expected.  Just how it should have yesterday morning when I set out to write a couple simple tests.

And for the record - the current "solution" for debugging device unit tests (which involves putting in a Debugger.Break() call in the unit test and then doing an "attach to process" from another instance of Studio) is an unweildy pain in the ass.  It takes no less than a minute just te get a unit test running and in a state that you can step through code.  That might not sound like a lot, but try this: put a breakpoint in your code and when the debugger hit is, wait a full minute before you step or look at the Locals window.  Now do this every time you want to debug.

 

5/28/2008 12:46:42 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [2]  | 
 Tuesday, May 27, 2008

I don't use LINQ terribly often because it seems that most of the work I do is pre-CF 3.5.  It only creeps into my code in things like unit tests or test projects. 

This weekend I spent a little time updating my AudioTagR project and adding some tools and utilities to it.  One of the challenges I faced was let's assume I have two root directories that contain music files (they really can be any file, but this is a real-world example, so we'll use the exact scenario I had).  In each of these roots are folders for Artists.  In each of those are one or more folders that represent albums by that artist.

Now let's assume one of those root folders (Root A) is my "root" music collection and it contains a few thousand artists.  The other root folder (Root B) is a collection of music off my old hard drives, CDs, etc.  I know that there are duplicates between these folders - artists that exist in both as well as albums that exist in both.  I want to go through Root B and move only those albums to Root A if they don't already exist.  That means that I want to move all albums that aren't already in Root A, creating the containing Artist folder if it's there.  If the folder is there, I want to skip it and I'll manually check the list of songs later.

The traditional way to do this would be to write a recursive method that would look something like this pseudocode:

void Parse(sourcefolder, destfolder)
{
   foreach(directory in sourcefolder.directories)
   {
       if(! exists(destfolder[folder]))
       {
          Copy(sourcefolder, destfolder);
       }
       else
       {
           Parse(directory, destfolder + directory);
       }
   }
}

Well since this code really is nothing but a series of operations on a collection, LINQ immediately comes to mind as a good fit.

The first challenge I ran into is that my algorithm requires a list of directories contained in a parent directory.  Unfortunately Directory.GetDirectories returns a list with the fully qualified path and I just needed the name of the folder itself.  So I wrote a couple of extension methods that get purely a list of the directory names, not the paths.  I also added one for checking to see if a directory was empty (to be used later for cleanliness):


public static class IO
{
  public static bool IsEmptyDirectory(this string path)
  {
    return (Directory.GetDirectories(path).Count() + Directory.GetFiles(path).Count()) == 0;
  }

  public static string FolderNameWithoutPath(this string path)
  {
    return Path.GetFileName(path);
  }

  public static string[] GetFolderNamesWithoutPath(this string path)
  {
    return (from folder in Directory.GetDirectories(path)
        select folder.FolderNameWithoutPath()).ToArray();
  }
}

Once I had those, the resulting merge method was a simple iteration across a couple LINQ queries.

private void MergeFolders(string sourceFolder, string destinationFolder)
{
  // copy those in A but not in B
  foreach(string folder in
      sourceFolder.GetFolderNamesWithoutPath().Except(
      destinationFolder.GetFolderNamesWithoutPath(), StringComparer.InvariantCultureIgnoreCase))
  {
    Directory.Move(Path.Combine(sourceFolder, folder), Path.Combine(destinationFolder, folder));
  }

  // now go through those in both and repeat
  foreach (string folder in
      sourceFolder.GetFolderNamesWithoutPath().Intersect(
      destinationFolder.GetFolderNamesWithoutPath(), StringComparer.InvariantCultureIgnoreCase))
  {
    string src = Path.Combine(sourceFolder, folder);
    MergeFolders(src, Path.Combine(destinationFolder, folder));

    if (src.IsEmptyDirectory()) Directory.Delete(src);
  }
}

 

5/27/2008 10:33:04 AM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Monday, May 19, 2008
We've published a new article on the OpenNETCF Community Site titled "Native vs. Managed Code: GDI Performance"
 
 
In it, I look at the performance differences between native and managed code making GDI calls.
 
In case you missed them, our other recently published articles include:
 
- Performance Implications of Crossing the P/Invoke Boundary
- An Introduction to WCF for Device Developers
- Getting a Millisecond-Resolution DateTime under Windows CE
- Using GDI+ on Windows Mobile
- Sharing Windows Mobile Ink with the Desktop
- OpenNETCF Mobile Ink Library for Windows Mobile 6
- Improving Data Access Performance with Data Caching
- Developing Connected Smart Device Applications with sqlClient
- Debugging Without ActiveSync
- Image Manipulation in Windows Mobile 5.0
- Don't Fear the Garbage Collector
 
All of our articles are available online at:
http://community.OpenNETCF.com/articles
 
5/19/2008 12:27:16 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Friday, May 09, 2008
OpenNETCF is in the midst of some major infrastructure updates to get automated unit testing of device assemblies working with Team Foundation Server.  Let's just say that it's nowhere near a simple task.

As part of the work, we needed to automate access to the Device Emulator using the Microsoft-supplied Automation Interfaces.  Their C++ and WScript samples for usage leave a bit to be desired, so we wrapped them in an object-oriented model to provide at least a skeletal framework for launching, resetting, saving state etc.  The classes haven't been heavily tested and the test harness for the classes is very basic, but it's a good starting point, and the download (below) is what we're using in our continuous integration process, so it's definitely functional.



We're releasing this source under the MIT X-11 license.  If you make updates and want to submit them back to us, we'll be happy to integrate them, but it's not required.

Download the source and test harness here

5/9/2008 3:04:11 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [1]  | 
 Monday, May 05, 2008

Finally!  Someone has created a code profiler for the .NET Compact Framework.  And what's even more exciting is that it's free.  I've not used it, so I can't vouch for how well it works, or how easy it is to use, but the fact it exists is quite promising.

5/5/2008 8:14:17 AM (Eastern Daylight Time, UTC-04:00)  #    Comments [1]  | 
 Friday, April 18, 2008

Ever since learning how to use function pointers in C, I've always been a fan of using them to help make code a bit more usable, especially when you've got a state machine.  Today, as I'm working on a Wizard UI for a desktop application I came across a typical scenario for using a function pointer.  Depending on the stage of the Wizard you're in, a button will have to do separate things.

That got me to thinking that most managed developers simply don't understand the power and utility of delegates, but instead simply consider them a necessity when using Control.Invoke or creating custom events. Sure, in my case I could have a switch statement in the click handler and do logic there, or I could unhook the click handler from one method and hook it to another, but those all seem ugly and a pain in the ass to me.  A simple function pointer change is all you need.  So I decided I'd throw together a really simple example of how you would use a delegate to change the behavior of a Button click.

Let's assume that we have a button that we want to click, and when it's clicked it will do one of 4 things, depending on the state of our application.  We'll just use a messagebox here to give you the idea - what it does is up to you- it's a function after all.