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

Samples from Users
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus

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

SMS-like Software Distribution in the Background

Keywords: 	 SMS-like software distribution in the background

I was just perusing the tech-support articles, and I noticed that someone wanted to know if Winbatch can accomplish software distribution to a workstation with no-one logged in. The article ID was W14614. I have written a script that can accomplish software distribution tasks when converted to run as a service. The compiled Winbatch executable must be run as a service using an administrative context (the service is configured to use a user that is a member of the local administrator group - similar to the SMS client installation service). The winbatch script/service can be configured in many ways, including how often to query the 3 possible sysupdate.ini files for updates. The script compares local registry keys (set via the Wise installation packages) to the contents of the .ini files. If versions are out of sync, the script will install the software, write status to a log file, and then fall asleep again until the next cycle (default is 5 minutes).

The script is compiled as a .exe file, and then the srvany.exe/instsrv.exe tools (from the NT4 resource kit) are used to configure it as a service. Since it is a service, it is always running, even when there is nobody logged into the workstation.

The sysupdate.ini files contain parameters to ensure that distributions only occur at a particular date and beyond, or within a particular time window (such as midnight to 6:00 am).

I am including a sample sysupdate.ini file and the code. I have changed some of the values for registry keys, and have tried to make them generic. However, I have not recompiled this script with the new values so I do not know if it will work right out of the door.


Sysupdate.ini:

[Application List]
WinZip7=1
Adobe3=1

[WinZip7]
Version=20000203
Action=\Packages\Winzip\Winzip7.exe
Year=2000
Month=5
Day=12
Starthour=20
Stophour=24

[Adobe3]
Version=19990502
Action=\Packages\Adobe\Acroread.exe
Year=2000
Month=7
Day=1
Starthour=2
Stophour=6

Sysupdate.wbt:

;** Initialize Log file settings, and specify the drives that contain copies
;** of sysupdate.ini.   The copy on the F: drive is global, whereas the copy on the 
;** R: drive is site-specific.

LogDate=TimeDate()
LogFile="c:\winnt\sysupdate.log"
Fupdfile="sysupdate.ini"
Rupdfile="sysupdate.ini"

;** Determine how often the workstation queries the contents of all sysupdate.ini files 
;** for updates.    Default to 5 minutes if no value is specified.
If RegExistKey(@REGMACHINE, "Software\SYSUpdate\SysDistFreq")
   regkey=RegOpenKey(@REGMACHINE, "Software\SYSUpdate")
   QueryTime=RegQueryValue(regkey, "SysDistFreq")
   RegCloseKey(regkey)
Else
   QueryTime=300
Endif

;** Write first log message
LogMessage=Strcat("%LogDate% - Initialized SYSUpdate service with %QueryTime% second query frequency.",@CRLF)
GoSub WriteLog

;** Determine which server will act as the Distribution Server for packages
;** This value is set either via the registry or in the environment
ErrorMode(@OFF)
If RegExistValue(@REGMACHINE, "Software\SYSUpdate[DistServer]")
   regkey=RegOpenKey(@REGMACHINE, "Software\SYSUpdate")
   CurrentServer=RegQueryValue(regkey, "DistServer")
   RegCloseKey(regkey)
