Discussion:
Execute a batch file on remote host
(too old to reply)
Hulicat
2007-10-30 16:16:53 UTC
Permalink
Running Windows 2003 R2 I need to execute a batch on remote Windows
2003 R2 machine.

I have tried a number of things including rexec, etc.

The goal would not to deploy any additional code to the remote host.

Is there a way to this via Cscript?do I need to write a vbs script?

Thanks,
Dennis
Chris M
2007-10-30 16:52:18 UTC
Permalink
Post by Hulicat
Running Windows 2003 R2 I need to execute a batch on remote Windows
2003 R2 machine.
I have tried a number of things including rexec, etc.
The goal would not to deploy any additional code to the remote host.
Is there a way to this via Cscript?do I need to write a vbs script?
Check out PsExec:

http://www.microsoft.com/technet/sysinternals/Security/PsExec.mspx
--
Chris M.
Richard Mueller [MVP]
2007-10-30 18:04:07 UTC
Permalink
Post by Hulicat
Running Windows 2003 R2 I need to execute a batch on remote Windows
2003 R2 machine.
I have tried a number of things including rexec, etc.
The goal would not to deploy any additional code to the remote host.
Is there a way to this via Cscript?do I need to write a vbs script?
A VBScript program can use WMI to connect to the remote computer, copy the
executable (a batch file in this case), run it, wait for execution to
complete, then delete the file. I have an example VBScript program that does
this for all computers in a domain group. You can either modify this for one
computer, or place the computer object in a group by itself. The program
deploys only to computers in the group, so it does not hurt to have user
objects in the group.

http://www.rlmueller.net/Deploy.htm

The program writes a log to document everything.
--
Richard Mueller
Microsoft MVP Scripting and ADSI
Hilltop Lab - http://www.rlmueller.net
--
1RealTruth
2009-06-19 03:34:14 UTC
Permalink
Thank you Richard. Your script looks really nice but I have a problem
with it. I'm not working on a domain. I'm trying to incorporate code
to do this in a VB program I'm writing. I have the process of ending
tasks down but I'm trying to incorporate batch files to shut down and
restart Cold Fusion and IIS. We have batch files to do this but not all
the servers have them.

I'm doing this in my spare time to try and help our NOC guys with their
job. Also I'm getting let go at the end of July. I wanted to do
something to help before I leave. It will also help me with getting
back into programming. I'm going to see if the company that bought us
will give me a good recommendation for my next job. My wife wants to go
back to Europe. She's a member of the EU but I'm not.

Any help will be greatly appreciated.

Thank you.
Post by Richard Mueller [MVP]
Post by Hulicat
Running Windows 2003 R2 I need to execute a batch on remote Windows
2003 R2 machine.
I have tried a number of things including rexec, etc.
The goal would not to deploy any additional code to the remote host.
Is there a way to this via Cscript?do I need to write a vbs script?
A VBScript program can use WMI to connect to the remote computer, copy the
executable (a batch file in this case), run it, wait for execution to
complete, then delete the file. I have an example VBScript program that does
this for all computers in a domain group. You can either modify this for one
computer, or place the computer object in a group by itself. The program
deploys only to computers in the group, so it does not hurt to have user
objects in the group.
http://www.rlmueller.net/Deploy.htm
The program writes a log to document everything.
--
Richard Mueller
Microsoft MVP Scripting and ADSI
Hilltop Lab - http://www.rlmueller.net
--
--
1RealTruth
------------------------------------------------------------------------
1RealTruth's Profile: http://forums.techarena.in/members/106922.htm
View this thread: http://forums.techarena.in/server-scripting/843476.htm

http://forums.techarena.in
Richard Mueller [MVP]
2009-06-19 18:31:22 UTC
Permalink
Post by 1RealTruth
Thank you Richard. Your script looks really nice but I have a problem
with it. I'm not working on a domain. I'm trying to incorporate code
to do this in a VB program I'm writing. I have the process of ending
tasks down but I'm trying to incorporate batch files to shut down and
restart Cold Fusion and IIS. We have batch files to do this but not all
the servers have them.
I'm doing this in my spare time to try and help our NOC guys with their
job. Also I'm getting let go at the end of July. I wanted to do
something to help before I leave. It will also help me with getting
back into programming. I'm going to see if the company that bought us
will give me a good recommendation for my next job. My wife wants to go
back to Europe. She's a member of the EU but I'm not.
Any help will be greatly appreciated.
Thank you.
Here is a version of the program I linked that uses an array of computer
names, instead of a domain group. I have not tested the program, but this
should work even if there is no domain. In the code below I specify only one
computer in the array, but there could be as many as desired:
============
' Deploy.vbs
Option Explicit

