Web Server Tools and Samples on Windows CE

I get asked enough about various Web Server based technologies on CE that it's time I try and answer the most common ones here.  You can tell it's been a while since I've posted since I'm more verbose than usual.

First off, why do you want a web server on an embedded device?  Usually people think WinCE and PocketPC's are the same thing, but this is not the case.  CE can also run in devices without displays (think a residential gateway or a vending machine).  In this case, a web server running on the CE device itself can dynamically generate HTML and send it back to a remote web browser, which in turn can configure the device remotely. 

II - ISAPI Extensions Versus ASP Pages Versus ...
CE supports both ASP and ISAPI extensions, inspired by IIS's implementation.  They're both subsets, though with ISAPI's we come pretty close.  Not so with ASP, which is much more limited in features.  The first thing you need to decide is whether to use ISAPI extensions or ASP pages.

ISAPI extension pro's:
* Require very limited system resources - RAM/ROM.  Since they're straight C, run very fast.
* Relatively easy to debug them using your C debugger

ISAPI extension con's:
* Harder to make changes to HTML pages, which either are hardcoded in .c files (yuck!) or you'll need to read out and do some custom parsing on.
* C is harder to program in that JScript/VBScript.

ASP pro's:
* Scripting languages are easier that C programming.
* Easier to make changes to web pages on the fly and immediately see them being made in results displayed.

ASP con's:
* ASP requires JScript and/or VBScript on the device, which require about 300KB ROM and much more RAM than ISAPI's each. 
* My best guess is that ASP's on CE run about 20-50 times slower than an equivalent ISAPI extension.
* We don't have good script debugging tools on WinCE -- i.e. no Visual Interdev.  (The Scripting "printf()" equivalent is as good as we get I'm afraid.)  However you can debug tricky stuff with desktop tools if you have to and take fix back to CE.

What about ASP.Net?  Sorry, we don't have it on CE.  Furthermore, the Compact Framework does not allow you to call managed code from native, so you can't have your ISAPI/ASP page call out into managed.  (You can do managed code->native calls, but not the other way around.)

CE also has ISAPI filters, like IIS.  If you don't know what this means, good.  I highly recommend you avoid using ISAPI filters unless you have a really bizarro scenario.  Ask yourself why an ISAPI extension/ASP page isn't good enough for your purposes, then sleep on it, and ask yourself the same question again.  I recommend against filters because they're tricky to get right and because most of the time I see people using them there is a much simpler solution that involves using an ISAPI extension.  There are cases where an ISAPI filter is the only way to go, but these (at least for simple web server scenarios) are rare.

III - Making writing ISAPI Extensions easier - NatAdmin, WebAdmin, and RemoteAdmin
Pretty much all Microsoft written remote UI config for CE uses ISAPI extensions.  The reason is that we don't control the hardware that our code will run on.  We know that an OEM may have super-limited RAM/ROM, so we have to shoot for the lowest common denominator.  Since you probably know how much RAM/ROM you have, you may be able to go for ASP's if that makes sense.

