Thread overview
Windows 2000 Service and D
Apr 19, 2005
jicman
Apr 20, 2005
Andrew Fedoniouk
Apr 20, 2005
David L. Davis
Apr 20, 2005
jicman
Apr 20, 2005
J C Calvarese
Apr 21, 2005
David L. Davis
Apr 21, 2005
J C Calvarese
Apr 20, 2005
jicman
April 19, 2005
Greetings!

I am trying to have a D executable become a service using,

http://support.microsoft.com/kb/q137890/

as the instructions.  I know the D program, or the executable, is working great, so it shouldn't be a problem.  Does anyone see any problem with this?  Any pointers?  I've never done it, but D has brought up so many new options for me, that it's now easy to create executables and stop using JScript scripts. :-) Thank you Walter.  I don't care what JCC says about you, you're ok in my book. :-)

thanks,

josé


April 20, 2005
I think it make sense to create general purpose NT Service class for D. There are a lot of prototypes, e.g: http://www.codeproject.com/system/VoitelNTService.asp

Andrew.


"jicman" <jicman_member@pathlink.com> wrote in message news:d43vcn$1m38$1@digitaldaemon.com...
>
> Greetings!
>
> I am trying to have a D executable become a service using,
>
> http://support.microsoft.com/kb/q137890/
>
> as the instructions.  I know the D program, or the executable, is working
> great,
> so it shouldn't be a problem.  Does anyone see any problem with this?  Any
> pointers?  I've never done it, but D has brought up so many new options
> for me,
> that it's now easy to create executables and stop using JScript scripts.
> :-)
> Thank you Walter.  I don't care what JCC says about you, you're ok in my
> book.
> :-)
>
> thanks,
>
> josé
>
> 


April 20, 2005
In article <d44c2n$210c$1@digitaldaemon.com>, Andrew Fedoniouk says...
>
>I think it make sense to create general purpose NT Service class for D. There are a lot of prototypes, e.g: http://www.codeproject.com/system/VoitelNTService.asp
>
>Andrew.
>

Here's some basic NT service code that Gifford Hesketh (first.last@gmail.com ) wrote back in May 2004...I can't seem to find his message in forum where this code attached, so I'm going to copy in what I downloaded back then. I've never tested it (but still plan to), but I think this would be a good starting place for you to start writing your planned general purpose NT Service class in D. :)