Dim strExecutable, strGroup, m_strCommand
Dim m_objFSO, m_strProgram
Dim strScriptName, strScriptPath, strScriptFolder
Dim strComputer, strParms, strLogFile, strLocal
Dim m_objLogFile, m_objNetwork, m_objShell, m_strTempFile
Dim m_objLocal, m_strDrive, m_blnFirst, m_objSourceFile
Dim intSuccess, intFailure
Dim arrComputers

Const ForAppending = 8

' Specify array of computer NetBIOS names.
arrComputers = Array("MyComputer")

' Prompt for the program to run on each remote computer.
strExecutable = InputBox("Enter the full path and name of the program " _
& "to deploy to computers in the array", "Deployment Utility")

' Check for the existence of the file.
Set m_objFSO = CreateObject("Scripting.FileSystemObject")
If (m_objFSO.FileExists(strExecutable) = False) Then
Wscript.Echo "File " & strExecutable & " not found"
Wscript.Quit
End If
' Retrieve program name.
m_strProgram = m_objFSO.GetFileName(strExecutable)

' Prompt for command line parameters.
strParms = InputBox("Enter any command line parameters", _
"Deployment Utility")
strParms = Trim(strParms)

' Construct command to execute on remote computers.
m_strCommand = m_strProgram
If (strParms <> "") Then
m_strCommand = m_strCommand & " " & strParms
End If

' Retrieve temporary file name for ping operation.
Set m_objShell = CreateObject("Wscript.Shell")
m_strTempFile = m_objShell.ExpandEnvironmentStrings("%TEMP%")
m_strTempFile = m_strTempFile & "\RunResult.tmp"

' Determine current directory.
strScriptName = Wscript.ScriptName
strScriptPath = Wscript.ScriptFullName
strScriptFolder = Left(strScriptPath, _
Len(strScriptPath) - Len(strScriptName) - 1)

' Setup log file in current directory.
strLogFile = strScriptFolder & "\Deploy.log"
Set m_objLogFile = m_objFSO.OpenTextFile(strLogFile, ForAppending, True)
m_objLogFile.WriteLine "====="
m_objLogFile.WriteLine CStr(Now()) & " Deployment started"
m_objLogFile.WriteLine "-- Deployment executable " & strExecutable
m_objLogFile.WriteLine "-- Command to execute " & m_strCommand
m_objLogFile.WriteLine "-- Deploy to computers in array"

' Retrieve local computer name.
Set m_objNetwork = CreateObject("Wscript.Network")
strLocal = m_objNetwork.ComputerName

' Connect to local computer with WMI.
Set m_objLocal = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate,authenticationLevel=Pkt}!\\" _
& strLocal & "\root\cimv2")
m_objLogFile.WriteLine "-- Connected to local computer " & strLocal

' Default drive letter to map for copying executable file
' to remote computer.
m_strDrive = "Z:"
m_blnFirst = True

