WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Run Winbatch as a Service

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

A NT Service Template Script - For Experts


; ServiceTest.wbt
;
; REQUIRES: WINBATCH 2005B OR NEWER
;
; This script simply runs as a service and displays its configuration information
; in a message box.  Multiple services instances can be configured.  All supported 
; run-time parameters are obtained from the registry and/or the command line parameters
;
; This script is designed to run both as a service and as an interactive program.  When run
; as a service, it simply does its normal work as configured.  When run as an interactive
; application, it presents a dialog box providing configuration options, including options
; to install or remove the service control manager database entry for the ServiceTest
; service.
;
; This script should be compiled as a Small EXE script.  All run-time DLLs and extender
; DLLs should be manually copied into the same directory as the compiled .EXE file.  The
; .EXE file should also be copied to a .EXS extension so that it can be run as a native
; NT service.  The "run script hidden" option should be selected when compiling this
; script.
;
; The Win32 NT Network Extender is used by this script.
;
; Although this script doesn't do anything even remotely useful by any direction action
; that it takes, it does serve as a template for quickly developing WinBatch scripts that
; are intended to run as native NT services.  Feel free to canibalize it as necessary for
; use in other projects.
;
;


#DEFINEFUNCTION LogMsg(hLogFile,LogMsgText)

if (hLogFile != 0)
  FileWrite(hLogFile,StrCat(TimeYmdHms(),' ',LogMsgText))
endif


return
#ENDFUNCTION


; Declare the subroutine that processes our main dialog box.
;
; Also declare other constant values that are important for dialog processing...

BUTTON_CLOSE = 1
BUTTON_APPLY = 2
BUTTON_STARTSERVICE = 3
BUTTON_STOPSERVICE = 4
BUTTON_INSTALLSERVICE = 5
BUTTON_REMOVESERVICE = 6

EDITBOX_CMDLINE = 7
EDITBOX_REGPARAM1 = 8
EDITBOX_REGPARAM2 = 9
EDITBOX_REGPARAM3 = 10
EDITBOX_DESCRIPTION = 11

SPINNER_INSTANCE = 12

VARYTEXT_STATUS = 13

PROCOPT_INITIALIZE = 0
PROCOPT_BUTTON_PUSH = 2
PROCOPT_EDITBOX_CHANGE = 5
PROCOPT_SPINNER_CHANGE = 10
PROCOPT_TIMER_EVENT = 1

#DEFINESUBROUTINE MainDlgProc(DialogHandle, EventCode, ControlNum, Res4, Res5)
IntControl(72,2,0,0,0)
switch (EventCode)

  case PROCOPT_INITIALIZE
    DialogProcOptions(DialogHandle, PROCOPT_BUTTON_PUSH, 1)
    DialogProcOptions(DialogHandle, PROCOPT_EDITBOX_CHANGE, 1)
    DialogProcOptions(DialogHandle, PROCOPT_SPINNER_CHANGE, 1)
    DialogProcOptions(DialogHandle, PROCOPT_TIMER_EVENT, 1000)
    DialogControlState(DialogHandle, BUTTON_APPLY, 3, 2)
    DialogControlSet(DialogHandle, BUTTON_CLOSE, 4, '&Close')
    gosub SetFieldValues
    gosub UpdateSvcStatus
    bDirty = @FALSE

    break

  case PROCOPT_TIMER_EVENT
    gosub UpdateSvcStatus

    break

  case PROCOPT_EDITBOX_CHANGE
    DialogControlState(DialogHandle, BUTTON_APPLY, 4, 2)
    DialogControlSet(DialogHandle, BUTTON_CLOSE, 4, '&Cancel')
    bDirty = @TRUE

    break

  case PROCOPT_SPINNER_CHANGE
    TempSvcInstanceNum = Int(DialogControlGet(DialogHandle,SPINNER_INSTANCE,8))
    SvcInstanceStr = StrFixLeft(SvcInstanceNum,'0',2)
    if (TempSvcInstanceNum < 1)
      DialogControlSet(DialogHandle,SPINNER_INSTANCE,8,1)
    else
      if (TempSvcInstanceNum > 99)
        DialogControlSet(DialogHandle,SPINNER_INSTANCE,8,99)
      else
        if (bDirty)
          TempAnswer = AskYesNo(Title01,StrCat('Apply unsaved changes to service instance #',SvcInstanceNum,'?'))
          if (TempAnswer)
            gosub ApplyChanges
          else
          endif
        endif
        SvcInstanceNum = TempSvcInstanceNum
        SvcInstanceStr = StrFixLeft(SvcInstanceNum,'0',2)
        BuildSvcInstanceInfo()
        ConfigGet(@TRUE)
        gosub SetFieldValues
        DialogControlState(DialogHandle, BUTTON_APPLY, 3, 2)
        DialogControlSet(DialogHandle, BUTTON_CLOSE, 4, '&Close')
        bDirty = @FALSE
        gosub UpdateSvcStatus
      endif
    endif

    break

  case PROCOPT_BUTTON_PUSH

    if  (ControlNum == BUTTON_CLOSE)
      return -1
    endif

    gosub GetFieldValues

    if (ControlNum == BUTTON_APPLY)
      gosub ApplyChanges
      gosub UpdateSvcStatus
      return -2
    endif

    if (ControlNum == BUTTON_INSTALLSERVICE)
      DialogProcOptions(DialogHandle, 1000, 2) ; Put dialog into busy state...
      InstallSvc()
      gosub ApplyChanges
      DialogProcOptions(DialogHandle, 1000, 0) ; Restore dialog to active state...
      gosub UpdateSvcStatus
      return -2 ; Don't terminate the dialog
    endif

    if  (ControlNum == BUTTON_REMOVESERVICE)
      DialogProcOptions(DialogHandle, 1000, 2) ; Put dialog into busy state...
      RemoveSvc()
      DialogProcOptions(DialogHandle, 1000, 0) ; Restore dialog to active state...
      gosub UpdateSvcStatus
      return -2 ; Don't terminate the dialog
    endif

    if  (ControlNum == BUTTON_STARTSERVICE)
      DialogProcOptions(DialogHandle, 1000, 2) ; Put dialog into busy state...
      StartSvc()
      DialogProcOptions(DialogHandle, 1000, 0) ; Restore dialog to active state...
      gosub UpdateSvcStatus
      return -2 ; Don't terminate the dialog
    endif

    if  (ControlNum == BUTTON_STOPSERVICE)
      DialogProcOptions(DialogHandle, 1000, 2) ; Put dialog into busy state...
      StopSvc()
      DialogProcOptions(DialogHandle, 1000, 0) ; Restore dialog to active state...
      gosub UpdateSvcStatus
      return -2 ; Don't terminate the dialog
    endif

    break