# /*
# ** service.d -- a skeletal service for Windows
# **
# ** Created 2004-May-27 for the public domain
# ** by Gifford Hesketh (first.last@gmail.com )
# */
# // -------------------------------------------------------------
# // The Japanese author's web site for the Windows headers for D
# // these are the converted header files being imported below.
# // http://hp.vector.co.jp/authors/VA028375/d/windows.h.html
# // -------------------------------------------------------------
# // The direct download for the Windows headers for D
# // http://hp.vector.co.jp/authors/VA028375/d/lib_dmd_windows.7z
# import winbase;
# import winerror;
# import winnt;
# import winsvc;
#
# extern( Windows )
# {
#
#   char * theServiceName = "service.d";
#
#   int main( char[][] args )
#   {
#     SERVICE_TABLE_ENTRY[] theServiceTable;
#     theServiceTable.length = 2;
#
#     theServiceTable[ 0 ].lpServiceName = theServiceName;
#     theServiceTable[ 0 ].lpServiceProc = & ( ServiceMain );
#     theServiceTable[ 1 ].lpServiceName = null;
#     theServiceTable[ 1 ].lpServiceProc = null;
#
#     if ( !(StartServiceCtrlDispatcher( theServiceTable )) )
#     {
#       /*
#        ** probably (?) run from the command line
#        */
#        void * theSCM;
#
#        OutputDebugString( "! StartServiceCtrlDispatcher" );
#
#        theSCM = OpenSCManager( null, null,
#                                SC_MANAGER_CREATE_SERVICE | DELETE );
#
#        if ( cast(SC_HANDLE)0 != theSCM )
#        {
#           void * theService;
#           theService = OpenService( theSCM, theServiceName, DELETE );
#
#           if ( cast(SC_HANDLE)0 != theService )
#           {
#             /*
#             ** service exists; delete it
#             */
#             if ( DeleteService( theService ) )
#             {
#               OutputDebugString( ". DeleteService" );
#             }
#             else
#             {
#               OutputDebugString( "! DeleteService" );
#             }
#
#             CloseServiceHandle( theService );
#           }
#           else
#           {
#             if ( ERROR_SERVICE_DOES_NOT_EXIST == GetLastError() )
#             {
#               /*
#               ** service does not exist; create it
#               */
#               theService = CreateService( theSCM, theServiceName,
#                                           theServiceName,
#                                           SERVICE_ALL_ACCESS,
#                                           SERVICE_WIN32_OWN_PROCESS,
#                                           SERVICE_DEMAND_START,
#                                           SERVICE_ERROR_IGNORE,
#                                           args[ 0 ], null, null,
#                                           null, null, null );
#
#               if ( cast(SC_HANDLE)0 == theService )
#               {
#                 OutputDebugString( "! CreateService" );
#               }
#               else
#               {
#                 OutputDebugString( ". CreateService" );
#
#                 CloseServiceHandle( theService );
#               }
#             }
#           }
#
#           CloseServiceHandle( theSCM );
#        }
#
#     }
#     else
#     {
#       /*
#       ** the service has finished running
#       */
#       OutputDebugString( ". StartServiceCtrlDispatcher" );
#     }
#
#     return 0;
#
#   } // main ()
#
#
#    /*
#    ** the name of this function is arbitrary
#    */
#    void ServiceMain ( uint dwArgc, char * * lpszArgv )
#    {
#      void * theEvent;
#      SERVICE_STATUS theServiceStatus;
#      SERVICE_STATUS_HANDLE theServiceStatusHandle;
#
#      theServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
#
#      theServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
#                                            SERVICE_ACCEPT_PAUSE_CONTINUE |
#                                            SERVICE_ACCEPT_PARAMCHANGE;
#      theServiceStatus.dwWin32ExitCode = 0;
#      theServiceStatus.dwServiceSpecificExitCode = 0;
#      theServiceStatus.dwCheckPoint = 0;
#      theServiceStatus.dwWaitHint = 0;
#
#      theServiceStatusHandle = RegisterServiceCtrlHandler( theServiceName,
#                               &( ServiceCtrlHandler ) );
#
#      if ( cast(SERVICE_STATUS_HANDLE)0 == theServiceStatusHandle )
#      {
#        OutputDebugString( "! RegisterServiceCtrlHandlerEx" );
#      }
#      else
#      {
#        OutputDebugString( ". RegisterServiceCtrlHandlerEx" );
#      }
#
#      theServiceStatus.dwCurrentState = SERVICE_START_PENDING;
#
#      if ( !SetServiceStatus( theServiceStatusHandle, &theServiceStatus ) )
#      {
#        OutputDebugString( "! SERVICE_START_PENDING" );
#      }
#      else
#      {
#        OutputDebugString( ". SERVICE_START_PENDING" );
#      }
#
#
#     /*
#     ** create a synchronization object so the control handler
#     ** can notify when to stop
#     */
#     theEvent = CreateEvent( null, true, false, theServiceName );
#
#     if ( null == theEvent )
#     {
#       theServiceStatus.dwCurrentState = SERVICE_STOPPED;
#
#       if ( !SetServiceStatus( theServiceStatusHandle,
#                               &( theServiceStatus ) ) )
#       {
#         OutputDebugString( "! SERVICE_STOPPED" );
#       }
#       else
#       {
#         OutputDebugString( ". SERVICE_STOPPED" );
#       }
#
#       return;
#     }
#
#     theServiceStatus.dwCurrentState = SERVICE_RUNNING;
#
#     if ( !SetServiceStatus( theServiceStatusHandle, &(theServiceStatus) ) )
#     {
#       OutputDebugString( "! SERVICE_RUNNING" );
#     }
#     else
#     {
#       OutputDebugString( ". SERVICE_RUNNING" );
#     }
#
#     /*
#     ** wait for notification to stop from the control handler
#     */
#     WaitForSingleObject( theEvent, INFINITE );
#
#     theServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
#
#     if ( !SetServiceStatus( theServiceStatusHandle, &(theServiceStatus) ) )
#     {
#       OutputDebugString( "! SERVICE_STOP_PENDING" );
#     }
#     else
#     {
#       OutputDebugString( ". SERVICE_STOP_PENDING" );
#     }
#
#     /*
#     ** deref the synchronization object
#     */
#     CloseHandle ( theEvent );
#
#     theServiceStatus.dwCurrentState = SERVICE_STOPPED;
#
#     if ( !SetServiceStatus( theServiceStatusHandle, &(theServiceStatus) ) )
#     {
#       OutputDebugString( "! SERVICE_STOPPED" );
#     }
#     else
#     {
#       OutputDebugString( ". SERVICE_STOPPED" );
#     }
#
#     return;
#
#   } // ServiceMain ()
#
#   /*
#   ** the name of this function is arbitrary
#   */
#   void ServiceCtrlHandler( uint dwControl )
#   {
#     void * theEvent;
#
#     switch ( dwControl )
#     {
#       case SERVICE_CONTROL_STOP:
#         OutputDebugString( ". SERVICE_CONTROL_STOP" );
#
#         theEvent = OpenEvent( EVENT_MODIFY_STATE, false, theServiceName );
#         SetEvent( theEvent );
#         CloseHandle( theEvent );
#
#         break;
#
#       case SERVICE_CONTROL_PAUSE:
#         OutputDebugString( ". SERVICE_CONTROL_PAUSE" );
#         break;
#
#       case SERVICE_CONTROL_CONTINUE:
#         OutputDebugString( ". SERVICE_CONTROL_CONTINUE" );
#         break;
#
#       case SERVICE_CONTROL_PARAMCHANGE:
#         OutputDebugString( ". SERVICE_CONTROL_PARAMCHANGE" );
#         break;
#
#       case SERVICE_CONTROL_INTERROGATE:
#         OutputDebugString( ". SERVICE_CONTROL_INTERROGATE" );
#         break;
#
#       case SERVICE_CONTROL_SHUTDOWN:
#         OutputDebugString( ". SERVICE_CONTROL_SHUTDOWN" );
#         break;
#
#       default:
#         OutputDebugString( ". ServiceCtrlHandler" );
#         break;
#     }
#
#     return;
#
#   } // ServiceCtrlHandler ()
#
# } // extern ( Windows )

