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

Launching WinBatch and Other Apps
plus

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

RemoteRun.wbt - User Sample Code

Keywords: PsExec.exe PsExec Remote Remotely Launch Run script .WBT WinBatch RemoteRun RunRemote RemoteRun.wbt

; Name: RemoteRun.wbt
; Purpose: Run a script or reg file on a list of remote machines
; Requirements: PsExec.exe (http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx)
; Setup: Edit Workstations.txt to include names or IP addresses of remote machines
; Author: Les Ferch
; 2008-09-29: Initial release
; 2008-09-30: Reliability and data logging improvements

IntControl(12,5,0,0,0) ; Terminate silently
IntControl(1003,0,0,0,0) ; Disable WinBatch dialog
IntControl(28,2,0,0,0) ; Force GUI font for all dialogs
Title = "RemoteRun"
Terminate(Version()<"2006D",Title,"WinBatch 2006D or higher is required to run this script")
TitleWin = Title:":"
If WinExist(TitleWin) Then Exit
BoxTitle(TitleWin)
DirChange(DirScript())
AddExtender("WWWNT34i.DLL")
AddExtender("WWINT44i.DLL")

IniFile = DirScript():Title:".ini"
WksFile = "Workstations.txt"
PSEFile = "psexec.txt"
LogFile = Title:".log"
Terminate(!FileExist(WksFile),Title,"File not found: ":WksFile)
WksList = FileGet(WksFile)
RemoteDir = "\Windows\Debug" ; Must exist and have no spaces in name

; Define header data we want to remove from log file
x = "PsExec v1.94 - Execute processes remotely":@CR
x = x:"Copyright (C) 2001-2008 Mark Russinovich":@CR
x = x:"Sysinternals - www.sysinternals.com"
PSEHeader = x

PingTimeOut = 1 ; Ping timeout in seconds
PSETimeOut = 5 ; PsExec timeout in seconds

; Strip blank lines from workstation list
WksList = StrReplace(WksList,@CRLF,@LF)
Count = ItemCount(WksList,@LF)
NewList = ""
For i = 1 To Count
   Item = ItemExtract(i,WksList,@LF)
   Item = StrTrim(Item)
   If Item!="" Then NewList = NewList:Item:@TAB
Next
WksList = StrTrim(NewList)
WksList = StrReplace(WksList,@TAB,@LF)
Count = ItemCount(WksList,@LF)
Terminate(Count==0,Title,"No entries found in: ":WksFile)

; Get last used settings
Script = ""
CmdLine = ""
ID = ""
PW = ""
If FileExist(IniFile) Then
   Script = IniReadPvt("Config","Script","",IniFile)
   CmdLine = IniReadPvt("Config","CmdLine","",IniFile)
   ID = IniReadPvt("Config","ID","",IniFile)
EndIf
If !FileExist(Script) Then Script = ""

; Prompt for script
FileTypes = "cmd exe kix reg vbs wbt|*.cmd;*.exe;*.kix;*.reg;*.vbs;*.wbt|All Files|*.*"
Script = AskFilename("Select script to run on remote machines","",FileTypes,Script,1)

; Identify extension and set up correct handling
FileExt = StrLower(FileExtension(Script))
KIX = FileExt=="kix"
REG = FileExt=="reg"
VBS = FileExt=="vbs"
WBT = FileExt=="wbt"
Processor = ""
If KIX Then Processor = "Kix32.exe "
If REG Then Processor = "Regedit.exe /s "
If VBS Then Processor = "Wscript.exe "
If WBT Then Processor = "WinBatch.exe "

If KIX||WBT
   Msg = "Please ensure that ":Processor:"is on the search path of the remote machines before continuing."
   If WBT Then Msg = Msg:@LF:@LF:"To run a compiled WinBatch script remotely, please Cancel and select a .exe file instead."
   Pause(Title,Msg)
EndIf

; Prompt for command line parameters
ScriptBaseName = FileBaseName(Script)
If REG || StrIndex(CmdLine,ScriptBaseName,1,@FWDSCAN)==0 Then
   CmdLine = FileBaseName(Script)
   If StrIndex(CmdLine," ",1,@FWDSCAN)>0 Then CmdLine = '"':CmdLine:'"'
EndIf
If !REG Then CmdLine = AskLine(Title,"Add any necessary parameters:",CmdLine:" ")

; Prompt for account and password
Msg = "Enter admin account. Examples:":@LF
Msg = Msg:"local\ntadmin":@LF:"naeast\u123456"
While @TRUE
   ID = AskLine(Title,Msg,ID)
   If ID!="" Then Break
EndWhile
While PW==""
   PW = AskPassword(Title,"Enter password for the account: ":ID)
EndWhile

; Prompt to run hidden or interactive
Msg = "Run script hidden (desktop interaction prohibited)?":@LF:@LF
Msg = Msg:"Click No only if script must interact with desktop."
Answer = AskYesNo(Title,Msg)
Interact = ""
If Answer==@NO Then Interact = " -i"

