The purpose of this series of posts is to give an overview of my experiences deploying code to multiple platforms, in this case specifically taking a set of services written for Windows CE and make them cross-platform as a set of daemons for Raspbian. This post focuses on the difference between Windows CE and Raspbian itself.

Purpose of the Device

The device is designed to capture, process and relay data from multiple other devices to a central server somewhere out in the wild of the internet. For this purpose the device runs a number of programs:

  • Data capture service
  • Message relay service, similar to Flume
  • Web-front end for configuration/debugging, running ASP classic
  • Updater service

The points of focus here is that we’re using three Windows services and an ASP classic web site. Inside those we’re listening to UDP traffic, sending and receiving files over FTP, sending and receiving via data web services. These areas are potential issues for moving from Windows CE to Raspbian as their behaviour is quite different between the platforms.

The services are already cross-platform between Windows and Windows CE. One of the major differences between the two is that the Windows CE version is not actually a service, but rather a program that runs without a GUI. This is due to Windows CE not having a concept of service applications until version 4.0. Moving to Linux the aim would be to run the service as a daemon.

Relevant Platform Differences

File Structure

The most obvious difference between the platforms is the file structure. Most users are familiar with a filepath structure in Windows, where each folder separated by a backslash proceeding the drive letter. For example:

C:\Users\sam\Documents

However Linux uses forward slashes to separate folders and doesn’t use drive letters for different drives. Below is the equivalent from Xubuntu, although most Debian based OS’ are very similar:

/home/sam/Documents/

There are some differences between how Windows and Windows CE use drive letters. For example in the screen shot below from Windows CE there are three drives available, none of which have a drive letter.

Untitled

ExternalStorage and Hard Disk are both removable drives, with the OS installed on the InternalStorage; the equivalent filepath for this Windows CE would be:

\My Documents\

Windows Services and Linux Daemons

Windows Services and Linux Daemons are very similar in that they both run in the background, though there are a number of stark differences. For example with a .NET Windows Service there are several events that can be called: start, stop, restart, etc. However it appears for a Linux Daemon it appears things are quite different, where the daemon runs just like any other application and is configured by an init script for that daemon.

For the context of .NET/Mono services on Linux however there is a simple way of executing services:

1
mono-service2 MyService.exe

Essentially this command will run the .NET/Mono program, in this case “MyService.exe” in the background, attempting to use the standard .NET Windows events if able. It’s also possible to run a .NET/Mono application with no GUI like this. Setting the .NET/Mono service to run doing start-up can be configured in the same way as a regular daemon by using an init script.

1
sudo ps aux

The above command returns all the daemons currently running along with various information related to that daemon. If there’s a mono-service then the command will start with the mono runtime path, for example see the MyService.exe output below:

1
2
3
sam@makise ~ $ sudo ps aux \[sudo\] password for sam:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
sam 19730 13.3 5.6 80096 53832 ? Sl Mar30 570:41 /usr/bin/mono /usr/lib/mono/2.0/mono-service.exe MyService.exe
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
sam 19730 13.3 5.6 80096 53832 ? Sl Mar30 570:41 /usr/bin/mono /usr/lib/mono/2.0/mono-service.exe MyService.exe

Running services under mono-service will be covered in most detail later on.

Relevant Framework Differences

The framework we use on Windows CE is .NET Compact Edition 2.0.aspx), however Windows CE can have version 3.0/3.5. Changing the .NET version for service would require distributing and installing that version of .NET on every device currently deployed, which is just not possible.

Complimentary to .NET the framework used on Raspbian is Mono, this is mostly compliant to .NET. Mono’s compliance with .NET is the full framework, not just the compact edition, despite Raspbian running on an ARM processor. Using MonoDevelop, it’s suggested that Mono will support any .NET version from 2.0 to 4.5 . If you’re migrating to Raspbian and leaving your old platform behind I’d recommend changing your framework version to the latest, as this will give you access to all the latest features and fixes for the .NET/Mono framework.

Mono is an open source project, supported by Xamarin, to support .NET written applications for Windows, OS X and Linux based operating systems. There are features in .NET which are currently not implemented or bugged in Mono, however the vast amount of .NET features is supported.

1
2
3
4
5
6
7
8
// Example Code, Please Remove using System.Runtime.InteropServices;
[DllImport(user32.dll)] private extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndIntertAfter, int X, int Y, int cx, int cy, int uFlags);
[DllImport(user32.dll)] private extern int GetSystemMetrics(int Which);
private const int SM_CXSCREEN = 0;
private const int SM_CYSCREEN = 1;
private IntPtr HWND_TOP = IntPtr.Zero; private const int SWP_SHOWWINDOW = 64;
public int ScreenX { get { return GetSystemMetrics(SM_CXSCREEN); } }
public int ScreenY { get { return GetSystemMetrics(SM_CYSCREEN); } }