My favorite option, and one which I convinced my previous employer to adopt as a company policy, is as follows:
All server-type applications are written with no directly-attached UI of any sort. Whether this compiles as a console application, as a windows application, or otherwise is irrelevant at the design stage -- with .NET the difference comes down to flipping a compiler switch. Generally, though, since the program is running without direct human intervention, we usually designed it to run as a service -- the Service Control Manager takes care of startup and shutdown, can restart the application when it fails, and does a lot of good stuff that is difficult to do on your own when writing a desktop application.
Next, you have the server application listen over the network for an "admin" to connect. This admin connection is your UI. Things like SSL encryption and authentication are up to you and your company, but at the base of it I would recommend building a line-based human-readable interface. That way you can connect to it with telnet and issue commands like "show connections
", "drop user 52
", and "restart
". Any sort of administrative behavior, and any sort of status and statistics should be exposed using this interface. First of all, this helps with debugging, and second of all, it leads to the next step...
Last you build a UI. A simple one probably. Part of the configuration for this UI is to specify a host and port for it to connect to, as well as any authentication bits. The UI application connects to the machine running the service and issues commands over the network admin interface, and interprets the results. At our company, each new UI was a snap-in module as part of a larger project. This project would show little red and green lights representing the various servers and their statuses. Clicking on a server would allow you to "drill-down" to that server and examine various aspects of it state or configuration.
Though the project started as my little program on only one or two servers, it quickly grew to include dozens of servers running a handful of services each, running on diverse operating systems and in numerous cities around the world. This simple UI policy allowed us to easily track and control hundreds of these services from one single seat, or simultaneously at different desks in different offices.
Scalability mean not requiring someone in front of the computer to hit a button on a program you wrote.