endswitch

return -1

:Cancel

IntControl(72,2,0,0,0)

return

:ApplyChanges

DialogProcOptions(DialogHandle, 1000, 2) ; Put dialog into busy state...
ConfigSet()
DialogProcOptions(DialogHandle, 1000, 0) ; Restore dialog to active state...
DialogControlState(DialogHandle, BUTTON_APPLY, 3, 2)
DialogControlSet(DialogHandle, BUTTON_CLOSE, 4, '&Close')
bDirty = @FALSE

return

:GetFieldValues

CmdLine = DialogControlGet(DialogHandle,EDITBOX_CMDLINE,3)
RegParam1 = DialogControlGet(DialogHandle,EDITBOX_REGPARAM1,3)
RegParam2 = DialogControlGet(DialogHandle,EDITBOX_REGPARAM2,3)
RegParam3 = DialogControlGet(DialogHandle,EDITBOX_REGPARAM3,3)
SvcDescription = DialogControlGet(DialogHandle,EDITBOX_DESCRIPTION,3)

return

:SetFieldValues

DialogControlSet(DialogHandle,EDITBOX_CMDLINE,3,CmdLine)
DialogControlSet(DialogHandle,EDITBOX_REGPARAM1,3,RegParam1)
DialogControlSet(DialogHandle,EDITBOX_REGPARAM2,3,RegParam2)
DialogControlSet(DialogHandle,EDITBOX_REGPARAM3,3,RegParam3)
DialogControlSet(DialogHandle,EDITBOX_DESCRIPTION,3,SvcDescription)

return

:UpdateSvcStatus

bExists = wntSvcStatus('',SvcKeyName,1000,0)

if (bExists)
  TempMsg = 'Exists'

  ErrorMode(@OFF)
  SvcStatus = wntSvcStatus('',SvcKeyName,1000,2)
  RC = LastError()
  ErrorMode(@CANCEL)

  if (RC == 0)
    switch SvcStatus
      case 1
        TempMsg = StrCat(TempMsg,', Stopped')
        break
      case 3
        TempMsg = StrCat(TempMsg,', Stop Pending')
        break
      case 4
        TempMsg = StrCat(TempMsg,', Running')
        break
      case 5
        TempMsg = StrCat(TempMsg,', Continue Pending')
        break
      case 6
        TempMsg = StrCat(TempMsg,', Pause Pending')
        break
      case 7
        TempMsg = StrCat(TempMsg,', Paused')
        break
      case SvcStatus
        TempMsg = StrCat(TempMsg,', Unknown Status = "',SvcStatus,'"')
    endswitch
  endif
else
  TempMsg = 'Does not exist'
endif

DialogControlSet(DialogHandle, VARYTEXT_STATUS, 4, TempMsg)

return
#ENDSUBROUTINE



; Define the subroutine that gets config settings.

#DEFINESUBROUTINE ConfigGet(bInteractive)
IntControl(72,2,0,0,0)

if (RegExistValue(@REGMACHINE,StrCat(RegBase,'\Parameters[RegParam1]')))
  RegParam1 = RegQueryValue(@REGMACHINE,StrCat(RegBase,'\Parameters[RegParam1]'))
else
  if (bInteractive)
    RegParam1 = ''
  else
    TempMsg = StrCat('Error!  RegParam1 parameter is undefined.  Aborting...')
    LogMsg(hLogFile,TempMsg)
    IntControl(1000,ERR_CONFIG_PARAM_UNDEFINED,0,0,0)
    exit
  endif
endif

if (RegExistValue(@REGMACHINE,StrCat(RegBase,'\Parameters[RegParam2]')))
  RegParam2 = RegQueryValue(@REGMACHINE,StrCat(RegBase,'\Parameters[RegParam2]'))
else
  if (bInteractive)
    RegParam2 = ''
  else
    TempMsg = StrCat('Error!  RegParam2 parameter is undefined.  Aborting...')
    LogMsg(hLogFile,TempMsg)
    IntControl(1000,ERR_CONFIG_PARAM_UNDEFINED,0,0,0)
    exit
  endif
endif

if (RegExistValue(@REGMACHINE,StrCat(RegBase,'\Parameters[RegParam3]')))
  RegParam3 = RegQueryValue(@REGMACHINE,StrCat(RegBase,'\Parameters[RegParam3]'))
else
  if (bInteractive)
    RegParam3 = ''
  else
    TempMsg = StrCat('Error!  RegParam3 parameter is undefined.  Aborting...')
    LogMsg(hLogFile,TempMsg)
    IntControl(1000,ERR_CONFIG_PARAM_UNDEFINED,0,0,0)
    exit
  endif