' Bind to local executable program file.
On Error Resume Next
Set m_objSourceFile = m_objLocal.Get("cim_datafile=""" _
& Replace(strExecutable, "\", "\\") & """")
If (Err.Number <> 0) Then
On Error GoTo 0
m_objLogFile.WriteLine "-- ### File not found: " & strExecutable
Wscript.Echo "File not found: " & strExecutable
Wscript.Quit
End If
On Error GoTo 0

' Enumerate array of computer names.
intSuccess = 0
intFailure = 0
For Each strComputer In arrComputers
m_objLogFile.WriteLine CStr(Now()) _
& " deploy to computer " & strComputer
Wscript.Echo "Deploying to " & strComputer
If (IsConnectible(strComputer, 1, 500) = True) Then
m_objLogFile.WriteLine "-- Computer found"
If (RunProgram(strComputer) = True) Then
intSuccess = intSuccess + 1
Wscript.Echo "-- success"
Else
intFailure = intFailure + 1
Wscript.Echo "-- failure"
End If
Else
m_objLogFile.WriteLine "-- ### computer not available"
intFailure = intFailure + 1
Wscript.Echo "-- not available"
End If
Next

' Log results.
m_objLogFile.WriteLine CStr(Now()) & " Deployment finished"
m_objLogFile.WriteLine "-- Successfully deployed to " & CStr(intSuccess) _
& " computers"
m_objLogFile.WriteLine "-- Failed to deploy to " & CStr(intFailure) _
& " computers"
m_objLogFile.WriteLine "====="
m_objLogFile.Close

' Notify user.
Wscript.Echo "Deployment finished. See log " & strLogFile

Function IsConnectible(ByVal strHost, ByVal intPings, ByVal intTO)
' Returns True if strHost can be pinged.
' Based on a program by Alex Angelopoulos and Torgeir Bakken.
' Requires the following variables be declared with global scope:
' m_objShell, m_strTempFile, m_objFSO.

Dim objFile, strResults

If (intPings = "") Then
intPings = 2
End If
If (intTO = "") Then
intTO = 750
End If

Const OpenAsDefault = -2
Const FailIfNotExist = 0
Const ForReading = 1

' Ping the host and redirect output to temporary file.
m_objShell.Run "%comspec% /c ping -n " & intPings & " -w " & intTO _
& " " & strHost & ">" & m_strTempFile, 0, True

' Read the temporary file.
Set objFile = m_objFSO.OpenTextFile(m_strTempFile, ForReading, _
FailIfNotExist, OpenAsDefault)
strResults = objFile.ReadAll
objFile.Close

' Determine if the host responded.
If (InStr(strResults, "TTL=") <> 0) Then
IsConnectible = True
Else
IsConnectible = False
End If
End Function

Function RunProgram(ByVal strComputer)
' Function to run a program on a remote computer.
' Returns True if successful, False otherwise.
' Requires the following variables be declared with global scope:
' m_objLogFile, m_strProgram, m_objNetwork, m_blnFirst,
' m_strDrive, m_objSourceFile, m_strCommand, m_objLocal.

Dim objRemote, objProcess, intReturnCode, objDestFile
Dim intWaitTime, blnDelete, objRemoteProcess, colProcesses

' Connect to remote computer with WMI.
On Error Resume Next
Set objRemote = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate,authenticationLevel=Pkt}!\\" _
& strComputer & "\root\cimv2")
If (Err.Number <> 0) Then
m_objLogFile.WriteLine _
"-- ### Failed to connect with WMI, Error Number: " _
& Err.Number & ", Description: " & Err.Description
On Error GoTo 0
RunProgram = False
Exit Function
End If
On Error GoTo 0
m_objLogFile.WriteLine "-- Connected with WMI"

' Check if executable running on remote computer.
Set colProcesses = objRemote.ExecQuery _
("SELECT * FROM Win32_Process " _
& "WHERE Name = '" & m_strProgram & "'")
For Each objRemoteProcess In colProcesses
m_objLogFile.WriteLine _
"-- ### Program already running, no deployment"
RunProgram = False
Exit Function
Next

' Map a drive to the root of the C: drive on remote computer.
On Error Resume Next
m_objNetwork.MapNetworkDrive m_strDrive, "\\" & strComputer & "\C$"
If (Err.Number <> 0) Then
On Error GoTo 0
' Drive mapping failed. If this is the first computer,
' try another drive letter.
If (m_blnFirst = True) Then
m_blnFirst = False
m_strDrive = "Y:"
On Error Resume Next
m_objNetwork.MapNetworkDrive m_strDrive, "\\" _
& strComputer & "\C$"
If (Err.Number <> 0) Then
On Error GoTo 0
' Try another drive letter.
m_strDrive = "X:"
On Error Resume Next
m_objNetwork.MapNetworkDrive m_strDrive, "\\" _
& strComputer & "\C$"
If (Err.Number <> 0) Then
On Error GoTo 0
m_objLogFile.WriteLine "-- ### Unable to map any drive"
RunProgram = False
Exit Function
End If
End If
Else
m_objLogFile.WriteLine "-- ### Unable to map drive " _
& m_strDrive
RunProgram = False
Exit Function
End If
End If
On Error GoTo 0
m_blnFirst = False
m_objLogFile.WriteLine "-- Drive mapped"

' Copy the executable from the local computer to the remote computer.
intReturnCode = m_objSourceFile.Copy(m_strDrive & "\\" & m_strProgram)
If (intReturnCode <> 0) And (intReturnCode <> 10) Then
' Failure detected and failure was not "file aleady exists".
m_objLogFile.WriteLine _
"-- ### Failed to copy executable file, Error: " _
& CStr(intReturnCode)
RunProgram = False
' Remove drive mapping.
m_objNetwork.RemoveNetworkDrive m_strDrive, True
m_objLogFile.WriteLine "-- Drive mapping removed"
Exit Function
End If
m_objLogFile.WriteLine "-- Executable file copied"

' Execute the program on the remote computer.
Set objProcess = objRemote.Get("Win32_Process")

' Run the program in silent mode.
intReturnCode = objProcess.Create("c:\\" & m_strCommand)
If (intReturnCode <> 0) Then
m_objLogFile.WriteLine "-- ### Failed to start program, Error: " _
& CStr(intReturnCode)
RunProgram = False
' Remove drive mapping.
m_objNetwork.RemoveNetworkDrive m_strDrive, True
m_objLogFile.WriteLine "-- Drive mapping removed"
Exit Function
End If
m_objLogFile.WriteLine "-- Program started at " & CStr(Now())

' Get reference to the file that was copied.
Set objDestFile = m_objLocal.Get("cim_datafile=""" _
& m_strDrive & "\\" & m_strProgram & """")

' Attempt to delete the file once per second for 2 minutes.
' The file cannot be deleted until the program stops running.
blnDelete = False
Wscript.Sleep 1000
For intWaitTime = 0 To 120
' Pause 1 second
Wscript.Sleep 1000
' Check if file can be deleted.
If (objDestFile.Delete() = 0) Then
blnDelete = True
Exit For
End If
Next

m_objLogFile.WriteLine "-- Deployment successful at " & CStr(Now())

If (blnDelete = False) Then
m_objLogFile.WriteLine "-- ### Caution: Unable to delete executable"
End If

' Remove drive mapping.
m_objNetwork.RemoveNetworkDrive m_strDrive, True
m_objLogFile.WriteLine "-- Drive mapping removed"

RunProgram = True

End Function
==========
If this is a VB program, perhaps you don't want to query for things like the
file to be deployed and command line parameters, but you should be able to
assign appropriate values in place of the prompts. If there is never more
than one computer, you could revise the program to work with one value of
strComputer rather than an array. For example, a version with everything
hard coded (you might take values from a form) follows. I don't include the
functions as they are unchanged. Since you also may not want anything
echoed, I've removered the Wscript.Echo statements and replaced with MsgBox
statements (or you might eliminate them all). I also replaced Wscript.Quit
with End. However, note the problem I mention after this code:
==============
' Deploy.vbs
Option Explicit

Dim strExecutable, strGroup, m_strCommand
Dim m_objFSO, m_strProgram
Dim strScriptName, strScriptPath, strScriptFolder
Dim strComputer, strParms, strLogFile, strLocal
Dim m_objLogFile, m_objNetwork, m_objShell, m_strTempFile
Dim m_objLocal, m_strDrive, m_blnFirst, m_objSourceFile
Dim intSuccess, intFailure

Const ForAppending = 8

' Specify computer NetBIOS name.
strComputer = "MyComputer"

' Specify the program to run on each remote computer.
strExecutable = "F:\MyFolder\MyUtility.exe"

' Check for the existence of the file.
Set m_objFSO = CreateObject("Scripting.FileSystemObject")
If (m_objFSO.FileExists(strExecutable) = False) Then
Call MsgBox("File " & strExecutable & " not found")
End
End If
' Retrieve program name.
m_strProgram = m_objFSO.GetFileName(strExecutable)

' Specify any command line parameters.
strParms = ""

' Construct command to execute on remote computers.
m_strCommand = m_strProgram
If (strParms <> "") Then
m_strCommand = m_strCommand & " " & strParms
End If

' Retrieve temporary file name for ping operation.
Set m_objShell = CreateObject("Wscript.Shell")
m_strTempFile = m_objShell.ExpandEnvironmentStrings("%TEMP%")
m_strTempFile = m_strTempFile & "\RunResult.tmp"

' Determine current directory.
strScriptName = Wscript.ScriptName
strScriptPath = Wscript.ScriptFullName
strScriptFolder = Left(strScriptPath, _
Len(strScriptPath) - Len(strScriptName) - 1)

' Setup log file in current directory.
strLogFile = strScriptFolder & "\Deploy.log"
Set m_objLogFile = m_objFSO.OpenTextFile(strLogFile, ForAppending, True)
m_objLogFile.WriteLine "====="
m_objLogFile.WriteLine CStr(Now()) & " Deployment started"
m_objLogFile.WriteLine "-- Deployment executable " & strExecutable
m_objLogFile.WriteLine "-- Command to execute " & m_strCommand
m_objLogFile.WriteLine "-- Deploy to computer " & strComputer

' Retrieve local computer name.
Set m_objNetwork = CreateObject("Wscript.Network")
strLocal = m_objNetwork.ComputerName

' Connect to local computer with WMI.
Set m_objLocal = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate,authenticationLevel=Pkt}!\\" _
& strLocal & "\root\cimv2")
m_objLogFile.WriteLine "-- Connected to local computer " & strLocal

' Default drive letter to map for copying executable file
' to remote computer.
m_strDrive = "Z:"
m_blnFirst = True

' Bind to local executable program file.
On Error Resume Next
Set m_objSourceFile = m_objLocal.Get("cim_datafile=""" _
& Replace(strExecutable, "\", "\\") & """")
If (Err.Number <> 0) Then
On Error GoTo 0
m_objLogFile.WriteLine "-- ### File not found: " & strExecutable
Call MsgBox("File not found: " & strExecutable)
End
End If
On Error GoTo 0

intSuccess = 0
intFailure = 0
m_objLogFile.WriteLine CStr(Now()) _
& " deploy to computer " & strComputer
If (IsConnectible(strComputer, 1, 500) = True) Then
m_objLogFile.WriteLine "-- Computer found"
If (RunProgram(strComputer) = True) Then
intSuccess = intSuccess + 1
Else
intFailure = intFailure + 1
End If
Else
m_objLogFile.WriteLine "-- ### computer not available"
intFailure = intFailure + 1
End If

' Log results.
m_objLogFile.WriteLine CStr(Now()) & " Deployment finished"
m_objLogFile.WriteLine "-- Successfully deployed to " & CStr(intSuccess) _
& " computers"
m_objLogFile.WriteLine "-- Failed to deploy to " & CStr(intFailure) _
& " computers"
m_objLogFile.WriteLine "====="
m_objLogFile.Close
=========
A problem in VB is that the Wscript.Sleep command used in Function
RunProgram is not supported in VB. You would need to remove the two Sleep
statements, but I suspect the lack of a delay will cause problems. You may
need to use a timer control instead. Note you may also want to save the log
file somewhere else (the above saves in the folder where the script
resides). Or you may skip the log file feature.
--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--
1RealTruth
2009-06-19 20:05:44 UTC
Permalink
Thank you. I'll test it out tonight when I get home from work.

I was checking out more of your website last night. You have a lot of
really nice programs.

Thanks again,
Kevin
--
1RealTruth
------------------------------------------------------------------------
1RealTruth's Profile: http://forums.techarena.in/members/106922.htm
View this thread: http://forums.techarena.in/server-scripting/843476.htm

http://forums.techarena.in
urkec
2007-10-30 20:36:02 UTC
Permalink
Post by Hulicat
Running Windows 2003 R2 I need to execute a batch on remote Windows
2003 R2 machine.
I have tried a number of things including rexec, etc.
The goal would not to deploy any additional code to the remote host.
Is there a way to this via Cscript?do I need to write a vbs script?
Thanks,
Dennis
You can try to modify this sample from the Script Center.

http://www.microsoft.com/technet/scriptcenter/scripts/os/process/procthd/pcthvb03.mspx

I think you can't run interactive processes using Win32_Process class on
Windows 2003, but I'm not sure.
--
urkec
Loading...