Skip to main content

Wise Installer 0, James 1

As you may have read in previous posts I've been using Wise Installer to create MSI files of our software for the PocketPC and Smartphone. However a deadline on Wednesday to go and demonstrate one of our applications and a still non-functional Wise installer led me to return to basics and get down and dirty with .CAB, .INF, .INI & .MSI's...and guess what? It's actually not too unbearable!

Starting on Tuesday afternoon I had a working MSI installer with custom actions and multi-cab install in about 4 hours. The problem with getting this stuff to work is that there really isn't a great overall guide to it all. I Googled a couple of links and used the MSDN Compact Framework FAQ and after reading through it all understood pretty much what there is to know and plugged it all together. These are the links I used...

The missing ingredient in all this how to install the cab files your application is dependent upon. To locate exactly what CAB files your application will need open the "Dependencies.PPC.txt" file that is created in the Cab folder under your project once you have run "BuildCab". Have a scan through, you'll see the other .CAB files pretty easily. So how do you get these into the .MSI?

  • Follow the instructions in the first link for adding a CustomInstaller and Setup Project to your SmartDevice solution.
  • Create a .INI file for each .CAB mentioned in the Dependencies file (if you want to install it)
  • Add the .CAB files to the Setup Project. The full path to each is in the Dependencies file.
  • The secret can call the CEAppMgr (ActiveSync Add/Remove Programs) program with multiple .INI files on the command line parameter and it will install these one at a time.
The code below is a modification of that shown in the links above - it allows you to call the RunAppManager method with an optional number of .INI files as parameters. I have actually got another version of this that reads the .INI files from an xml manifest file but I don't want to make things too easy for you!

private void CustomInstaller_AfterInstall(object sender, InstallEventArgs e)
string desktopFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// run WinCE App Manager to install .cab file on device
this.RunAppManager(desktopFolder, "OpenNETCF.ini", "YourApplication.ini");
private void RunAppManager(string desktopFolder, params string[] iniFiles)
// get path to the app manager
const string RegPath = @"Software\Microsoft\Windows\" +
@"CurrentVersion\App Paths\CEAppMgr.exe";
RegistryKey key = Registry.LocalMachine.OpenSubKey(RegPath);
string appManager = key.GetValue("") as string;

// build up the list of ini file arguments - each one needs wrapping in ""
string args = string.Empty;

for (int i = 0; i < iniFiles.Length; i++)
args += string.Format("\"{0}\" ", Path.Combine(desktopFolder, iniFiles[i]));

if (appManager != null)
// launch the app
//MessageBox.Show(appManager + "\n" + args);
Process.Start(string.Format("\"{0}\"", appManager), args);
// could not locate app manager
MessageBox.Show("Could not launch the WinCE Application Manager.");

This is the INI file for OpenNETCF. The text in red must match up and DO NOT have any spaces between the files and commas in the CabFiles list. The list below has a line break just for formatting sake but it should be all one continuous line.

Version = 1.0
Component = OpenNETSDF

Description = OpenNETCF SDF.


This works really consistently (unlike Wise!) and I'm pleased with what I've acheived. I have plans for creating a Visual Studio.NET addin to run the CAB build and scan the Dependency file and automatically create the Setup Project with the right CAB and INI files in it for you but that's another story.

You can customise the installer using WinForms/.NET in the AfterInstall and Uninstall events so you can make the whole thing pretty slick. Have a go, it's not as tricky as it looks!

And to make it even easier these links tumbled out of the blog-sphere the day after I had done all this! DOH!


Anonymous said…
After struggling for 2/3 days with this problem. I was releived to find that this article gave me the solution in less than 20 mins of effort!
Thanks James
Anonymous said…
I also struggled for 10-20 hours and almost deciding to give up before finding your blog. Thanks SOOOO much.
M Ramsden said…
Thanks! You rock... even 2 years after the fact.

Popular posts from this blog

Walk-Thru: Using Wolfpack to automatically deploy and smoke test your system

First, some history... The advent of NuGet has revolutionised many many aspects of the .Net ecosystem; MyGet, Chocolatey & OctopusDeploy to name a few solutions building upon its success bring even more features to the table.

I also spotted that NuGet could solve a problem I was having with my OSS System Monitoring software Wolfpack; essentially this is a core application framework that uses plugins for extension (Wolfpack Contrib) but how to unify, standardise and streamline how these plugins are made available? NuGet to the rescue again - I wrapped the NuGet infrastructure (I deem NuGet to be so ubiquitous and stable that is has transcended into the software "infrastrucuture" hall of fame) with a new OSS project called Sidewinder. Sidewinder allows me to wrap all my little extension and plugins in NuGet packages and deploy them directly from the Wolfpack application - it even allows me to issue a new version of Wolfpack and have Wolfpack update itself, sweet huh?


Geckoboard Countdown Widget v2

v2 is here, now with added colours! This time using the RAG Numbers widget to display your date countdown - as you get nearer the date the number will change from green to amber then red.

The new url is:!
Note 1: notice the new /rag/ path and the msg querystring param.
Note 2: the original v1 url still works

To use this on your Geckoboard add a new "Custom Widget/RAG Numbers" widget. By default the number will turn amber at 10 or less days to go and red at 3 or less days to go however you can change these with the querystring (see below).

Required querystring params
date: "yyyy-mm-dd" format, this is the target date to countdown totz: timezone offset in hours from GMT that you are in. Can be negative if you are behind GMT
Optional querystring params
msg: the label that appears next to the number of days (remember to encode spaces as +). The default is "Days Remaining" if you…

Resharper add-in idea - highlight IDisposable vars

[Update 18th July 2013]
@RobGibbens and Greg Hurlman picked up on this - Rob pointed out that there is an FxCop rule that can do this and Greg suggested a Visual Studio extension. I've had a quick look at the Visual Studio options and it looks like an "Editor Extension" is a good fit....hmmm, Project New, click...doh...dammit I really don't have time for this but it looks a fun little diversion! I'll update here if I get anything working.

[Original Post]
Had an interesting idea for a Visual Studio Resharper add-in the other day but don't have the time to implement it so thought I would put it out might already exist (and hopefully someone can point me in the right direction) or someone will build it (Darren Voisey where are you?!).

The idea is very simple really - when you have a variable for an object that implements IDisposable it gets highlighted or a tell-tale is displayed to let you know it should be disposed or should be wrapped in a using sta…