endif


bExists = wntSvcStatus('',SvcKeyName,1000,0)

if (bExists)
  ErrorMode(@OFF)
  SvcDescription = wntSvcCfgGet('',SvcKeyName,1000,10)
  RC = LastError()
  ErrorMode(@CANCEL)
  if (RC != 0)
    SvcDescription = ''
  endif

  ErrorMode(@OFF)
  CmdLine = wntSvcCfgGet('',SvcKeyName,1000,3)
  TempPos = StrIndexNc(SvcBinSpec,StrSub(CmdLine,1,StrLen(SvcBinSpec)),0,@FWDSCAN)
  if (TempPos != 0)
    CmdLine = StrSub(CmdLine,StrLen(SvcBinSpec)+2,-1)
  else
    TempPos = StrIndexNc(FileNameShort(SvcBinSpec),StrSub(CmdLine,1,StrLen(FileNameShort(SvcBinSpec))),0,@FWDSCAN)
    if (TempPos != 0)
      CmdLine = StrSub(CmdLine,StrLen(FileNameShort(SvcBinSpec))+2,-1)
    else
      TempMsg = StrCat('Error!  Unable to obtain command line parameters.  Aborting...')
      Message(Title01,TempMsg)
      IntControl(1000,ERR_CMDLINE_PARAM_FAULT,0,0,0)
      exit
    endif
  endif
else
  SvcDescription = ''
  CmdLine = ''
endif


return

:Cancel

IntControl(72,2,0,0,0)

return
#ENDSUBROUTINE



; Get some global configuration parameters

#DEFINESUBROUTINE GlobalConfigGet()
IntControl(72,2,0,0,0)

if (RegExistValue(@REGMACHINE,StrCat(RegBase,'\Parameters[Debug]')))
  bDebug = RegQueryDWord(@REGMACHINE,StrCat(RegBase,'\Parameters[Debug]'))
else
  bDebug = @FALSE
  RegSetDWord(@REGMACHINE,StrCat(RegBase,'\Parameters[Debug]'),bDebug)
endif

if (RegExistValue(@REGMACHINE,StrCat(RegBase,'\Parameters[DebugTrace]')))
  bDebugTrace = RegQueryDWord(@REGMACHINE,StrCat(RegBase,'\Parameters[DebugTrace]'))
else
  bDebugTrace = @FALSE
  RegSetDWord(@REGMACHINE,StrCat(RegBase,'\Parameters[DebugTrace]'),bDebugTrace)
endif

if (RegExistValue(@REGMACHINE,StrCat(RegBase,'\Parameters[TraceFileSpec]')))
  TraceFileSpec = RegQueryValue(@REGMACHINE,StrCat(RegBase,'\Parameters[TraceFileSpec]'))
else
  TraceFileSpec = DefTraceFileSpec
  RegSetValue(@REGMACHINE,StrCat(RegBase,'\Parameters[TraceFileSpec]'),TraceFileSpec)
endif

if (RegExistValue(@REGMACHINE,StrCat(RegBase,'\Parameters[Log]')))
  bLog = RegQueryDWord(@REGMACHINE,StrCat(RegBase,'\Parameters[Log]'))
else
  bLog = @FALSE
  RegSetDWord(@REGMACHINE,StrCat(RegBase,'\Parameters[Log]'),bLog)
endif

if (RegExistValue(@REGMACHINE,StrCat(RegBase,'\Parameters[LogFileSpec]')))
  LogFileSpec = RegQueryValue(@REGMACHINE,StrCat(RegBase,'\Parameters[LogFileSpec]'))
else
  LogFileSpec = DefLogFileSpec
  RegSetValue(@REGMACHINE,StrCat(RegBase,'\Parameters[LogFileSpec]'),LogFileSpec)
endif

return

:Cancel

IntControl(72,2,0,0,0)

return
#ENDSUBROUTINE



; Define the subroutine that sets config settings.

#DEFINESUBROUTINE ConfigSet()
IntControl(72,2,0,0,0)

bExists = wntSvcStatus('',SvcKeyName,1000,0)

if (bExists)
  RegSetValue(@REGMACHINE,StrCat(RegBase,'\Parameters[RegParam1]'),RegParam1)
  RegSetValue(@REGMACHINE,StrCat(RegBase,'\Parameters[RegParam2]'),RegParam2)
  RegSetValue(@REGMACHINE,StrCat(RegBase,'\Parameters[RegParam3]'),RegParam3)
  ErrorMode(@OFF)
  wntSvcCfgSet('',SvcKeyName,1000,10,SvcDescription)
  RC = LastError()
  if (CmdLine != '')
    wntSvcCfgSet('',SvcKeyName,1000,3,StrCat(SvcBinSpec,' ',CmdLine))
  else
    wntSvcCfgSet('',SvcKeyName,1000,3,SvcBinSpec)
  endif
  RC = LastError()
  ErrorMode(@CANCEL)
endif

return

:Cancel

IntControl(72,2,0,0,0)

return
#ENDSUBROUTINE



; Install the service

#DEFINESUBROUTINE InstallSvc()
IntControl(72,2,0,0,0)

bExists = wntSvcStatus('',SvcKeyName,1000,0)

if (!bExists)
  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(Title01,TempMsg)
    return
  endif
endif

ErrorMode(@OFF)
wntSvcCfgSet('',SvcKeyName,1000,0,SvcType)
RC = LastError()
ErrorMode(@CANCEL)

if (RC != 0)
  TempMsg = StrCat('wntSvcCfgSet("","',SvcKeyName,'",1000,',0,',',SvcType,')  RC = ',RC)
  TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error!  Unable to configure the service.  Aborting service installation...')
  Message(Title01,TempMsg)
  return
