A Windows service initially looks something like this:
using System.ServiceProcess;
internal partial class MyService : ServiceBase
{
static void Main()
{
ServiceBase[] ServicesToRun = new ServiceBase[] { new MyService() };
ServiceBase.Run( ServicesToRun );
}
}
What I have done is modify Main()
so that I can use it both to launch the service and to process command-line stuff, like this:
using System;
using System.Runtime.InteropServices;
using System.ServiceProcess;
internal partial class MyService : ServiceBase
{
const int ATTACH_PARENT_PROCESS = -1;
[DllImport( "kernel32.dll" )]
static extern bool AttachConsole( int dwProcessId );
[DllImport( "kernel32.dll" )]
static extern bool FreeConsole();
static void Main()
{
if ( Environment.UserInteractive ) {
try {
// Redirect console output to the parent process.
AttachConsole( ATTACH_PARENT_PROCESS );
// Process command line arguments here...
} catch {
// Handle exceptions here...
} finally {
// Detach from the console.
FreeConsole();
}
} else {
ServiceBase[] ServicesToRun = new ServiceBase[] { new MyService() };
ServiceBase.Run( ServicesToRun );
}
}
}
When the executable is built, I register it with the operating system as normal (actually, I use a -install command-line option to do that). When the service is started, the UserInteractive
flag is false, so the service starts as usual. From a command prompt, though, the UserInteractive
flag is true, so the command-line processing takes over.
All you need at this point is have the command-line instance of your executable communicate with the service instance of your executable via some sort of IPC - socket, pipe, shared memory, WCF, etc.