Hope this helps,
David L.

-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
-------------------------------------------------------------------

MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html
April 20, 2005
Thanks.

David L. Davis says...
>
>In article <d44c2n$210c$1@digitaldaemon.com>, Andrew Fedoniouk says...
>>
>>I think it make sense to create general purpose NT Service class for D. There are a lot of prototypes, e.g: http://www.codeproject.com/system/VoitelNTService.asp
>>
>>Andrew.
>>
>
>Here's some basic NT service code that Gifford Hesketh (first.last@gmail.com ) wrote back in May 2004...I can't seem to find his message in forum where this code attached, so I'm going to copy in what I downloaded back then. I've never tested it (but still plan to), but I think this would be a good starting place for you to start writing your planned general purpose NT Service class in D. :)
>
># /*
># ** service.d -- a skeletal service for Windows
># **
># ** Created 2004-May-27 for the public domain
># ** by Gifford Hesketh (first.last@gmail.com )
># */
># // -------------------------------------------------------------
># // The Japanese author's web site for the Windows headers for D
># // these are the converted header files being imported below.
># // http://hp.vector.co.jp/authors/VA028375/d/windows.h.html
># // -------------------------------------------------------------
># // The direct download for the Windows headers for D
># // http://hp.vector.co.jp/authors/VA028375/d/lib_dmd_windows.7z
># import winbase;
># import winerror;
># import winnt;
># import winsvc;
>#
># extern( Windows )
># {
>#
>#   char * theServiceName = "service.d";
>#
>#   int main( char[][] args )
>#   {
>#     SERVICE_TABLE_ENTRY[] theServiceTable;
>#     theServiceTable.length = 2;
>#
>#     theServiceTable[ 0 ].lpServiceName = theServiceName;
>#     theServiceTable[ 0 ].lpServiceProc = & ( ServiceMain );
>#     theServiceTable[ 1 ].lpServiceName = null;
>#     theServiceTable[ 1 ].lpServiceProc = null;
>#
>#     if ( !(StartServiceCtrlDispatcher( theServiceTable )) )
>#     {
>#       /*
>#        ** probably (?) run from the command line
>#        */
>#        void * theSCM;
>#
>#        OutputDebugString( "! StartServiceCtrlDispatcher" );
>#
>#        theSCM = OpenSCManager( null, null,
>#                                SC_MANAGER_CREATE_SERVICE | DELETE );
>#
>#        if ( cast(SC_HANDLE)0 != theSCM )
>#        {
>#           void * theService;
>#           theService = OpenService( theSCM, theServiceName, DELETE );
>#
>#           if ( cast(SC_HANDLE)0 != theService )
>#           {
>#             /*
>#             ** service exists; delete it
>#             */
>#             if ( DeleteService( theService ) )
>#             {
>#               OutputDebugString( ". DeleteService" );
>#             }
>#             else
>#             {
>#               OutputDebugString( "! DeleteService" );
>#             }
>#
>#             CloseServiceHandle( theService );
>#           }
>#           else
>#           {
>#             if ( ERROR_SERVICE_DOES_NOT_EXIST == GetLastError() )
>#             {
>#               /*
>#               ** service does not exist; create it
>#               */
>#               theService = CreateService( theSCM, theServiceName,
>#                                           theServiceName,
>#                                           SERVICE_ALL_ACCESS,
>#                                           SERVICE_WIN32_OWN_PROCESS,
>#                                           SERVICE_DEMAND_START,
>#                                           SERVICE_ERROR_IGNORE,
>#                                           args[ 0 ], null, null,
>#                                           null, null, null );
>#
>#               if ( cast(SC_HANDLE)0 == theService )
>#               {
>#                 OutputDebugString( "! CreateService" );
>#               }
>#               else
>#               {
>#                 OutputDebugString( ". CreateService" );
>#
>#                 CloseServiceHandle( theService );
>#               }
>#             }
>#           }
>#
>#           CloseServiceHandle( theSCM );
>#        }
>#
>#     }
>#     else
>#     {
>#       /*
>#       ** the service has finished running
>#       */
>#       OutputDebugString( ". StartServiceCtrlDispatcher" );
>#     }
>#
>#     return 0;
>#
>#   } // main ()
>#
>#
>#    /*
>#    ** the name of this function is arbitrary
>#    */
>#    void ServiceMain ( uint dwArgc, char * * lpszArgv )
>#    {
>#      void * theEvent;
>#      SERVICE_STATUS theServiceStatus;
>#      SERVICE_STATUS_HANDLE theServiceStatusHandle;
>#
>#      theServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
>#
>#      theServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
>#                                            SERVICE_ACCEPT_PAUSE_CONTINUE |
>#                                            SERVICE_ACCEPT_PARAMCHANGE;
>#      theServiceStatus.dwWin32ExitCode = 0;
>#      theServiceStatus.dwServiceSpecificExitCode = 0;
>#      theServiceStatus.dwCheckPoint = 0;
>#      theServiceStatus.dwWaitHint = 0;
>#
>#      theServiceStatusHandle = RegisterServiceCtrlHandler( theServiceName,
>#                               &( ServiceCtrlHandler ) );
>#
>#      if ( cast(SERVICE_STATUS_HANDLE)0 == theServiceStatusHandle )
>#      {
>#        OutputDebugString( "! RegisterServiceCtrlHandlerEx" );
>#      }
>#      else
>#      {
>#        OutputDebugString( ". RegisterServiceCtrlHandlerEx" );
>#      }
>#
>#      theServiceStatus.dwCurrentState = SERVICE_START_PENDING;
>#
>#      if ( !SetServiceStatus( theServiceStatusHandle, &theServiceStatus ) )
>#      {
>#        OutputDebugString( "! SERVICE_START_PENDING" );
>#      }
>#      else
>#      {
>#        OutputDebugString( ". SERVICE_START_PENDING" );
>#      }
>#
>#
>#     /*
>#     ** create a synchronization object so the control handler
>#     ** can notify when to stop
>#     */
>#     theEvent = CreateEvent( null, true, false, theServiceName );
>#
>#     if ( null == theEvent )
>#     {
>#       theServiceStatus.dwCurrentState = SERVICE_STOPPED;
>#
>#       if ( !SetServiceStatus( theServiceStatusHandle,
>#                               &( theServiceStatus ) ) )
>#       {
>#         OutputDebugString( "! SERVICE_STOPPED" );
>#       }
>#       else
>#       {
>#         OutputDebugString( ". SERVICE_STOPPED" );
>#       }
>#
>#       return;
>#     }
>#
>#     theServiceStatus.dwCurrentState = SERVICE_RUNNING;
>#
>#     if ( !SetServiceStatus( theServiceStatusHandle, &(theServiceStatus) ) )
>#     {
>#       OutputDebugString( "! SERVICE_RUNNING" );
>#     }
>#     else
>#     {
>#       OutputDebugString( ". SERVICE_RUNNING" );
>#     }
>#
>#     /*
>#     ** wait for notification to stop from the control handler
>#     */
>#     WaitForSingleObject( theEvent, INFINITE );
>#
>#     theServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
>#
>#     if ( !SetServiceStatus( theServiceStatusHandle, &(theServiceStatus) ) )
>#     {
>#       OutputDebugString( "! SERVICE_STOP_PENDING" );
>#     }
>#     else
>#     {
>#       OutputDebugString( ". SERVICE_STOP_PENDING" );
>#     }
>#
>#     /*
>#     ** deref the synchronization object
>#     */
>#     CloseHandle ( theEvent );
>#
>#     theServiceStatus.dwCurrentState = SERVICE_STOPPED;
>#
>#     if ( !SetServiceStatus( theServiceStatusHandle, &(theServiceStatus) ) )
>#     {
>#       OutputDebugString( "! SERVICE_STOPPED" );
>#     }
>#     else
>#     {
>#       OutputDebugString( ". SERVICE_STOPPED" );
>#     }
>#
>#     return;
>#
>#   } // ServiceMain ()
>#
>#   /*
>#   ** the name of this function is arbitrary
>#   */
>#   void ServiceCtrlHandler( uint dwControl )
>#   {
>#     void * theEvent;
>#
>#     switch ( dwControl )
>#     {
>#       case SERVICE_CONTROL_STOP:
>#         OutputDebugString( ". SERVICE_CONTROL_STOP" );
>#
>#         theEvent = OpenEvent( EVENT_MODIFY_STATE, false, theServiceName );
>#         SetEvent( theEvent );
>#         CloseHandle( theEvent );
>#
>#         break;
>#
>#       case SERVICE_CONTROL_PAUSE:
>#         OutputDebugString( ". SERVICE_CONTROL_PAUSE" );
>#         break;
>#
>#       case SERVICE_CONTROL_CONTINUE:
>#         OutputDebugString( ". SERVICE_CONTROL_CONTINUE" );
>#         break;
>#
>#       case SERVICE_CONTROL_PARAMCHANGE:
>#         OutputDebugString( ". SERVICE_CONTROL_PARAMCHANGE" );
>#         break;
>#
>#       case SERVICE_CONTROL_INTERROGATE:
>#         OutputDebugString( ". SERVICE_CONTROL_INTERROGATE" );
>#         break;
>#
>#       case SERVICE_CONTROL_SHUTDOWN:
>#         OutputDebugString( ". SERVICE_CONTROL_SHUTDOWN" );
>#         break;
>#
>#       default:
>#         OutputDebugString( ". ServiceCtrlHandler" );
>#         break;
>#     }
>#
>#     return;
>#
>#   } // ServiceCtrlHandler ()
>#
># } // extern ( Windows )
>
>Hope this helps,
>David L.
>
>-------------------------------------------------------------------
>"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
>-------------------------------------------------------------------
>
>MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html