endif

ErrorMode(@OFF)
wntSvcCfgSet('',SvcKeyName,1000,1,SvcStart)
RC = LastError()
ErrorMode(@CANCEL)

if (RC != 0)
  TempMsg = StrCat('wntSvcCfgSet("","',SvcKeyName,'",1000,',1,',',SvcStart,')  RC = ',RC)
  TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error!  Unable to configure the service.  Aborting service installation...')
  Message(Title01,TempMsg)
  return
endif

ErrorMode(@OFF)
wntSvcCfgSet('',SvcKeyName,1000,2,SvcErrCtrl)
RC = LastError()
ErrorMode(@CANCEL)

if (RC != 0)
  TempMsg = StrCat('wntSvcCfgSet("","',SvcKeyName,'",1000,',2,',',SvcErrCtrl,')  RC = ',RC)
  TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error!  Unable to configure the service.  Aborting service installation...')
  Message(Title01,TempMsg)
  return
endif

ErrorMode(@OFF)
if (CmdLine != '')
  wntSvcCfgSet('',SvcKeyName,1000,3,StrCat(SvcBinSpec,' ',CmdLine))
else
  wntSvcCfgSet('',SvcKeyName,1000,3,SvcBinSpec)
endif
RC = LastError()
ErrorMode(@CANCEL)

if (RC != 0)
  if (CmdLine != '')
    TempMsg = StrCat('wntSvcCfgSet("","',SvcKeyName,'",1000,',3,',"',SvcBinSpec,' ',CmdLine,'")  RC = ',RC)
  else
    TempMsg = StrCat('wntSvcCfgSet("","',SvcKeyName,'",1000,',3,',"',SvcBinSpec,'")  RC = ',RC)
  endif
  TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error!  Unable to configure the service.  Aborting service installation...')
  Message(Title01,TempMsg)
  return
endif

ErrorMode(@OFF)
wntSvcCfgSet('',SvcKeyName,1000,4,SvcLoadOrderGroup)
RC = LastError()
ErrorMode(@CANCEL)

if (RC != 0)
  TempMsg = StrCat('wntSvcCfgSet("","',SvcKeyName,'",1000,',4,',"',SvcLoadOrderGroup,'")  RC = ',RC)
  TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error!  Unable to configure the service.  Aborting service installation...')
  Message(Title01,TempMsg)
  return
endif

ErrorMode(@OFF)
wntSvcCfgSet('',SvcKeyName,1000,6,SvcDependsOn)
RC = LastError()
ErrorMode(@CANCEL)

if (RC != 0)
  TempMsg = StrCat('wntSvcCfgSet("","',SvcKeyName,'",1000,',6,',"',SvcDependsOn,'")  RC = ',RC)
  TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error!  Unable to configure the service.  Aborting service installation...')
  Message(Title01,TempMsg)
  return
endif

ErrorMode(@OFF)
wntSvcCfgSet('',SvcKeyName,1000,7,SvcStartName)
RC = LastError()
ErrorMode(@CANCEL)

if (RC != 0)
  TempMsg = StrCat('wntSvcCfgSet("","',SvcKeyName,'",1000,',7,',"',SvcStartName,'")  RC = ',RC)
  TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error!  Unable to configure the service.  Aborting service installation...')
  Message(Title01,TempMsg)
  return
endif

ErrorMode(@OFF)
wntSvcCfgSet('',SvcKeyName,1000,9,SvcDisplayName)
RC = LastError()
ErrorMode(@CANCEL)

if (RC != 0)
  TempMsg = StrCat('wntSvcCfgSet("","',SvcKeyName,'",1000,',9,',"',SvcDisplayName,'")  RC = ',RC)
  TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error!  Unable to configure the service.  Aborting service installation...')
  Message(Title01,TempMsg)
  return
endif

ErrorMode(@OFF)
wntSvcCfgSet('',SvcKeyName,1000,14,SvcRecoveryOptions)
RC = LastError()
ErrorMode(@CANCEL)

if (RC != 0)
  TempMsg = StrCat('wntSvcCfgSet("","',SvcKeyName,'",1000,',14,',"',SvcRecoveryOptions,'")  RC = ',RC)
  TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Error!  Unable to configure the service.  Aborting service installation...')
  Message(Title01,TempMsg)
  return
endif

ErrorMode(@OFF)
wntSvcCfgSet('',SvcKeyName,1000,10,SvcDescription)
RC = LastError()
ErrorMode(@CANCEL)

TempAnswer = AskYesNo(Title01,'Stop & restart the service now?')

if (TempAnswer == @YES)
  StopSvc()
  StartSvc()
endif

return

:Cancel

IntControl(72,2,0,0,0)

return
#ENDSUBROUTINE



; Remove the service

#DEFINESUBROUTINE RemoveSvc()
IntControl(72,2,0,0,0)

bExists = wntSvcStatus('',SvcKeyName,1000,0)

if (bExists)
  ErrorMode(@OFF)
  SvcStatus = wntSvcStatus('',SvcKeyName,1000,2)
  RC = LastError()
  ErrorMode(@CANCEL)

  if (SvcStatus != 1) ; Not stopped
    ErrorMode(@OFF)
    wntSvcControl('',SvcKeyName,1000,1)
    RC = LastError()
    ErrorMode(@CANCEL)
  endif

  ErrorMode(@OFF)
  wntSvcDelete('',SvcKeyName,1000)
  RC = LastError()
  ErrorMode(@CANCEL)
else
  TempMsg = StrCat('Warning!  Service does not exist.')
  Message(Title01,TempMsg)
endif

return

:Cancel

IntControl(72,2,0,0,0)

return
#ENDSUBROUTINE



; Start the service