; Last warning
Msg = "Are you sure you want to run:":@LF:@LF:CmdLine:@LF:@LF
Msg = Msg:"on all workstations listed in ":WksFile:"?"
Pause(Title,Msg)

ID = StrReplace(ID,"/","\")
If StrIndex(ID,"\",1,@FWDSCAN)==0 Then ID = "local\":ID

; Save settings back to INI file
IniWritePvt("Config","Script",Script,IniFile)
IniWritePvt("Config","CmdLine",CmdLine,IniFile)
IniWritePvt("Config","ID",ID,IniFile)

; Run console command and capture StdOUT and StdERR
#DefineFunction RunCmd(Command)
If Command=="" Then Return ""
Temp = Environment("Temp")
ComSpec = Environment("ComSpec")
F1 = StrCat(Temp,"\",GetTickCount(),"1.txt")
F2 = StrCat(Temp,"\",GetTickCount(),"2.txt")
RunHideWait(ComSpec,StrCat('/c "',Command,' >"',F1,'"',' 2>"',F2,'""'))
F1Data = StrReplace(StrTrim(FileGet(F1)),StrCat(@CR,@CR),@CR)
F2Data = StrReplace(StrTrim(FileGet(F2)),StrCat(@CR,@CR),@CR)
Separator = Num2Char(160) ; Non-breaking space used to separate StdERR from StdOUT
If F1Data=="" || F2Data=="" Then Separator = ""
Result = StrCat(F2Data,@CRLF,Separator,F1Data)
FileDelete(F1)
FileDelete(F2)
Return Result
#EndFunction

IntControl(1003,1,0,0,0) ; Enable WinBatch dialog
BoxOpen(Title,"Processing...")

CmdLine = "C:":RemoteDir:"\":CmdLine
CmdLine = Processor:CmdLine
IDP = StrLower(ID)
IDP = StrReplace(ID,"local\","")
PSEData = ""
CopyFailList = ""
PingFailList = ""

; Copy, run, and delete script on all remote machines
For i = 1 To Count
   Workstation = ItemExtract(i,WksList,@LF)
   BoxText("Processing ":Workstation:" (":i:" of ":Count:" )")
   OK = iPing(Workstation,PingTimeOut)
   If OK ; Copy script to remote workstation if Ping OK
      ErrMode = ErrorMode(@OFF)
      wntAddDrive(ID,PW,"\\":Workstation:"\ipc$",@NONE,@FALSE)
      FileCopy(Script,"\\":Workstation:"\C$":RemoteDir,@FALSE)
      OK = wntCancelCon("\\":Workstation:"\ipc$",@FALSE,@TRUE)
      ErrorMode(ErrMode)
      If OK ; Execute script on remote workstation if Copy OK
         DirChange(DirScript())
         Data = RunCmd("psexec \\":Workstation:" -accepteula -n ":PSETimeOut:" -u ":IDP:" -p ":PW:Interact:" ":CmdLine)
         PSEData = PSEData:Data:@CRLF
         ErrMode = ErrorMode(@OFF)
         ; Remove script from remote workstation
         wntAddDrive(ID,PW,"\\":Workstation:"\ipc$",@NONE,@FALSE)
         FileDelete("\\":Workstation:"\C$":RemoteDir:"\":FileBaseName(Script))
         wntCancelCon("\\":Workstation:"\ipc$",@FALSE,@TRUE)
         ErrorMode(ErrMode)
      Else
         CopyFailList = CopyFailList:Workstation:@CRLF
      EndIf
   Else
      PingFailList = PingFailList:Workstation:@CRLF
   EndIf
Next

BoxShut()
IntControl(1003,0,0,0,0) ; Disable WinBatch dialog

; Clean up log file
LogData = ItemExtract(1,PSEData,Num2Char(160))
LogData = StrReplace(LogData,@LF,"")
LogData = StrReplace(LogData,PSEHeader,"")
While StrIndex(LogData,"  ",1,@FWDSCAN)>0
   LogData = StrReplace(LogData,"  "," ")
EndWhile
LogData = StrReplace(LogData,@CR:" ":@CR,@CR)
While StrIndex(LogData,@CR:@CR,1,@FWDSCAN)>0
   LogData = StrReplace(LogData,@CR:@CR,@CR)
EndWhile
LogData = StrReplace(LogData,"Connecting to",@CR:"Connecting to")
LogData = @TAB:LogData
LogData = StrReplace(LogData,@TAB:@CR:@CR,"")
LogData = StrReplace(LogData,@CR,@CRLF)

; Add to log workstations that failed copy or ping
If CopyFailList!=""
   Heading = "Script copy failed for the following machines:"
   LogData = Heading:@CRLF:CopyFailList:@CRLF:LogData
EndIf
If PingFailList!=""
   Heading = "Ping failed for the following machines:"
   LogData = Heading:@CRLF:PingFailList:@CRLF:LogData
EndIf

; Save and display log file
FilePut(LogFile,LogData)
Run(LogFile,"")


Article ID:   W17967
Filename:   RemoteRun wbt - User Sample.txt
File Created: 2008:09:30:13:51:54
Last Updated: 2008:09:30:13:51:54