April 20, 2005
Thanks.

Andrew Fedoniouk says...
>
>I think it make sense to create general purpose NT Service class for D. There are a lot of prototypes, e.g: http://www.codeproject.com/system/VoitelNTService.asp
>
>Andrew.
>
>
>"jicman" <jicman_member@pathlink.com> wrote in message news:d43vcn$1m38$1@digitaldaemon.com...
>>
>> Greetings!
>>
>> I am trying to have a D executable become a service using,
>>
>> http://support.microsoft.com/kb/q137890/
>>
>> as the instructions.  I know the D program, or the executable, is working
>> great,
>> so it shouldn't be a problem.  Does anyone see any problem with this?  Any
>> pointers?  I've never done it, but D has brought up so many new options
>> for me,
>> that it's now easy to create executables and stop using JScript scripts.
>> :-)
>> Thank you Walter.  I don't care what JCC says about you, you're ok in my
>> book.
>> :-)
>>
>> thanks,
>>
>> josé
>>
>> 
>
>


April 20, 2005
David L. Davis wrote:
> In article <d44c2n$210c$1@digitaldaemon.com>, Andrew Fedoniouk says...
> 
>>I think it make sense to create general purpose NT Service class for D.
>>There are a lot of prototypes, e.g:
>>http://www.codeproject.com/system/VoitelNTService.asp
>>
>>Andrew.
>>
> 
> 
> Here's some basic NT service code that Gifford Hesketh (first.last@gmail.com )
> wrote back in May 2004...I can't seem to find his message in forum where this
> code attached, so I'm going to copy in what I downloaded back then. I've never

