Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.
Keywords:
It is possible to create a compiled WinBatch program that will run as a native service on Windows NT family systems. It requires you have the WinBatch+Compiler software package, because the script *MUST* be compiled.
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.). Or use any of the following service functions: SvcSetAccept, SvcSetState, SvcWaitForCmd. You can use loops or branching (For, While, Goto, etc.) to cause the WinBatch service to continue running for an indefinite period of time.
Windows NT native service '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 preceeding 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
Since you compiled using the Small EXE option, you should copy the necessary dlls: WIL dll and any Extender dlls used by the service script, to the same directory as the service (.EXS) file.
A WinBatch service can be configured 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.
Windows NT native service install code (INSTALL_SVC.WBT):
#DefineFunction InstallSvc(SvcKeyName, SvcStringValues, SvcNumValues) ;Parameters: ;[SvcKeyName] ;The actual registry key name of the service to be looked for ; ;[SvcStringValues] ;Is a is a tab-delimited or vertical-bar ('|') delimited list of string properties for the service being created, ;in the following format: "ServiceName | DisplayName | BinaryPathName | LoadOrderGroup | ServiceStartName | Password" ; ServiceName: ; String that specifies the name of the service to install. The maximum string length is 256 characters. The service control ; manager database preserves the case of the characters, but service name comparisons are always case insensitive. Forward-slash ; (/) and back-slash (\) are invalid service name characters. ; ; DisplayName: ; String that is to be used by user interface programs to identify the service. This string has a maximum length of 256 ; characters. The name is case-preserved in the service control manager. Display name comparisons are always case-insensitive. ; ; BinaryPathName: ; The fully qualified path to the service binary file. ; ; LoadOrderGroup: ; The load ordering group of which this service is a member. If a blank string, the service does not belong to a group. ; The registry has a list of load ordering groups located at: ; HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ServiceGroupOrder ; The startup program uses this list to load groups of services in a specified order with respect to the other groups in the list. ; You can place a service in a group so that another service can depend on the group. The order in which a service starts is ; determined by the following criteria: ; 1. The order of groups in the registry's load-ordering group list. Services in groups in the load-ordering group list are ; started first, followed by services in groups not in the load-ordering group list and then services that do not belong to a group. ; 2. The service's dependencies listed in the "Dependencies" parameter and the dependencies of other services dependent on the service. ; ; ServiceStartName: ; If the service type is SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS, this name is the account name in the form of ; "DomainName\Username", which the service process will be logged on as when it runs. If the account belongs to the built-in ; domain, ".\Username" can be specified. To log on as the LocalSystem account, specify "LocalSystem". If the service type is ; SERVICE_KERNEL_DRIVER or SERVICE_FILE_SYSTEM_DRIVER, this name is the Windows NT driver object name (that is, \FileSystem\Rdr ; or \Driver\Xns) which the input and output (I/O) system uses to load the device driver. You can specify both a ServiceStartName ; and a Password together, in the form "ServiceStartName|Password". If ServiceStartName does not contain a '\', then '.\' will ; automatically be prepended, unless ServiceStartName == "LocalSystem". ; ; Password: ; Password to the account name specified by the "ServiceStartName" parameter if the service type is SERVICE_WIN32_OWN_PROCESS ; or SERVICE_WIN32_SHARE_PROCESS. If the service type is SERVICE_KERNEL_DRIVER or SERVICE_FILE_SYSTEM_DRIVER, this parameter ; is ignored. ; ;[SvcNumValues] ;A tab-delimited or vertical-bar ('|') delimited list of numeric properties for the service being created, in the ;following format:"ServiceType | StartType | ErrorControl" ; ServiceType: ; Service type are the flags to indicate the type of service. In addition, for a SERVICE_WIN32 service, the SERVICE_INTERACTIVE_PROCESS ; flag might be set, indicating that the service process can interact with the desktop: ; Value Name ; 1 SERVICE_KERNEL_DRIVER ; 2 SERVICE_FILE_SYSTEM_DRIVER ; 16 SERVICE_WIN32_OWN_PROCESS ; 32 SERVICE_WIN32_SHARE_PROCESS ; In addition to the SERVICE_WIN32 service, the SERVICE_INTERACTIVE_PROCESS flag may be set, indicating that the service process can ; interact with the desktop: Note: ServiceStartName must be LocalSystem in order to interact with the desktop. ; 256 SERVICE_INTERACTIVE_PROCESS ; ; StartType: ; Specifies when to start the service. One of the following values is specified: ; Value Name ; 0 SERVICE_BOOT_START ; 1 SERVICE_SYSTEM_START ; 2 SERVICE_AUTO_START ; 3 SERVICE_DEMAND_START ; 4 SERVICE_DISABLED ; ; ErrorControl: ; Specifies the severity of the error if this service fails to start during startup, and determines the action taken by the startup ; program if failure occurs. One of the following values can be specified: ; Value Name ; 0 SERVICE_ERROR_IGNORE ; 1 SERVICE_ERROR_NORMAL ; 2 SERVICE_ERROR_SEVERE ; 3 SERVICE_ERROR_CRITICAL IntControl(72,2,0,0,0) bExists = wntSvcStatus('',SvcKeyName,1000,0) If bExists wntSvcDelete( "", SvcKeyName, 1000) EndIf ErrorMode(@OFF) wntSvcCreate('',SvcStringValues,SvcNumValues,'','') RC = LastError() ErrorMode(@CANCEL) If (RC != 0) TempMsg = StrCat('wntSvcCreate("","',SvcStringValues,'",',SvcNumValues,',"","") RC = ',RC) TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error! Unable to create the service. Aborting service installation...') Message("ERROR",TempMsg) Return EndIf Return :CANCEL IntControl(72,2,0,0,0) Return #EndFunction AddExtender("wwwnt34i.dll") SvcKeyName="My Service Name" DisplayName="My Service Display Name" types="EXS Files|*.EXS" BinaryPathName=AskFilename("Select Compiled Service Script", "C:\", types, "", 1) LoadOrderGroup="" ServiceStartName="LocalSystem" Password="" ;CONSTANTS SERVICE_WIN32_OWN_PROCESS = 16 SERVICE_INTERACTIVE_PROCESS = 256 SERVICE_AUTO_START = 2 SERVICE_ERROR_NORMAL = 1 SvcStringValues = StrCat(SvcKeyName,"|",DisplayName,"|",BinaryPathName,"|",LoadOrderGroup,"|",ServiceStartName,"|",Password) SvcNumValues = StrCat(SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,@TAB,SERVICE_AUTO_START,@TAB,SERVICE_ERROR_NORMAL) InstallSvc(SvcKeyName, SvcStringValues, SvcNumValues) Message("Complete",StrCat("Installed service: ",SvcKeyName))
Windows NT native service Uninstall code (UNINSTALL_SVC.WBT):
#DefineFunction UnInstallSvc(SvcKeyName) ;Parameters: ;[SvcKeyName] ;The actual registry key name of the service to be looked for IntControl(72,2,0,0,0) bExists = wntSvcStatus('',SvcKeyName,1000,0) If bExists ErrorMode(@OFF) wntSvcDelete( "", SvcKeyName, 1000) RC = LastError() ErrorMode(@CANCEL) If (RC != 0) TempMsg = StrCat('wntSvcDelete("","',SvcKeyName,'",1000) RC = ',RC) TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error! Unable to delete the service. Aborting service deletion...') Message("Error",TempMsg) Return EndIf EndIf Return :CANCEL IntControl(72,2,0,0,0) Return #EndFunction AddExtender("wwwnt34i.dll") SvcKeyName="My Service Name" UnInstallSvc(SvcKeyName) Message("Service Uninstall Complete",StrCat("Service: ",SvcKeyName, " is no longer installed"))
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 Stopping the service manually 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. WinBatch services do not exit when a user logs out.
Sample Code to Start a Service (START_SVC.WBT)
;Starting a service AddExtender("wwwnt34i.dll") SvcKeyName="My Service Name" SERVICE_RUNNING = 4 state = wntSvcStatus('', SvcKeyName, 1000, 2) ;get service status If state != SERVICE_RUNNING wntSvcStart('', SvcKeyName, 1000, "", "") ;start service EndIf While state != SERVICE_RUNNING ;loop until service starts again. TimeDelay(1) ErrorMode(@OFF) wntSvcControl('', SvcKeyName, 1000, 4) ;update status in servicemanager ErrorMode(@CANCEL) state = wntSvcStatus('', SvcKeyName, 1000, 2) ;get service status EndWhile Pause(SvcKeyName,"Service should be started now") Exit
Sample Code to Stop a Service (STOP_SVC.WBT)
;Stopping a service AddExtender("wwwnt34i.dll") SvcKeyName="My Service Name" SERVICE_STOPPED = 1 state = wntSvcStatus('', SvcKeyName, 1000, 2) ;get service status If state != SERVICE_STOPPED wntSvcControl('', SvcKeyName, 1000, 1) ;stop service EndIf While state != SERVICE_STOPPED ;loop until service is reported as stopped. TimeDelay(1) ErrorMode(@OFF) wntSvcControl('', SvcKeyName, 1000, 4) ;update status in servicemanager ErrorMode(@CANCEL) state = wntSvcStatus('', SvcKeyName, 1000, 2) ;get service status EndWhile Pause(SvcKeyName, "Service should be stopped now") Exit
If you are making a WinBatch service that will NOT be installed as an interactive service, you should use IntControl(38) 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.
The DebugTrace function is very useful when debugging service scripts. See the Windows Interfance Language Help file for details.
Article ID: W17357
File Created: 2013:04:04:10:21:46
Last Updated: 2013:04:04:10:21:46