Else
   regkey=RegOpenKey(@REGMACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment")
   UNCCurrentServer=RegQueryExpSz(regkey,"[DistServer]")
   CurrentServer=StrSub(UNCCurrentServer,3,-1)
   RegCloseKey(regkey)
Endif
ErrorMode(@CANCEL)

If CurrentServer==""
   LogMessage=Strcat("%LogDate% - SYSUpdate Init failure - DistServer value not set.",@CRLF)
   Gosub WriteLog
   Exit
Endif

while 1

   ;** Read and itemize the %DistServer%\Login\sysupdate.ini file, and execute updates if necessary
   ;** One of the 2 sysupdate.ini files (F:\Login\sysupdate.ini) is identical on all distribution
   ;** servers in the platform, ensuring that the update is processed by all workstations.   It can be 
   ;** replicated to all distribution servers ensuring only 1 copy will need to be updated (the master copy).  
   ;** The second copy is specific to the server, ensuring that only the workstations that use this particular
   ;** server will get the distribution.   The third copy resides on the workstation's C: drive, and can 
   ;** be used for individual installation of packages.
   INIFile=StrCat("\\","%CurrentServer%","\Login\","%Fupdfile%")
   GoSub ParseIniFile

   INIFile=StrCat("\\","%CurrentServer%","\Regional\","%Rupdfile%")
   GoSub ParseIniFile

   INIFile="c:\winnt\sysupdate.ini"
   GoSub ParseIniFile

   TimeDelay(QueryTime)

EndWhile

:ParseIniFile

   FE=FileExist(INIFile)
   If FE==@False Then Goto NextLoop

   LogDate=TimeDate()

   List=IniItemizePvt("Application List", INIFile)
   Count=ItemCount(List, @TAB)

   ;** Parse registry and compare against appropriate SYSUPDATE.INI file 

   For X=1 to Count                
      App=ItemExtract(x, List, @TAB)
      AppVer=IniReadPvt(App, "Version","None",INIFile)
      AppAction=IniReadPvt(App, "Action","None",INIFile)
      AppYear=IniReadPvt(App, "Year", "None", INIFile)
      AppMonth=IniReadPvt(App, "Month","None",INIFile)
      AppDay=IniReadPvt(App, "Day", "None", INIFile)
      AppStartHour=IniReadPvt(App, "Starthour", "None", INIFile)
      AppStopHour=IniReadPvt(App, "Stophour", "None", INIFile)
      If AppVer=="None" Then Goto AppVerMissing
      ErrorMode(@OFF)
      regkey=RegOpenKey(@REGMACHINE, "Software\SYSUpdate")
      CurrVer=RegQueryValue(regkey, "%App%")
      RegCloseKey(regkey)
      ErrorMode(@CANCEL)
      If CurrVer < AppVer Then Goto AppUpdateEXE
      Goto AppUpdateComplete

      :AppVerMissing
      LogMessage=Strcat("%LogDate% - %App%: %INIFile% file error.",@CRLF)
      GoSub WriteLog
      Goto AppUpdateComplete

      :AppUpdateEXE
      ;** Set variables for current time information, and apply logic for year 1999 or 2000+.  
      CurrTime=TimeYmdHms()
      YearPos=StrScan(CurrTime,":",1,@FWDSCAN)
      If YearPos==5
         CurrYear=StrSub(CurrTime,1,4)
         CurrMonth=StrSub(CurrTime,6,2)
         CurrDay=StrSub(CurrTime,9,2)
         CurrHour=StrSub(CurrTime,12,2)
         CurrMin=StrSub(CurrTime, 15,2)
      Else
         CurrYear=StrSub(CurrTime,1,2)
         If CurrYear==99
            CurrYear=1999
         Else
            CurrentYear=2000+%CurrYear%
            CurrYear=CurrentYear
         Endif
         CurrMonth=StrSub(CurrTime,4,2)
         CurrDay=StrSub(CurrTime,7,2) 
         CurrHour=StrSub(CurrTime,10,2)
         CurrMin=StrSub(CurrTime, 13,2)
      Endif
      ;** Determine if we are beyond the date specified in SYSUpdate.ini, and if so, run the update
      If AppYear!="None"
         If CurrYear>AppYear
            GoSub InstallSysUpdate
         Else
            If CurrYear==AppYear
               If CurrMonth>AppMonth
                  GoSub InstallSysUpdate
               Else
                  If CurrMonth==AppMonth
                     If CurrDay>=AppDay
                        GoSub InstallSysUpdate
                     Endif
                  Endif
               Endif
            Endif
         Endif
      Else
         GoSub InstallSysUpdate
      Endif

   :AppUpdateComplete
   Next
   :NextLoop
Return

:InstallSysUpdate

UpdateToRun=StrCat("\\","%CurrentServer%","%AppAction%")

;** Determine if the workstation is in the appropriate distribution window, 
;** and execute the package if this is the case.
If AppStartHour!="None"
   If AppStartHour=AppStartHour
         If CurrHour<=AppStopHour
            LogDate=TimeDate()
            LogMessage=Strcat("%LogDate% - %App%: Started system update...",@CRLF)
            GoSub WriteLog
            RunWait(UpdateToRun,"")
            LogDate=TimeDate()
            LogMessage=Strcat("%LogDate% - %App%: System update complete.",@CRLF)
            GoSub WriteLog				
         Endif
      Endif
   Else
      If CurrHour>=AppStartHour
         LogDate=TimeDate()
         LogMessage=Strcat("%LogDate% - %App%: Started system update...",@CRLF)
         GoSub WriteLog
         RunWait(UpdateToRun,"")
         LogDate=TimeDate()
         LogMessage=Strcat("%LogDate% - %App%: System update complete.",@CRLF)
         GoSub WriteLog
      Else
         If CurrHour<=AppStopHour
            LogDate=TimeDate()
            LogMessage=Strcat("%LogDate% - %App%: Started system update...",@CRLF)
            GoSub WriteLog
            RunWait(UpdateToRun,"")
            LogDate=TimeDate()
            LogMessage=Strcat("%LogDate% - %App%: System update complete.",@CRLF)
            GoSub WriteLog
         Endif
      Endif
   Endif
Else
   LogDate=TimeDate()
   LogMessage=Strcat("%LogDate% - %App%: Started system update...",@CRLF)
   GoSub WriteLog
   RunWait(UpdateToRun,"")
   LogDate=TimeDate()
   LogMessage=Strcat("%LogDate% - %App%: System update complete.",@CRLF)
   GoSub WriteLog
Endif

Return

:WriteLog

FE=FileExist(LogFile)
If FE==@False Then
   handle=FileOpen(LogFile, "WRITE")
   FileWrite(handle, "** SYSUpdate Log File **")
   FileClose(handle)
EndIf        
fs1=FileSize(LogFile)
binbuf1=BinaryAlloc(fs1 + 100)
BinaryRead(binbuf1, LogFile)
a=BinaryEodGet(binbuf1)
BinaryPokeStr(binbuf1, a, LogMessage)
BinaryWrite(binbuf1, LogFile)
BinaryFree(binbuf1)

Return

Article ID:   W14961
File Created: 2001:11:08:12:41:08
Last Updated: 2001:11:08:12:41:08