Service Script

 

It is possible to create a compiled WinBatch program that will run as a native service. To do this, compile the WinBatch script as usual using the 'Small EXE for Networked PC's' option in the WinBatch Compiler, but make sure to specify an output file with an extension of ".EXS" instead of ".EXE". Alternatively, you can simply rename an existing WinBatch program (version 2001 and higher) by changing its extension from ".EXE" to ".EXS".

 

You can install a WinBatch service (or any service) using the wntSvcCreate function in the WIL Windows NT extender (see the Win32 Network Extender help file).

 

A WinBatch service can be configured in the Service Manager (in Control Panel) to run automatically on system startup, or manually on demand.

 

In either case, when the WinBatch service starts up it processes the script just like a normal WinBatch program.

 

If you want the WinBatch service to wait for a particular time or event to occur, you can use any of the normal WIL methods (TimeDelay, TimeWait, WinWaitExist, etc.). You can also use any of the following service functions: SvcSetAccept, SvcSetState, SvcWaitForCmd.

 

You can also use loops or branching (For, While, Goto, etc.) to cause the WinBatch service to continue running for an indefinite period of time. When processing reaches the end of the script (or a Return or Exit command, or a Cancel event), the WinBatch service will automatically stop. You can force a WinBatch service to stop prematurely by using the "Stop" function in the Service Manager (in Control Panel), or using another service control program (such as the wntSvcControl function in the WIL Windows NT extender). A WinBatch service will exit automatically on Windows shutdown.

 

If you are making a WinBatch service that will not be installed as an interactive service, you should use IntControl(38) at the beginning of the script to prevent WIL from displaying any unexpected error message boxes. If a non-interactive service attempts to interact with the desktop, it can cause the script to hang.

 

Notes:

Pre-Vista versions of Windows

  • A service that is running under the LocalSystem account cannot access network resources.

  • To have a service access the desktop, that service must log on as the LocalSystem account, and be allowed to interact with the desktop.

Vista and newer

  • Services cannot directly interact with a user.

 

WinBatch+Compiler

 

Large EXE for Standalone PC's

Small EXE for Networked PC's

Encode for Call's from EXE files

Encrypted with Password

 Windows NT native service

 

Service Functions:

SvcSetAccept

SvcSetState

SvcWaitForCmd.

 

 

 

Sample service script template

;Initialze variables for the SvcSetAccept function
SERVICE_ACCEPT_STOP             =   1    ;The service can be stopped
SERVICE_ACCEPT_PAUSE_CONTINUE   =   2    ;The service can be paused and continued
SERVICE_ACCEPT_SHUTDOWN         =   4    ;The service is notified when system shutdown occurs
SERVICE_ACCEPT_HARDWAREPRFCHG   =   3    ;The computer's hardware profile has changed.
SERVICE_ACCEPT_POWEREVENT       =   64   ;The computer's power status has changed.
SERVICE_ACCEPT_SESSIONCHANGE    =   128  ;The computer's session status has changed (requires XP/2003 or newer.)
SERVICE_ACCEPT_PRESHUTDOWN      =   256  ;The computer is about to shutdown (requires Vista/2008 or newer.)
SERVICE_ACCEPT_LOGOFF           =   32768;The service is notified when user logoff occurs
;Initialize variables for the SvcSetState function
SERVICE_STATE_STOPPED           =   1   ;The service is not running
SERVICE_STATE_STOP_PENDING      =   3   ;The service is stopping
SERVICE_STATE_RUNNING           =   4   ;The service is running
SERVICE_STATE_CONTIN_PENDING  =   5   ;The service continue is pending
SERVICE_STATE_PAUSE_PENDING     =   6   ;The service pause is pending
SERVICE_STATE_PAUSED            =   7   ;The service is paused
;Initialize variables for the SvcWaitForCmd function
SERVICE_CONTROL_NOT_SERVICE     =  -1   ;Script not running as a service
SERVICE_CONTROL_TIMEOUT         =   0   ;Timeout occurred or no codes to process
SERVICE_CONTROL_STOP            =   1   ;Requests the service to stop
SERVICE_CONTROL_PAUSE           =   2   ;Requests the service to pause
SERVICE_CONTROL_CONTINUE        =   3   ;Requests the paused service to resume
SERVICE_CONTROL_SHUTDOWN        =   5   ;Requests the service to perform cleanup tasks, because the system is shutting down
SERVICE_CONTROL_HARDWAREPRFCHG  =   12  ;The computer's hardware profile has changed.
SERVICE_CONTROL_POWEREVENT      =   13  ;The power status has changed.
SERVICE_CONTROL_SESSIONCHANGE   =   14  ;The session status has changed (requires XP/2003 or newer.)
SERVICE_CONTROL_PRESHUTDOWN     =   15  ;The system will be shutting down (requires Vista/2008 or newer.)
SERVICE_CONTROL_USER128         = 128   ;User command 128
SERVICE_CONTROL_USER129         = 129   ;User command 129
SERVICE_CONTROL_USER130         = 130   ;User command 130
SERVICE_CONTROL_USER131         = 131   ;User command 131
;                                       ;More user commands as needed
SERVICE_CONTROL_USER255         = 255   ;User command 255
SERVICE_CONTROL_LOGOFF          = 32768 ;logoff notification
;Setup debugging prompt strings....
debugcodes="0: Timeout|1: Stop|2: Pause|3: Continue|5: Shutdown|128: User Cmd 128|129:User Cmd 129|32768: Logoff"
;Tell system that we want specific notifications
flag=SvcSetAccept( SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_LOGOFF)
If flag== -1
   DoingDebug=@TRUE
   Pause("Debug Mode","Not currently running as a service")