This final section will look at 3 interesting ISAPI extensions that MS has shipped the source code for over the years.  Hopefully you can either reuse this code without modification or extend it for your custom needs.  You should at least learn something from the good (and the bad :() of these samples.

(Note: All of the code described below is included in Platform Builder only.  It's not available from Microsoft to say people doing HTTPD development on PocketPC's.  Sorry.)

III.A - NatAdmin
CE ships all our ISAPI extensions as public code in Platform BUilder to help you get started.  In CE 3.0 (CommAddon Pack) and CE 4.0-4.2 the main ISAPI extension was NatAdmin.  The "NAT" part of this gives away it's history - it was originally designed to configure NAT (i.e. residential gateway) boxes.  This includes setting the IP addresses of device's NICs, changing the firewall logic, changing the IP addresses that the DHCP allocator hands out, etc...  As is typical with any technology that works well enough, NatAdmin had tons of stuff unrelated directly to the gateway added to it over time.  For instance, there is SMB server configuration pages, FTP server stuff, and so on.

NatAdmin was never architected to be extended this far.  It did one particularly gross thing, which was hardcoding all the HTML pages is C strings with sprintf format identifiers in them.  This made initial development very easy, but made the maintenence and modifying the page very hard.

Code to NatAdmin lives in %_WINCEROOT%\public\servers\sdk\samples\natadmin\

III.B - WebAdmin
In CE 4.2, an older and wiser John Spaith came up with a better way when he wrote WebAdmin, which is an ISAPI extension that configures the web server itself only (i.e. virtual roots settings, which users have access to what, etc...).  He wrote a generic script engine named IsapiGEN that will read in a file and do conditional checks, foreach statements, and print out variable data.  IsapiGEN can handle variables by having a callback C++ class that returns variables as a string.  The parsed file will then be sent back as HTML to the web browser.  WebAdmin used ISAPIGen totally, though IsapiGen is avialable for other uses as well.

This is nicer because it allows the display and control logic to be separated.  In some sense this is the poor man's ASP.  However, this architecture is a bit tricky to get the hang of.  We still ship it in CE 5.0 and if you're looking at something very simple this may not be a bad approach.  The code and a readme.txt explaining how to use ISapiGen live in %_WINCEROOT%\public\servers\sdk\samples\natadmin\baseisapi.  The WebAdmin code that uses IsapiGen is in %_WINCEROOT%\public\servers\sdk\samples\http\webadmin.

III.C - RemoteAdmin

[NOTE! 9/12/05 UPDATE:] Customer experience has shown that RemoteAdmin is considerably more difficult to customize than we thought it would be.  If you are building a gateway image (SYSGEN_GATEWAY or SYSGEN_SMB_UI) then RemoteAdmin works pretty well.  Unfortunately it is hard-coded to work only out of the box with those components.  Making it work in a non-gateway device is possible in theory, but because of its architecture it's quite difficult to figure this out. 

Even gateway customers have had all sorts of problems customizing it because of its complicated architecture.  I'm leaving the original text below that I wrote describing the way RemoteAdmin can work in the best case, but please be aware that customers I've spoken with have not had a very good experience.

If you don't need any of the networking config UI that RemoteAdmin offers, you're best bet is either creating an ISAPI extension from scratch or using WebAdmin as the framework.  If you still need to use RemoteAdmin on a non-gateway, according to Beggi Oskarsson you can do it as follows:  "I have solved my problem by using the Gateway template as a starting point and then manually added all catalog items that
the Industrial Controller template added automatically."

On behalf of Microsoft I apologize for the headaches this has caused, and I personally apologize for praising it so highly below without knowing better.


I finally got out of the Remote UI writing business in CE 5.0.  Chris Gray wrote RemoteAdmin in this release and NatAdmin was ripped from the tree entirely.  RemoteAdmin was much better thought out than our previous UI efforts.  It's similiar to IsapiGen in that it reads its data from script files.  However instead of having a C++ class that you have to bind to a particular page in the script engine, it generates JScript dynamically that has the various variables set and just sends over HTML script pages with a <include "variables.js"> on top.  So the architecture does a lot more on the client side and is much easier to extend.

Furthermore, it's easier to plug modules in and out of RemoteAdmin, unlike NatAdmin or WebAdmin, where everything was hard-coded.  The look and feel of RemoteAdmin are easier to change, too.  Since we were really serious about this, we documented how it works and how you can extend it to meet your needs at MSDN.  So rather than pointing you at C source and a readme.txt on this one, I can point you at http://msdn.microsoft.com/library/en-us/wcecomm5/html/wce50oriRemoteConfigurationFramework.asp?frame=true

Ideally you can ship RemoteAdmin in its present state - we spent a lot of time getting the UI itself polished.  But if you want to do branding or add custom configuration modules, hopefully you'll find the experience much better than in the past.

III.D Closing thoughts

If you're writing just a simple ISAPI extension or one that doesn't generate UI, then none of this may be all that helpful.  However, if you're doing ISAPI development work on CE 5.0 you should seriously think about tying into to RemoteAdmin.  If you're on CE 4.X and you have a ton of web pages to generate, may we suggest you upgrade to CE 5.0 :)?  If this isn't an option, take a look at WebAdmin and NatAdmin.  They'll give you some ideas, at least, and you may be able to use IsapiGen if you'll put up with a little learning curve.

At the devcon this July, even RemoteAdmin was critized by one of the attendees for using JScript and HTML when it could've been using XML and XSLT.  So the moral here is that there's no right answer to writing web pages, but I hope our existing samples and this post will get you off to a good start.

[Author: John Spaith]