Updated 2011-12-28 15:52:38 by dkf

As of 2007, winserv might be a preferable alternative [1].

It's possible to run Tcl scripts as services under Microsoft Windows NT. Matt Newman has done a nice job of producing a wrapper, ""tclsvc"", that lets any event-driven Tcl script run as a service. See it at http://www.sensus.org/tcl/index.htm. -- CLN

As of version 1.1 (1999/6/28 in the source code $Id: 1797,v 1.6 2004-01-24 07:00:18 jcw Exp $) there's a minor problem with this. The service only wakes up when the Tcl event loop fires. Hence, if you try to start or stop it from the services control panel and the Tcl code is blocked, the control panel will think the program has crashed. The simple solution is to put the following code before you start your main event loop:
 proc nothing {} {after 3000 nothing} ; nothing

This will wake the event loop every few seconds, which will allow Tclsrv to process requests for status, shut down, etc. -- DNew [But maybe only some flavors of Win* exhibit this?]

A/AK This patch will enable tclsvc to start or stop when the interpreter is idle waiting for an event to come...
--- tclsvc.c        Mon Jun 28 07:16:27 1999
+++ tclsvc.c        Mon Nov 24 18:53:22 2003
@@ -29,6 +29,9 @@
 /* internal variables */
 static TCHAR        szErr[256];
 static int                stopRequested = 0;
+static Tcl_ThreadId        mainThread;
+static int        mainThreadSet = 0;
+static Tcl_Event * alerter;
 
 static void
 exit_handler(ClientData clientData)
@@ -141,6 +144,9 @@
         exitCode = 1;
         goto done;
     }
+    mainThread = Tcl_GetCurrentThread();
+    alerter = (Tcl_Event *) ckalloc( sizeof (Tcl_Event) );
+    mainThreadSet = 1;
     while (stopRequested == 0) {
         Tcl_DoOneEvent(TCL_ALL_EVENTS);
     }
@@ -180,9 +186,16 @@
     Tcl_Eval(interp, buffer);
 }
 
+static int EmptyProc( Tcl_Event *ev, int flags ) { return 1; }
 void
 ServiceStop(void)
 {
     ReportStatusToSCMgr( SERVICE_STOP_PENDING, NO_ERROR, 0);
     stopRequested = 1;
+    if (mainThreadSet) { 
+        mainThreadSet = 0;
+        alerter -> proc = EmptyProc;
+        Tcl_ThreadQueueEvent(mainThread,alerter,TCL_QUEUE_TAIL);
+        Tcl_ThreadAlert(mainThread); 
+    }
 }

Note that the patch above lacks appropriate #ifdef's to make it compatible with pre-8.3 versions of tcl.

JH: For those who require up-to-date support for Tcl scripts to run as an NT service, this is one of the many features available in the Tcl Dev Kit.