Not that it really matters, but I managed to find the original post:
http://www.digitalmars.com/d/archives/digitalmars/D/2308.html

> tested it (but still plan to), but I think this would be a good starting place
> for you to start writing your planned general purpose NT Service class in D. :)
> 
> # /*
> # ** service.d -- a skeletal service for Windows
> # **
> # ** Created 2004-May-27 for the public domain # ** by Gifford Hesketh (first.last@gmail.com )

-- 
jcc7
http://jcc_7.tripod.com/d/
April 21, 2005
In article <d46mj7$1g4k$1@digitaldaemon.com>, J C Calvarese says...
>
>David L. Davis wrote:
>> In article <d44c2n$210c$1@digitaldaemon.com>, Andrew Fedoniouk says...
>> 
>>>I think it make sense to create general purpose NT Service class for D. There are a lot of prototypes, e.g: http://www.codeproject.com/system/VoitelNTService.asp
>>>
>>>Andrew.
>>>
>> 
>> 
>> Here's some basic NT service code that Gifford Hesketh (first.last@gmail.com ) wrote back in May 2004...I can't seem to find his message in forum where this code attached, so I'm going to copy in what I downloaded back then. I've never
>
>Not that it really matters, but I managed to find the original post: http://www.digitalmars.com/d/archives/digitalmars/D/2308.html
>
>> tested it (but still plan to), but I think this would be a good starting place for you to start writing your planned general purpose NT Service class in D. :)
>> 
>> # /*
>> # ** service.d -- a skeletal service for Windows
>> # **
>> # ** Created 2004-May-27 for the public domain
>> # ** by Gifford Hesketh (first.last@gmail.com )
>
>-- 
>jcc7
>http://jcc_7.tripod.com/d/

