Psexec not outputting to log file in VB script - vbscript

I have a VB script which needs to run psexec to launch an app called md5 on a remote server. Md5 generates a hash key of a file and takes one parameter - the file path\name. I need to retrieve the has key that is generated to store in a variable. Below is the code I am using:
Set objShell = CreateObject("Wscript.Shell")
strcomputer = "remotecomputer"
tempDest = "C:\somedir"
filename = "somefile"
strCommand = "psexec -accepteula \\" & strcomputer & " -c md5.exe " & tempDest & "\" & filename & " > log.txt"
Set objExecObject = objShell.Exec("%comspec% /c " & strCommand)
Do While objExecObject.Status <> 1 'loop until previous process has finished
WScript.Sleep 100
Loop
The MD5 command is run however nothing is written to the log file. When I copy and paste strCommand (substituting all the variables for the actual data) into a cmd prompt and run it, it successfully writes the output of Md5 to the log file.
At the end of the day I just need the output of Md5, if anyone knows a better way than writing it to a log file please let me know. I have already tried using objExecObject.StdOut.Readall() to try and catch the output which resulted in random failures - sometimes it would catch the output, sometimes it wouldn't, without changing anything in the script.

Just a guess: Are you sure about what the current directory is when the script is running? Try giving an absolute path to the log file and see if it helps.

I found a solution for this. Instead of using the following code:
strCommand = "psexec -accepteula \\" & strcomputer & " -c md5.exe " & tempDest & "\" & filename & " > log.txt"
Set objExecObject = objShell.Exec("%comspec% /c " & strCommand)
Do While objExecObject.Status <> 1 'loop until previous process has finished
WScript.Sleep 100
Loop
I used this instead:
strCommand = "psexec -accepteula \\" & strcomputer & " -c md5.exe " & tempDest & "\" & filename & " > log.txt"
objShell.Run "%comspec% /c " & strCommand, 0, true
The script is now redirecting to log.txt properly.

Related

Run Rscript.exe with VBScript and spaces in path

