Services in Windows Mobile and Windows CE are DLL libraries loaded by service.exe and then run as ..... well as a services. Unfortunately these DLLs has to be written in native code. But why to use native code when man just needs little "invisible" application, that will survive Windows Mobile memory management?

ServiceApplication class

I wrote ServiceApplication class that is used in similar way as Application class in Windows Forms. In fact it is the console application with main loop that processes system messages. ServiceApplication can be controlled from outside world by interprocess messages. Simple WM_USER windows messages. The easiest service can look like this.

const int WM_USER = 0x400;
const int WM_QUIT_SERVICE = WM_USER + 5001;
const int WM_CLEAR_LOG = WM_USER + 5002;

static void Main(string[] args)
{
// Set register name
ServiceApplication.Name = "MyFirstService";

// Register messages
ServiceApplication.RegisterMessage(Interprocess.WM_QUIT_SERVICE);
ServiceApplication.RegisterMessage(Interprocess.WM_CLEAR_LOG);

// Set event handler for registered messages
ServiceApplication.OnRegisteredMessage +=
new ServiceApplication.RegisteredMessageEventHandler(ServiceApplication_OnRegisteredMessage);

// Start main application loop
ServiceApplication.Run();
}

There is a service name set, which is actually name of MessageWindows that represents the service. All messages to control the service is send to this MessageWindow. All messages that should be processed by service has to be registered. Whenever the registered message arrived, event is fired. Event handler may look like this.

static void ServiceApplication_OnRegisteredMessage(ref Microsoft.WindowsCE.Forms.Message message)
{
switch (message.Msg)
{
case Interprocess.WM_QUIT_SERVICE:
ServiceApplication.Exit();
break;

case Interprocess.WM_CLEAR_LOG:
ClearLogFile();
break;
}
}

Talking to service

As I mentioned earlier, service is controlled through windows messages. Following code sends message to the service.
const int WM_USER = 0x400;
const int WM_QUIT_SERVICE = WM_USER + 5001;
const int WM_CLEAR_LOG = WM_USER + 5002;

public void StopService()
{
IntPtr hwnd = FindWindow(IntPtr.Zero, "MyFirstService");
Message msg = Message.Create(hwnd, WM_QUIT_SERVICE, (IntPtr)0, (IntPtr)0);
MessageWindow.SendMessage(ref msg);
}

[DllImport("coredll.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(IntPtr lpClassName, string lpWindowName);

Example application

ServiceApplication class is bundled in little demo application. Whole solution consists of three projects. Fisrt project CallLoggerLib is library containing ServiceApplication class and Interprocess class for communication with service. Second project is service implementation itself. Very simple CallLoggerService thats logs information about last phone call into the file. Third project CallLogger is a simple UI application which is used to start and stop the service.

When deploying to the device all files has to be in same directory!!

Download file: CallLogger.zip [60 Kb]

CODEPLEX library

Updated at 9th June 2008.Peter Nowak did some improvements on my sample code and publish it as a complete library on Codeplex: Managed Services for Windows Mobile.