Else
   DoingDebug=@FALSE
   ;Set up error handling
   IntControl(12,2+8,0,0,0)                    ;Tell WinBatch to not honor terminate and
                                               ;not complain on Windows exit
   IntControl(38,1,"errorlog.txt",0,0) ;Route fatal errors to a log file
EndIf
;Now for the main service loop
;in this service we respond to all control messages
;and check an ini file for work every 5 seconds
BoxOpen("Initializing","main service loop")
While @TRUE
   If DoingDebug==@FALSE
      code=SvcWaitForCmd(5000)      ; Timeout in 5 seconds
   Else
       ;For Debugging.  Prompt tester to see what code should be pretended here
       code=AskItemlist("Service Debug",debugcodes,"|",@UNSORTED,@SINGLE)
       If code=="" Then Continue
       code=ItemExtract(1,code,":")
   EndIf
   Switch code
          Case SERVICE_CONTROL_TIMEOUT
               ;Timeout occurred
               BoxTitle("SERVICE_CONTROL_TIMEOUT")
               ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
               GoSub DoWork
               ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
               Break
          Case SERVICE_CONTROL_STOP
               ;Stop command received
               BoxText("Stop command received")
               SvcSetState(SERVICE_STATE_STOP_PENDING)
               ;do stop cleanup work here
               TimeDelay(5)
               SvcSetState(SERVICE_STATE_STOPPED)
               Exit    ;Goodbye
               Break
          Case SERVICE_CONTROL_PAUSE
               ;Pause command received
               BoxText("Pause command received")
               SvcSetState(SERVICE_STATE_PAUSE_PENDING)
               ;do pause cleanup work here
               SvcSetState(SERVICE_STATE_PAUSED)
               Break
          Case SERVICE_CONTROL_CONTINUE
               ;Continue command received
               BoxText("Continue command received")
               SvcSetState(SERVICE_STATE_CONTIN_PENDING)
               ;do resume from pause state initilization here
               SvcSetState(SERVICE_STATE_RUNNING)
               Break
          Case SERVICE_CONTROL_SHUTDOWN
               ;Shutdown notification received
               ;Approx. 20 seconds to process
               BoxText("Shutdown notification received")
               SvcSetState(SERVICE_STATE_STOP_PENDING)
               ;do stop cleanup work here
               SvcSetState(SERVICE_STATE_STOPPED)
               Exit    ;Goodbye
               Break
          Case SERVICE_CONTROL_USER128
               ;User command 128 received
               BoxText("User command 128 received")
               Break
          Case SERVICE_CONTROL_USER129
               ;User command 129 received
               BoxText("User command 129 received")
               Break
          Case SERVICE_CONTROL_LOGOFF
               ;Logoff command received
               BoxText("Logoff command received")
               Break
         Case code
               ;Unrecognized command received
               BoxText("Unrecognized command received")
               Break
      EndSwitch
EndWhile
;Note.  The preceding loop never exits
Exit   ; Just a formality
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;The DoWork subroutine can be used to execute the code you want to run while
;the service has not control requests
:DoWork
   BoxText("WinBatch Services test is running")
Return