I have the followaing run.vbs script
Rexe = "R-Portable\App\R-Portable\bin\Rscript.exe"
Ropts = "--no-save --no-environ --no-init-file --no-restore --no-Rconsole "
RScriptFile = "runShinyApp.R"
Outfile = "ShinyApp.log"
startChrome = "GoogleChromePortable\App\Chrome-bin\chrome.exe --app=http://127.0.0.1:9999"
strCommand = Rexe & " " & Ropts & " " & RScriptFile & " 1> " & Outfile & " 2>&1"
intWindowStyle = 0 ' Hide the window and activate another window.'
bWaitOnReturn = False ' continue running script after launching R '
' the following is a Sub call, so no parentheses around arguments'
CreateObject("Wscript.Shell").Run strCommand, intWindowStyle, bWaitOnReturn
WScript.Sleep 1000
CreateObject("Wscript.Shell").Run startChrome, intWindowStyle, bWaitOnReturn
It works pretty well in most cases except when the user puts the run.vbs script in a folder with spaces in its name: e.g. if run.vbs is in folder "foo bar", the user gets the error : "C:\Users\[user name]\Desktop\foo" not recognized as internal command...
I don't understand why Rscript.exe looks for the absolute path before running even if it's called from its parent directory using relative path.
I heard about the double quote solution using the absolute path but it doesn't seem to work with .exe scripts (it does though with .bat and .cmd)
Thanks for any help!
Below code will help you
Dim oShell As Object
Set oShell = CreateObject("WScript.Shell")
'run command'
Dim oExec As Object
Dim oOutput As Object
Set oExec = oShell.Exec("C:\Program Files\R\R-3.2.3\bin\Rscript.exe C:\subfolder\YourScript.R " & """" & var1 & """")
Set oOutput = oExec.StdOut
handle the results as they are written to and read from the StdOut object
Dim s As String
Dim sLine As String
While Not oOutput.AtEndOfStream
sLine = oOutput.ReadLine
If sLine <> "" Then s = s & sLine & vbCrLf
Wend

Call command program that requires user input

Using VBScript (run through cscript), how can I call another command program (pscp in this case), which also requires user input, etc.?
The purpose is that the initial VBScript will gather the parameters (password, user, etc.), then the pscp command
pscp -r -pw password copyFromPath user#host:copyToPath
can be issued and the user will be able to see the output from the pscp command, as well as being able to input (if, for example, they gave the wrong password and are required to input it again).
I currently have:
' create the command, that calls pscp from cmd
Dim comSpec : comSpec = objShell.ExpandEnvironmentStrings("%comspec%")
Dim command : command = comspec & " /C " & """" & "pscp -r -pw " & "^""" & (Replace(pscpPassword,"""","\^""")) & "^"" " _
& "^""" & (windowsPath) & "^"" " _
& pscpUser & "#" & pscpHostName & ":" & Replace(linuxPath," ","\ ") & """"
Dim objExec : Set objExec = objShell.Exec(command)
An alternative I came up with for generating command was:
Dim command : command = "pscp -r -pw " & Chr(34) & Replace(pscpPassword,"""","\""") & Chr(34) & " " _
& Chr(34) & windowsPath & Chr(34) & " " _
& pscpUser & "#" & pscpHostName & ":" & Replace(linuxPath," ","\ ")
But neither of these allow me to interact with pscp once it's called.
Edit
The fact that I'm calling pscp is almost irrelevant. I could be calling any program which asks for user input and displays things to stdout and stderr
I put all the commands together into a script (separated with &), then run them all after the loop. I append "& pause" to keep the window open (see comments under question for full details)

Run cmd from vbscript silently

I created the following runas.vbs script:
**************
Option explicit
Dim oShell, k
Const PASSWORD = "Pass123~"
set oShell= Wscript.CreateObject("WScript.Shell")
WScript.Sleep 500
oShell.run("RunAs /noprofile /user:%computername%\postgres " & Chr(34) & "cmd /c\" &
Chr(34) & WScript.Arguments(0) & "\" & Chr(34) & Chr(34))
WScript.Sleep 1000
For k=1 To Len(PASSWORD)
WScript.Sleep 200
oShell.SendKeys Mid(PASSWORD,k,1)
Next
Wscript.Quit
**************
I use this vbscript in a Batch file to run initdb.exe (Postgresql).
Used as:
cscript //Nologo //B runasNSPostgres.vbs ""%LG_PATH%\initdb.exe" --locale=C --encoding=UTF-8 -U %DBADMIN% -D "%DBDATA%""
When this command is executed, another command prompt screen opens up which starts the initdb processing. I do not want the new cmd prompt screen to show up. I want the initdb.exe to run in the background.
If you hide the command prompt window, you won't be able to use SendKeys to send it your password keystrokes.
You can use another method, though. Try using the ECHO command and pipe its output to RunAs.
oShell.Run "echo " & PASSWORD & " | runas /noprofile ...", 0
Use a 0 as the 2nd parameter to prevent the window from appearing.

Why do we need generate a temporary file when remote uploading to FTP?

I am so confused with this, I am trying to upload data to FTP through VBS script and it works fine for a single file file but doesn't upload multiple files when I add the script inside a loop.
Also , why do we need to generate a temporary file when remote uploading to FTP,
I mean to say this,
this is the script I am using,
Dim fso, folder, files, strPath
Set fso = CreateObject("Scripting.FileSystemObject")
strPath = "E:/Test"
Set folder = fso.GetFolder(strPath)
Set files = folder.Files
Const hostname = "ftp.domain.com"
Const port = 21
Const username = "username"
Const password = "password"
Const remoteDir = "/"
Const useDefaultsExclusively = True
Const skipConfirmation = True
For each item In files
If InStr(1, item.Name, "txt") <> 0 Then
defaultFile = item.Name
localFile = fso.getFileName(defaultFile)
localDir = fso.getParentFolderName(defaultFile)
Set shell = CreateObject("WScript.Shell")
tempDir = shell.ExpandEnvironmentStrings("%TEMP%")
' temporary script file supplied to Windows FTP client
scriptFile = tempDir & "\" & fso.GetTempName
' temporary file to store standard output from Windows FTP client
outputFile = tempDir & "\" & fso.GetTempName
'input script
script = script & "lcd " & """" & localDir & """" & vbCRLF
script = script & "open " & hostname & " " & port & vbCRLF
script = script & "user " & username & vbCRLF
script = script & password & vbCRLF
script = script & "cd " & """" & remoteDir & """" & vbCRLF
script = script & "binary" & vbCRLF
script = script & "prompt n" & vbCRLF
script = script & "put " & """" & localFile & """" & vbCRLF
script = script & "quit" & vbCRLF
Set textFile = fso.CreateTextFile(scriptFile, True)
textFile.WriteLine(script)
' bWaitOnReturn set to TRUE - indicating script should wait for the program
' to finish executing before continuing to the next statement
shell.Run "%comspec% /c FTP -n -s:" & scriptFile & " > " & outputFile, 0, TRUE
Wscript.Sleep 10
' open standard output temp file read only, failing if not present
Set textFile = fso.OpenTextFile(outputFile, 1, 0, -2)
results = textFile.ReadAll
textFile.Close
End If
Next
fso.DeleteFile(scriptFile)
fso.DeleteFile(outputFile)
Why do we creating a Temporary file with this code, :S
Set shell = CreateObject("WScript.Shell")
tempDir = shell.ExpandEnvironmentStrings("%TEMP%")
' temporary script file supplied to Windows FTP client
scriptFile = tempDir & "\" & fso.GetTempName
' temporary file to store standard output from Windows FTP client
outputFile = tempDir & "\" & fso.GetTempName
Set textFile = fso.CreateTextFile(scriptFile, True)
textFile.WriteLine(script)
' bWaitOnReturn set to TRUE - indicating script should wait for the program
' to finish executing before continuing to the next statement
shell.Run "%comspec% /c FTP -n -s:" & scriptFile & " > " & outputFile, 0, TRUE
Wscript.Sleep 10
' open standard output temp file read only, failing if not present
Set textFile = fso.OpenTextFile(outputFile, 1, 0, -2)
results = textFile.ReadAll
textFile.Close
Although I am looping through the script , it must upload every txt file inside current directory but it uploads only the first one, why is it so ?
When I print the current file i.e
MsgBox defaultfile
it display the name of each txt file inside the current folder but uploads first file only.
There is no native method of live automation for FTP. This is actually a scripting workaround. Your script is creating a text file with FTP instructions. Then, it launches FTP from the command line using the -s switch. That -s switch allows you to provide a text file containing session commands for FTP.exe to execute before closing. So while your script isn't actually automating the FTP program directly, it simulates automation by running FTP in "unattended mode". You can get a better understanding by opening a command prompt and typing ftp /?.
[EDIT]
I apologize, I missed your second question. Your script is only uploading the first file because it loops around the CreateTextFile method. This method is failing after the first attempt because the file already exists. What you really ought to do is loop around adding your files to the temporary file and then execute FTP only once. Your web server will appreciate the break as well.
Dim fso, folder, files, strPath
Set fso = CreateObject("Scripting.FileSystemObject")
strPath = "E:/Test"
Set folder = fso.GetFolder(strPath)
Set files = folder.Files
Const hostname = "ftp.domain.com"
Const port = 21
Const username = "username"
Const password = "password"
Const remoteDir = "/"
Const useDefaultsExclusively = True
Const skipConfirmation = True
tempDir = shell.ExpandEnvironmentStrings("%TEMP%")
' temporary script file supplied to Windows FTP client
scriptFile = tempDir & "\" & fso.GetTempName
' temporary file to store standard output from Windows FTP client
outputFile = tempDir & "\" & fso.GetTempName
Set textFile = fso.CreateTextFile(scriptFile, True)
'input script
textFile.WriteLine("open " & hostname & " " & port)
textFile.WriteLine("user " & username)
textFile.WriteLine(password)
textFile.WriteLine("cd " & Chr(34) & remoteDir & Chr(34))
textFile.WriteLine("binary")
textFile.WriteLine("prompt n")
For Each item In files
If InStr(1, item.Name, "txt") <> 0 Then
textFile.WriteLine("put " & Chr(34) & item.Path & "\" & item.Name & Chr(34))
End If
Next
textFile.WriteLine("quit")
textFile.Close
Set shell = CreateObject("WScript.Shell")
' bWaitOnReturn set to TRUE - indicating script should wait for the program
' to finish executing before continuing to the next statement
shell.Run "%comspec% /c FTP -n -s:" & scriptFile & " > " & outputFile, 0, True
WScript.Sleep 10
' open standard output temp file read only, failing if not present
Set textFile = fso.OpenTextFile(outputFile, 1, 0, -2)
results = textFile.ReadAll
textFile.Close
fso.DeleteFile(scriptFile)
fso.DeleteFile(outputFile)

VBscript and CMD writing into a text file

I am writing a script that executes and write everything to the file
here is example,
I stored the complete command in the variable 'Command' ,
Command = "ftp ftp.xyz.com 21 " & vbCRLF
and then executing it in command prompt,
shell.Run "%comspec% /c FTP " & Command & " > " & E:/abc.txt, 0, TRUE
but when this program execute it won't write anything to the text file because this is an incomplete command, this command on execution prompt user to input username and password of FTP,
how can i do this , that my programm automatically input username and password when prompt and then write everything to file ?
You need to run FTP using an unattended script. (Try ftp /? and look at the -s switch.)
It looks like this:
Const HOSTNAME = "ftp.myserver.com"
Const USERNAME = "Login"
Const PASSWORD = "password"
Set WshShell = CreateObject("WScript.Shell")
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFile = objFso.CreateTextFile("session.txt")
With objFile
.WriteLine "USER username"
.WriteLine "password"
.WriteLine "cd /public_html/" ' continue adding commands like this
.Close
End With
strOutput = "C:\somefilepath\output.txt"
strCommand = "%systemroot%\System32\ftp.exe -s:session.txt > " & strOutput
strCommand = WshShell.ExpandEnvironmentStrings(strCommand)
WshShell.Run strCommand, 0, vbTrue
objFso.DeleteFile "session.txt", vbTrue
You can read more in my article Using FTP in WSH on ASP Free. I also answered a related question here.

Resources