J C Calvarese thanks for finding and posting the link to the original message, which I just had to read over all the messages again. And I see, I still owe you one for placing that zip-file on your website when I couldn't download the file. He! He! At the time I just couldn't get my darn Outlook Express setup correctly... but now of course, all is good! JC thanks again! :)

David L.

-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
-------------------------------------------------------------------

MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html
April 21, 2005
David L. Davis wrote:
> In article <d46mj7$1g4k$1@digitaldaemon.com>, J C Calvarese says...
> 
>>David L. Davis wrote:
>>
>>>In article <d44c2n$210c$1@digitaldaemon.com>, Andrew Fedoniouk says...
>>>
>>>
>>>>I think it make sense to create general purpose NT Service class for D.
>>>>There are a lot of prototypes, e.g:
>>>>http://www.codeproject.com/system/VoitelNTService.asp
>>>>
>>>>Andrew.
>>>>
>>>
>>>
>>>Here's some basic NT service code that Gifford Hesketh (first.last@gmail.com )
>>>wrote back in May 2004...I can't seem to find his message in forum where this
>>>code attached, so I'm going to copy in what I downloaded back then. I've never
>>
>>Not that it really matters, but I managed to find the original post:
>>http://www.digitalmars.com/d/archives/digitalmars/D/2308.html
>>
>>
>>>tested it (but still plan to), but I think this would be a good starting place
>>>for you to start writing your planned general purpose NT Service class in D. :)
>>>
>>># /*
>>># ** service.d -- a skeletal service for Windows
>>># **
>>># ** Created 2004-May-27 for the public domain # ** by Gifford Hesketh (first.last@gmail.com )
>>
>>-- 
>>jcc7
>>http://jcc_7.tripod.com/d/
> 
> 
> J C Calvarese thanks for finding and posting the link to the original message,
> which I just had to read over all the messages again. And I see, I still owe you
> one for placing that zip-file on your website when I couldn't download the file.
> He! He! At the time I just couldn't get my darn Outlook Express setup
> correctly... but now of course, all is good! JC thanks again! :)

LOL. I forgot about all of that. I'm comprehending fewer of these D NG posts every day, but at least I can still search the archives and download the attachments. ;)

I'm glad I could help.

-- 
jcc7
http://jcc_7.tripod.com/d/