FTP:Upload file to FTP and verify - windows

I am using VBS to
Upload a file to FTP
Verify the upload process
I am using the method which creates a text file, fills it with the appropriate command and then execute it using ftp.exe in windows.
FTPCommand = "%systemroot%\System32\ftp.exe -s:session.txt"
FTPCommand = objshell.ExpandEnvironmentStrings(FTPCommand)
objshell.Run FTPCommand,, vbTrue
fso.DeleteFile "session.txt", vbTrue
Part 1 is done using this code:
Set SessionFile = fso.OpenTextFile("session.txt", 2, vbTrue)
With SessionFile
.WriteLine "open abcd.com"
.WriteLine "username"
.WriteLine "pwd"
.WriteLine "cd /Test/Test1"
.WriteLine "put """ & File.Path & """"
.WriteLine "quit"
.Close
End With
FTPCommand = "%systemroot%\System32\ftp.exe -s:session.txt"
FTPCommand = objshell.ExpandEnvironmentStrings(FTPCommand)
objshell.Run FTPCommand,, vbTrue
fso.DeleteFile "session.txt", vbTrue
And Part 2 is done using this code:
Set SessionFile = fso.OpenTextFile("session.txt", 2, vbTrue)
With SessionFile
.WriteLine "open abcd.com"
.WriteLine "username"
.WriteLine "pwd"
.WriteLine "cd /Test/Test1"
.WriteLine "ls"
.WriteLine "close"
.WriteLine "bye"
.Close
End With
FTPCommand = "%systemroot%\System32\ftp.exe -s:session.txt"
FTPCommand = objshell.ExpandEnvironmentStrings(FTPCommand)
set ObjExec=objshell.exec(FTPCommand)
DO WHILE ObjExec.status=0 : wscript.sleep 50 : LOOP
StrTemp=ObjExec.stdout.readall
IF instr(1,StrTemp,File.Name,1)<>0 THEN
AlertMessage = AlertMessage & vbTab & "STATUS: UPLOAD SUCCESSFUL" & vbCrLf & vbCrLf
ELSE
AlertMessage = AlertMessage & vbTab & "STATUS: UPLOAD FAILED" & vbCrLf & vbCrLf
END IF
fso.DeleteFile "session.txt", vbTrue
The problem is that (in part 2 code) the code after
DO WHILE ObjExec.status=0 : wscript.sleep 50 : LOOP
never returns.So the file gets uploaded but the code to check the status never returns.
The session.txt file does not get delete and when I execute the command
%systemroot%\System32\ftp.exe -s:session.txt
manually it indeed shows me the list of files (because of ls command).
I have 3 questions:
Why it does not return. Where to start debugging from?
Is there anyway I can upload the file and check its status(maybe by
the error code returned by the ftp command after the "put" command).
Is there is an incorrect directory specified in the code to upload
file, the cd command fails and it incorrectly "puts" the file in the
root folder. same goes for the code checking the file upload. So
even if the directory specified in wrong, the program returns it as
successful
Edit 1:
I tried it using
.WriteLine "cd /Test"
and it worked. Is that directory switching (two folders deep)causing the problem ?
Edit 2:
I ran the ls command manually and it ran fine. The output is:
226 Transfer complete.
ftp: 586493 bytes received in 4.28Seconds 137.00Kbytes/sec.
Is 586493 bytes too much for this ?
I believe the problem may be:
1)The large no of files returned by LS command.
2)The directory structure I am accessing.
Edit:3
From this microsoft website it looks like the above point 1 is the culprit:
A console application's StdOut and StdErr streams share the same
internal 4KB buffer. In addition, the WshScriptExec object only
provides synchronous read operations on these streams. Synchronous
read operations introduce a dependency between the calling script
reading from these streams and the child process writing to those
streams, which can result in deadlock conditions.

I believe the problem is the way you read the stdout from the process. I use this technique succesfully as follows, sorry, I have no time to adapt your script and try it out, so that is up to you.
The following executes a ping to check if the server is online.
Function IsOnline(Address)
Dim strText
IsOnline = False
Set oExecObj = oShell.Exec("%comspec% /c ping -a -n 1 -w 20 " & Address)
Do While Not oExecObj.StdOut.AtEndOfStream
strText = oExecObj.StdOut.ReadAll()
If Instr(strText, "Reply from") > 0 Then
IsOnline = True
Exit Function
End If
Loop
End Function

Related

VBScript script as a wrapper for a silent Batch file

I have a batch file that gets some parameters from the command line and returns some values into STDOUT.
I want the batch file to be "silent" (such that the console is not shown), and found out probably the only possibility of using vbs script.
I used this thread for implementing the argument forwarding to the batch file in VBS.
Then, I used the following command for calling the batch file I wrapped:
CreateObject("WScript.Shell").Run batchFilePath & " " & Trim(arglist), 0, False
It turns out that my batch file does run, but its STDOUT is discarded somewhere, and does not make its way back to whom called the VBS script. I.e. the batch file's STDOUT is not redirected into the VBS script's STDOUT.
How can I make the batch file's STDOUT being redirected to the VBS script STDOUT, such that if I start the VBS script from some shell, the batch file's output will be printed to the shell too?
Use Exec instead of Run, like this:
set objShell = CreateObject( "WScript.Shell" )
cmd = "echo Hello World!"
' Run the process
set objRes = objShell.Exec( "cmd /c """ & cmd & """" )
' Wait for the child process to finish
Do While objRes.Status = 0
WScript.Sleep 100
Loop
' Show whatever it printed to its standard output
Wscript.Echo "The output was:" & vbNewLine & objRes.StdOut.ReadAll()
Try this...
Intreturn = WshShell.Run("cmd /c " & path& " " & args & ">c:\batchoutput.txt", 0, true)
Set fso = CreateObject("Scripting.FileSystemObject")
Set objfile = fso.OpenTextFile("c:\batchoutput.txt", 1)
text = objfile.ReadAll
Objfile.Close
Or try this...
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objexc = WshShell.Exec("cmd /c " & command and args) 'replace command and args with proper variables
strOutputText = ""
While Not objexc.StdOut.AtEndOfStream
strOutputText = strOutputText & objexc.StdOut.ReadLine()
Loop
Msgbox strOutputText
You may need some debugging on this.

capture command line output in vbscript

Got a simple script that executes a command to a server - briefly:
//Create shell
set WshShell=CreateObject("WScript.Shell")
WshShell.run "cmd.exe"
//send commands
WshShell.SendKeys "telnet IP_ADDRESS"
WshShell.Sendkeys "dir"
Server offers feedback which I want to capture. I just need to capture the first line into a variable, and then just print that variable out to confirm.
Can you help? Thanks.
Do not use the Windows telnet client for automation purposes. The telnet client that ships with Windows was made for interactive use only.
I'd use plink (from the PuTTY suite) in batch mode for this:
plink.exe -telnet -batch IP_ADDRESS dir
The tool doesn't require installation, so you can simply deploy it alongside your script.
Run it either in a batch file using head/tail, or in a VBScript using the Exec method, so you can read from StdOut:
addr = "62.39.x.x"
port = 24
timeout = 300 'seconds
timedOut = False
cmdline = "echo ""mute near get"" | plink.exe -telnet -batch " & addr & " -P " & port
Set sh = CreateObject("WScript.Shell")
'change working directory to directory containing script and plink executable
Set fso = CreateObject("Scripting.FileSystemObject")
sh.CurrentDirectory = fso.GetParentFolderName(WScript.ScriptFullName)
'wait until command completes or timeout expires
expiration = DateAdd("s", timeout, Now)
Set cmd = sh.Exec("%COMSPEC% /c " & cmdline)
Do While cmd.Status = 0 And Now < expiration
WScript.Sleep 100
Loop
If cmd.Status = 0 Then
cmd.Terminate
timedOut = True
End If
WScript.Echo cmd.StdOut.ReadAll
If cmd.ExitCode <> 0 Then
WScript.Echo "Command terminated with exit code " & cmd.ExitCode & "."
WScript.Echo cmd.StdErr.ReadAll
WScript.Quit 1
ElseIf timedOut Then
WScript.Echo "Command timed out."
WScript.Echo cmd.StdErr.ReadAll
WScript.Quit 2
End If
It might not be the best method, but worked for me:
Windows telnet command can save the output in client side using -f arguments. Therefore, you could use:
WshShell.SendKeys "telnet -f D:\output\telnet.out IP_ADDRESS"
and at the end of your script, simply process the content of telnet.out

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.

vbscript to grab newest file on ftp site

I need to comeup with a vbscript to grab a file from an ftp site where the file name is in the form "vendor(date)(date)(random#).zip" . These files are updated daily so I need a regex or way to select the newest file on the server and download it. I know how to handle this on the local file system, but I don't know how to determine which file to get on a remote ftp server.
Funny you posted this as I just recently had to knock out a script to do almost exactly word for word what you're asking for. Basically, all you really need to do is to have your script create an FTP command file, then call it.
Use your method of choice to create a string to hold the date in whatever format you are looking for, I called it strDate and in my case it ended up being this syntax: headerinfo.13September10 Where headerinfo is a standard file header with a number attached to it.
Write out an FTP command file:
Dim objOutStream
Set objOutStream = objFSO.OpenTextFile(strCommandFile, ForWriting, True, TristateFalse)
With objOutStream
.WriteLine "USER xxxxxx" ' USERNAME
.WriteLine "xxxxxxftp" ' Password
.WriteLine "binary"
.WriteLine "prompt n"
.WriteLine "lcd " & strNetmonData ' FOLDER I'm changing into
.WriteLine "mget *." & strDate ' Get all files with today's date in it
.WriteLine "bye"
.Close
End With
Then later in your script you just call it:
WSHShell.Run "%comspec% /c FTP -n -s:" & strCommandFile & " " & strSite, 0, True
Where strSite is the IP or name of the site you are trying to connect to.
The following code will help you to get the latest file name from ftp server after which you can download it.
Const ForWriting = 2
Dim objOutStream, objjFSO, objShell
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objOutStream = objFSO.OpenTextFile("C:\temp\temp\empty.txt", ForWriting,True)
With objOutStream
.WriteLine sUsername ' USERNAME
.WriteLine sPassword ' Password
.WriteLine "cd /"& sRemotePath' FOLDER I'm changing into
.WriteLine "ls -rt tmp/listing.txt"
.WriteLine "quit"
.Close
End With
Set objShell = CreateObject("WScript.Shell")
objShell.Run "%Comspec% /c FTP -i -s:" & "C:\temp\temp\empty.txt" & " " & sSite
wait(2)
Set strCommand = objShell.Exec ("%Comspec% /c head -1 tmp\listing.txt")
Set objStdOut = strCommand.StdOut
strFilename = objStdOut.ReadLine

Psexec not outputting to log file in VB script

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.

Resources