#DEFINESUBROUTINE StartSvc()
IntControl(72,2,0,0,0)

bExists = wntSvcStatus('',SvcKeyName,1000,0)

if (bExists)
  ErrorMode(@OFF)
  SvcStatus = wntSvcStatus('',SvcKeyName,1000,2)
  RC = LastError()
  ErrorMode(@CANCEL)

  if (SvcStatus == 1) ; Stopped
    ErrorMode(@OFF)
    wntSvcStart('',SvcKeyName,1000,'','')
    RC = LastError()
    ErrorMode(@CANCEL)
  else
    TempMsg = StrCat('Warning!  Service is not stopped.')
    Message(Title01,TempMsg)
  endif
else
  TempMsg = StrCat('Warning!  Service does not exist.')
  Message(Title01,TempMsg)
endif

return

:Cancel

IntControl(72,2,0,0,0)

return
#ENDSUBROUTINE



; Stop the service

#DEFINESUBROUTINE StopSvc()
IntControl(72,2,0,0,0)

bExists = wntSvcStatus('',SvcKeyName,1000,0)

if (bExists)
  ErrorMode(@OFF)
  SvcStatus = wntSvcStatus('',SvcKeyName,1000,2)
  RC = LastError()
  ErrorMode(@CANCEL)

  if (SvcStatus != 1) ; Not stopped
    ErrorMode(@OFF)
    wntSvcControl('',SvcKeyName,1000,1)
    RC = LastError()
    ErrorMode(@CANCEL)
  endif
else
  TempMsg = StrCat('Warning!  Service does not exist.')
  Message(Title01,TempMsg)
endif

return

:Cancel

IntControl(72,2,0,0,0)

return
#ENDSUBROUTINE



#DEFINESUBROUTINE BuildSvcInstanceInfo()

SvcKeyName = StrCat(SvcKeyNameBase,'_',SvcInstanceStr)
SvcDisplayName = StrCat(SvcDisplayNameBase,' #',SvcInstanceStr)
SvcBinSpec = StrCat(AppPath,AppRoot,'.exs')

