Installing CF 2.0

CF 2.0 is about to release on Nov 7th but obviously no device will have the bits in ROM for some time. If you are writing code now that relies on CF 2.0 how can you deploy it?

 

Firstly the CF bits need to be shipped with your installation.

There are a number of CAB files installed with Visual Studio 2005 for various different platforms. Take a look on a machine with a VS in C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\CompactFramework\2.0\v2.0\WindowsCE\wce500 and you will see directories for mips, sh4, x86 and arm cpu's. All Windows Mobile devices are armv4 compatible so the bits we need are in armv4i and the NETCFv2.wm.armv4i.cab file. The other directories and cab files are for Windows CE devices.

 

Now we have the bits, the next challenge is how to install them.

That’s pretty straight forward as its the same for any Windows Mobile cab file - it needs to be deployed and run on the device so if you are using an SD card then include the CAB file as part of the Autorun.exe install process, if you are using ActiveSync then add the cab to the list of files to be deployed.

 

The trickiest part is to know when to deploy CF 2.0.

If its already there then you don’t want to push the user through an uninstall step just to re-install the same bits each time. The right thing to do is detect what version of CF is installed during the installation steps of your app. There are a number of ways to achieve this for example look in the \Windows directory and pick a CF file to read the version or datetime information. The neatest way I have found is to use the registry as there is a DWORD value placed in HKLM\Software\Microsoft\.NETCompactFramework for each version on the device.

 

Take a bit of care about install order as well because CF 2.0 requires a device soft reset (its done automatically by the cab file) so install your bits first and CF 2.0 last so you don’t break your app install.

 

I built an example of this for an autorun.exe for SD / CF cards but the same principal can be taken to any install mechanism. Because all Windows Mobile 5.0 devices will have CF 1.0 SP3 installed I wrote the installer in C# for CF 1.0 to make my life a bit easier. Grab the full source here.

namespace Autorun

{

public class MyClass

{

private static string ReadCFVersions =

"<wap-provisioningdoc>" +

"<characteristic type=\"Registry\">" +

"<characteristic-query type=\"HKLM\\Software\\Microsoft\\.NETCompactFramework\"/>" +

"</characteristic>" +

"</wap-provisioningdoc>";

static void Main(string[] agrs)

{

bool bNeedsCf = true;

// Check the CF version.

if (agrs[0] == "install")

{

// Split the path and find the storage card name used

string FullPath = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;

string[] Tokens = FullPath.Split('\\');

if (Tokens.Length < 2)

{

MessageBox.Show("This install is designed for Windows Mobile 5.0 only", "Install Error");

return;

}

XmlDocument ConfigDoc = new XmlDocument();

ConfigDoc.LoadXml(ReadCFVersions);

// Apply the Read the setting value

XmlDocument results = ConfigurationManager.ProcessConfiguration(ConfigDoc, true);

// Now itterate through the versions.

foreach (XmlNode node in results.DocumentElement.FirstChild.FirstChild.ChildNodes)

{

if (node.Name == "parm")

{

// Get the second attribute

string[] tokens = node.Attributes[0].InnerText.Split('.');

int Major = Convert.ToInt32(tokens[0]);

if (Major >= 2)

{

bNeedsCf = false;

break;

}

}

}

// Need to install CF 2.0

if (bNeedsCf && DialogResult.Cancel == MessageBox.Show("This application requires a newer version of the Compact Framework. Click OK to install or Cancel to exit. Note: You might need to reset the device after the install", "Install CF 2.0", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1))

{

return;

}

// Now install the app.

string AppPath = string.Format("\\{0}\\MYAPP.CAB", Tokens[Tokens.Length - 2]);

RunCab(AppPath);

if (bNeedsCf)

{

// Build the cab file name

string CabPath = string.Format("\\{0}\\NETCFv2.wm.armv4i.cab", Tokens[Tokens.Length - 2]);

RunCab(CabPath);

}

}

}

 

Marcus