RegBase = StrCat(RegKeyBase,'\',SvcKeyName)

SvcStringValues = StrCat(SvcKeyName,@TAB,SvcDisplayName,@TAB,SvcBinSpec,@TAB,SvcLoadOrderGroup,@TAB,SvcStartName,@TAB,SvcPassword)
CrashLogFileSpec = StrCat(AppPath,AppRoot,'_',SvcInstanceStr,'.ERR')
DefTraceFileSpec = StrCat(AppPath,AppRoot,'_',SvcInstanceStr,'.TRC')
DefLogFileSpec = StrCat(AppPath,AppRoot,'_',SvcInstanceStr,'.LOG')
return
#ENDSUBROUTINE



; Define the main dialog box

CfgMainDlgFormat=`WWWDLGED,6.1`

CfgMainDlgCaption=`WinBatch "Service Test" Utility`
CfgMainDlgX=-01
CfgMainDlgY=-01
CfgMainDlgWidth=312
CfgMainDlgHeight=135
CfgMainDlgNumControls=020
CfgMainDlgProcedure=`MainDlgProc`
CfgMainDlgFont=`DEFAULT`
CfgMainDlgTextColor=`DEFAULT`
CfgMainDlgBackground=`DEFAULT,DEFAULT`
CfgMainDlgConfig=0

CfgMainDlg001=`255,103,048,011,PUSHBUTTON,DEFAULT,"&Cancel",2,2,32,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg002=`206,103,049,011,PUSHBUTTON,DEFAULT,"Apply",1,1,2,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg003=`105,103,046,011,PUSHBUTTON,DEFAULT,"&Start Service",5,5,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg004=`156,103,049,011,PUSHBUTTON,DEFAULT,"Sto&p Service",6,6,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg005=`006,103,049,011,PUSHBUTTON,DEFAULT,"&Install Service",3,3,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg006=`055,103,048,011,PUSHBUTTON,DEFAULT,"&Remove Service",4,4,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg007=`055,062,248,009,EDITBOX,CmdLine,DEFAULT,DEFAULT,11,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg008=`055,006,248,009,EDITBOX,RegParam1,DEFAULT,DEFAULT,7,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg009=`055,018,248,011,EDITBOX,RegParam2,DEFAULT,DEFAULT,8,0,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg010=`055,033,248,011,EDITBOX,RegParam3,DEFAULT,DEFAULT,9,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg011=`055,047,248,011,EDITBOX,SvcDescription,DEFAULT,DEFAULT,10,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg012=`281,119,022,011,SPINNER,SvcInstanceNum,"1",DEFAULT,12,8,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg013=`047,121,107,006,VARYTEXT,SvcCurrStatus,DEFAULT,DEFAULT,99,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg014=`004,007,046,008,STATICTEXT,DEFAULT,"Registry Param1",DEFAULT,99,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg015=`004,063,041,006,STATICTEXT,DEFAULT,"Command Line",DEFAULT,99,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg016=`004,020,046,006,STATICTEXT,DEFAULT,"Registry Param2",DEFAULT,99,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg017=`230,121,046,006,STATICTEXT,DEFAULT,"Service Instance #:",DEFAULT,99,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg018=`006,121,038,006,STATICTEXT,DEFAULT,"Service Status:",DEFAULT,99,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg019=`004,034,046,008,STATICTEXT,DEFAULT,"Registry Param3",DEFAULT,99,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
CfgMainDlg020=`004,049,048,006,STATICTEXT,DEFAULT,"Service Description",DEFAULT,99,DEFAULT,DEFAULT,DEFAULT,DEFAULT`

;ButtonPushed=Dialog("CfgMainDlg")





; Define some important constants

Title01 = 'WinBatch "Service Test"'

; Find out who we are, where we are located and what our version is

AppFileSpec = IntControl(1004,0,0,0,0)
AppPath = FilePath(AppFileSpec)
AppRoot = FileRoot(AppFileSpec)
AppProductVer = FileVerInfo(AppFileSpec,'','ProductVersion')
AppFileVer = FileVerInfo(AppFileSpec,'','FileVersion')

AppComments = FileVerInfo(AppFileSpec,'','Comments')
AppCompanyName = FileVerInfo(AppFileSpec,'','CompanyName')
AppFileDescription = FileVerInfo(AppFileSpec,'','FileDescription')
AppInternalName = FileVerInfo(AppFileSpec,'','InternalName')
AppLegalCopyright = FileVerInfo(AppFileSpec,'','LegalCopyright')
AppLegalTrademarks = FileVerInfo(AppFileSpec,'','LegalTrademarks')
AppProductName = FileVerInfo(AppFileSpec,'','ProductName')

RegKeyBase = 'SYSTEM\CurrentControlSet\Services'
SvcKeyNameBase = 'ServiceTest'
SvcDisplayNameBase = 'WinBatch "Service Test" Service'

SvcCurrStatus = ''

SvcLoadOrderGroup = ''
SvcStartName = 'LocalSystem'
SvcPassword = ''

SvcInstanceNum = 1
SvcInstanceStr = '01'
SvcDescription = ''

SvcInterval = 5.0

RegParam1 = ''
RegParam2 = ''
RegParam3 = ''
CmdLineParam1 = ''
CmdLineParam2 = ''

BuildSvcInstanceInfo()

SvcType = 16 + 256
SvcStart = 2
SvcErrCtrl = 1

SvcNumValues = StrCat(SvcType,@TAB,SvcStart,@TAB,SvcErrCtrl)

SvcDependsOn = ''

SvcRecoveryOptions = StrCat('1|60000',@TAB,'1|60000',@TAB,'1|60000')

ERR_SUCCESS = 0
ERR_UNKNOWN = 1
ERR_RUN_MODE_NOT_SERVICE = 2
ERR_INSTANCE_UNDEFINED = 3
ERR_CMDLINE_PARAM_FAULT = 4
ERR_CONFIG_PARAM_UNDEFINED = 5

IntControl(1000,ERR_UNKNOWN,0,0,0)

hLogFile = 0


; Add in our extenders...

AddExtender('WWWNT34I.DLL')


; Set our cancel handler...

IntControl(72,2,0,0,0)


; Figure out whether we are running as an application or as a service.
; If we are running as an application, then we need to present the
; configuration dialog box.  If we are running as a service then we
; should continue on and do our normal service mode processing.

RunMode = rtstatus()

if (RunMode == 1)
  Title01 = StrCat(Title01,' Configuration Utility')
  IntControl(1002,1,0,0,0) ; Show an icon on the taskbar
  gosub DoConfigureApp
  IntControl(1000,ERR_SUCCESS,0,0,0)
  exit
endif

Title01 = StrCat(Title01,' Service')

if (RunMode != 5)
  TempMsg = StrCat('Error!  Run Mode = "',RunMode,'", should be "5".  Aborting...')
  Message(Title01,TempMsg)
  IntControl(1000,ERR_RUN_MODE_NOT_SERVICE,0,0,0)
  exit
endif


; Get our command line.  We are dealing with a native service program here, and the
; only way that we get command line parameters passed in to us when we get automatically
; started up at system boot time is if they are included as part of the binary file
; specification that is part of the service definition.  We must call GetCommandLineA()
; in KERNEL32.DLL in order to obtain the full command line since a WinBatch script in
; native service mode only receives [in Param1 through Param9] the parameters that are
; manually supplied when a service is manually started.  Another key thing to remember
; here is that the binary file specification might be a short 8.3 name or it might be a
; long file name.  We will parse the command line and save all of the data after the
; binary file specification for use as command line parameter information.

CmdLine = ''

TempStrAddr = DllCall('KERNEL32.DLL',long:'GetCommandLineA')

TempByte = IntControl(32,TempStrAddr,'BYTE',0,0)

while(TempByte != 0)
  CmdLine = StrCat(CmdLine,Num2Char(TempByte))
  TempStrAddr = TempStrAddr + 1
  TempByte = IntControl(32,TempStrAddr,'BYTE',0,0)
endwhile

if (StrSub(CmdLine,1,1) == '"')
  ; We have a long file name in quotes with possible embedded spaces.
  CmdLine = StrSub(CmdLine,2,-1)
  TempPos = StrIndex(CmdLine,'"',0,@FWDSCAN)
  CmdLine = StrSub(CmdLine,TempPos+2,-1)
else
  ; We have a short file name w/o quotes and w/o embedded spaces.
  TempPos = StrIndex(CmdLine,' ',0,@FWDSCAN)
  CmdLine = StrSub(CmdLine,TempPos+2,-1)
endif

ParseData(CmdLine)

if (IsDefined(param1))
  CmdLineParam1 = param1
else
  CmdLineParam1 = ''
endif

if (IsDefined(param2))
  CmdLineParam2 = param2
else
  CmdLineParam2 = ''
endif

if (IsDefined(param3))
  CmdLineParam3 = param3
else
  CmdLineParam3 = ''
endif

if (IsDefined(param4))
  CmdLineParam4 = param4
else
  CmdLineParam4 = ''
endif

RawServiceName = IntControl(1009,0,0,0,0)

ErrorMode(@OFF)
SvcInstanceNum = Int(StrSub(RawServiceName,StrLen(RawServiceName)-1,2))
ErrorMode(@CANCEL)

if (SvcInstanceNum == 0)
  TempMsg = StrCat('Error!  Service instance number is undefined (zero).  Aborting...')
  Message(Title01,TempMsg)
  IntControl(1000,ERR_INSTANCE_UNDEFINED,0,0,0)
  exit
endif

SvcInstanceStr = StrFixLeft(SvcInstanceNum,'0',2)

BuildSvcInstanceInfo()

GlobalConfigGet()

if (bDebug) then Debug(@ON)
if (bDebugTrace) then DebugTrace(@ON,TraceFileSpec)

if (bLog)
  IntControl(40,3,0,0,0) ; Allow other processes to read & write this file.
  hLogFile = FileOpen(LogFileSpec,'WRITE')
endif

LogMsg(hLogFile,"*** Initialization started ***")
LogMsg(hLogFile,'')
LogMsg(hLogFile,StrCat('Application Program = "',AppFileSpec,'"'))
LogMsg(hLogFile,StrCat('AppComments = "',AppComments,'"'))
LogMsg(hLogFile,StrCat('AppCompanyName = "',AppCompanyName,'"'))
LogMsg(hLogFile,StrCat('AppFileDescription = "',AppFileDescription,'"'))
LogMsg(hLogFile,StrCat('AppFileVersion = "',AppFileVer,'"'))
LogMsg(hLogFile,StrCat('AppInternalName = "',AppInternalName,'"'))
LogMsg(hLogFile,StrCat('AppLegalCopyright = "',AppLegalCopyright,'"'))
LogMsg(hLogFile,StrCat('AppLegalTrademarks = "',AppLegalTrademarks,'"'))
LogMsg(hLogFile,StrCat('AppProductName = "',AppProductName,'"'))
LogMsg(hLogFile,StrCat('AppProductVersion = "',AppProductVer,'"'))
LogMsg(hLogFile,StrCat('WIL Dll Version = "',VersionDLL(),'"'))
LogMsg(hLogFile,StrCat('WWWNT34I.DLL Version = "',wntVersion(),'"'))
LogMsg(hLogFile,StrCat('Service Instance # = "',SvcInstanceNum,'"'))
LogMsg(hLogFile,StrCat('Log File Specification = "',LogFileSpec,'"'))
LogMsg(hLogFile,StrCat('Crash File Specification = "',CrashLogFileSpec,'"'))
LogMsg(hLogFile,StrCat('RegBase = "',RegBase,'"'))
LogMsg(hLogFile,StrCat('Debug = "',bDebug,'"'))
LogMsg(hLogFile,StrCat('DebugTrace = "',bDebugTrace,'"'))
LogMsg(hLogFile,StrCat('TraceFileSpec = "',TraceFileSpec,'"'))
LogMsg(hLogFile,StrCat('Log = "',bDebug,'"'))
LogMsg(hLogFile,StrCat('LogFileSpec = "',LogFileSpec,'"'))
LogMsg(hLogFile,StrCat('CmdLine = "',CmdLine,'"'))

; We are running in service mode.  Disable visible error messages and have them
; written to a crash log file.

if (FileExist(CrashLogFileSpec)) then FileDelete(CrashLogFileSpec)

IntControl(38,1,CrashLogFileSpec,0,0)

ConfigGet(@FALSE)

LogMsg(hLogFile,StrCat('RegParam1 = "',RegParam1,'"'))
LogMsg(hLogFile,StrCat('RegParam2 = "',RegParam2,'"'))
LogMsg(hLogFile,StrCat('RegParam3 = "',RegParam3,'"'))
LogMsg(hLogFile,'')
LogMsg(hLogFile,"*** Initialization complete, entering service loop ***")
LogMsg(hLogFile,'')

; 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_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_START_PENDING     = 2 ; The service is initializing
SERVICE_STATE_STOP_PENDING      = 3 ; The service is stopping
SERVICE_STATE_RUNNING           = 4 ; The service is running
SERVICE_STATE_CONTINUE_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_USER128         = 128 ; User command 128
SERVICE_CONTROL_USER129         = 129 ; User command 129
SERVICE_CONTROL_USER255         = 255 ; User command 255
SERVICE_CONTROL_LOGOFF          = 32768 ; logoff notification


; Set current service status...

CurrSvcState = SERVICE_STATE_START_PENDING


; Tell system that we want all notifications

flag = svcSetAccept( SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_LOGOFF )

if (flag == -1) 
  TempMsg = StrCat('Error!  The svcSetAccept() function returned "-1".  Aborting...')
  IntControl(1000,ERR_RUN_MODE_NOT_SERVICE,0,0,0)
  exit
else
   IntControl(12,2+8,0,0,0) ; Tell WinBatch to not honor terminate and not complain on Windows exit.
endif


; Build up a string we can use repeatedly in our text box to display a status message regarding the
; status of our service.

ParamMsg = StrCat('Command Line = "',CmdLine,'"')
ParamMsg = StrCat(ParamMsg,@CRLF,'RegParam1 = "',RegParam1,'"')
ParamMsg = StrCat(ParamMsg,@CRLF,'RegParam2 = "',RegParam2,'"')
ParamMsg = StrCat(ParamMsg,@CRLF,'RegParam3 = "',RegParam3,'"')
ParamMsg = StrCat(ParamMsg,@CRLF,'CmdLineParam1 = "',CmdLineParam1,'"')
ParamMsg = StrCat(ParamMsg,@CRLF,'CmdLineParam2 = "',CmdLineParam2,'"')
ParamMsg = StrCat(ParamMsg,@CRLF,'CmdLineParam3 = "',CmdLineParam3,'"')
ParamMsg = StrCat(ParamMsg,@CRLF,'CmdLineParam4 = "',CmdLineParam4,'"')

; Now we start the main service loop.  In this service we respond to all control messages.
; We also need to prime the loop so that we can properly schedule our work to be done.

SvcSetState(SERVICE_STATE_RUNNING)
CurrSvcState = SERVICE_STATE_RUNNING

while (@TRUE)
  code = SvcWaitForCmd(SvcInterval)      ; Timeout in 5.0 seconds unless SvcInterval has a different value

  switch code
    case SERVICE_CONTROL_TIMEOUT       
      if (CurrSvcState == SERVICE_STATE_RUNNING)
        LogMsg(hLogFile,'Doing work...')
        TempMsg = StrCat('Service State = RUNNING',@CRLF,@CRLF,ParamMsg)
        BoxOpen(Title01,TempMsg)
      endif
      break

    case SERVICE_CONTROL_STOP          
      SvcSetState(SERVICE_STATE_STOP_PENDING)
      LogMsg(hLogFile,'Service Stop message received')
      TempMsg = StrCat('Service State = STOP PENDING',@CRLF,@CRLF,ParamMsg)
      BoxOpen(Title01,TempMsg)
      if (hLogFile) then hLogFile = FileClose(hLogFile)
      SvcSetState(SERVICE_STATE_STOPPED)
      IntControl(1000,ERR_SUCCESS,0,0,0)
      exit
      break

    case SERVICE_CONTROL_PAUSE         
      SvcSetState(SERVICE_STATE_PAUSE_PENDING)
      SvcSetState(SERVICE_STATE_PAUSED)
      CurrSvcState = SERVICE_STATE_PAUSED
      LogMsg(hLogFile,'Service Pause message received')
      TempMsg = StrCat('Service State = PAUSE PENDING / PAUSED',@CRLF,@CRLF,ParamMsg)
      BoxOpen(Title01,TempMsg)
      break

    case SERVICE_CONTROL_CONTINUE 
      SvcSetState(SERVICE_STATE_CONTINUE_PENDING)
      SvcSetState(SERVICE_STATE_RUNNING)
      CurrSvcState = SERVICE_STATE_RUNNING
      LogMsg(hLogFile,'Service Continue message received')
      TempMsg = StrCat('Service State = CONTINUING',@CRLF,@CRLF,ParamMsg)
      BoxOpen(Title01,TempMsg)
      break

    case SERVICE_CONTROL_SHUTDOWN      
      SvcSetState(SERVICE_STATE_STOP_PENDING)
      LogMsg(hLogFile,'Service Shutdown message received')
      TempMsg = StrCat('Service State = SHUTTING DOWN',@CRLF,@CRLF,ParamMsg)
      BoxOpen(Title01,TempMsg)
      if (hLogFile) then hLogFile = FileClose(hLogFile)
      SvcSetState(SERVICE_STATE_STOPPED)
      IntControl(1000,ERR_SUCCESS,0,0,0)
      exit
      break

    case SERVICE_CONTROL_USER128       
      TempMsg = StrCat('Service State = Process User Message 128',@CRLF,@CRLF,ParamMsg)
      BoxOpen(Title01,TempMsg)
      ; User command 128 received
      break

    case SERVICE_CONTROL_USER129
      TempMsg = StrCat('Service State = Process User Message 129',@CRLF,@CRLF,ParamMsg)
      BoxOpen(Title01,TempMsg)
      ; User command 129 received
      break

    case SERVICE_CONTROL_LOGOFF
      TempMsg = StrCat('Service State = CONTROL LOGOFF',@CRLF,@CRLF,ParamMsg)
      BoxOpen(Title01,TempMsg)
      ; Logoff command received
      break

    case code
      TempMsg = StrCat('Service State = UNRECOGNIZED SCM CODE RECEIVED',@CRLF,@CRLF,ParamMsg)
      BoxOpen(Title01,TempMsg)
      ; Unrecognized command received
      break
  endswitch

endwhile

; Note - The preceeding loop never exits.

exit   ; Just a formality



;
; Start of gosub routines
;



:Cancel

IntControl(72,2,0,0,0)


return



:DoConfigureApp

; Display the main dialog.  We will stay inside the dialog until the 'OK' or 'Cancel' button 
; has been clicked, at which time this function will return and then we'll return from this
; gosub routine.

ConfigGet(@TRUE)

gosub UpdateEXSFromEXE

ButtonPushed=Dialog("CfgMainDlg")


return



:UpdateEXSFromEXE

TempBinSpec = StrCat(AppPath,AppRoot,'.exs')
if (!FileExist(TempBinSpec))
  ErrorMode(@OFF)
  FileCopy(AppFileSpec,TempBinSpec,@FALSE)
  ErrorMode(@CANCEL)
endif

if (FileExist(TempBinSpec) == 1)
  if (FileSize(AppFileSpec) != FileSize(TempBinSpec))
    ErrorMode(@OFF)
    Result = FileCopy(AppFileSpec,TempBinSpec,@FALSE)
    ErrorMode(@CANCEL)
    if (!Result)
      TempMsg = 'Warning!  EXE & EXS file are different sizes & EXS is locked.'
      Message(Title01,TempMsg)
    endif
  else
    if (FileTimeGetEx(AppFileSpec,2) != FileTimeGetEx(TempBinSpec,2))
      ErrorMode(@OFF)
      Result = FileCopy(AppFileSpec,TempBinSpec,@FALSE)
      ErrorMode(@CANCEL)
      if (!Result)
        TempMsg = 'Warning!  EXE & EXS file have different modification date/time stamps & EXS is locked.'
        Message(Title01,TempMsg)
      endif
    endif
  endif
endif

return

Article ID:   W16672
File Created: 2005:02:18:12:21:50
Last Updated: 2005:02:18:12:21:50