Redirection to standard output in VBS - vbscript

When writing a script in sh or in cmd you can put a > at the end of a line to have the output of that line redirected to a file. If not, it is sent to the standard output.
Also, both have the echo command to produce output to the standard output (which can, in turn, be redirected too).
How to perform those two things in a VBS script?

Nothing different. You only need to make sure your scripts are run with the console based script host cscript.
myscript.vbs:
' WScript.Echo is a host-aware hybrid method.
' in cscript, prints the message with final a new line feed, also accepts vary arguments (0 or more).
' in wscript, shows a message dialog window
WScript.Echo "test1", "arg2"
' WScript.Stdout.Write on the other hand is a more traditional way to write to standard output stream
' print the message as is with no new line feeds
WScript.Stdout.Write "test"
WScript.Stdout.Write "2"
Command:
cscript myscript.vbs
Output:
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.
test1 arg2
test2
There's also an option to prevent to display banner on the output.
cscript //NoLogo myscript.vbs
Output:
test1 arg2
test2
Redirection:
cscript //NoLogo myscript.vbs>output.txt
PS: cscript is the default script interpreter only on Windows Server operating systems. Otherwise the default is wscript. Therefore it is a good practice to run the scripts with a specific script host.
To change the default script host have a look at Running Your Scripts
Useful Links:
Echo Method
Write Method
Running Your Scripts

Related

How to redirect Windows cmd output to a text file?

I am trying to monitor the cmd output of a certain executable .exe and use it for another process running at the same time.
The problem is that all cmd redirecting functions ( '>','>>','<' and '|') would only redirect the output after a successful return of the last command.
What I wanted to do is to generate some kind of streaming log of my cmd.
You can run in your process in background by using
start /b something.exe > somefile.txt
Windows 20H2: Redirection works fine when logged in as true administrator but will NOT work when logged in as a created administrative user. I have used it for years to redirect the output of a multi target backup system using Hobo copy to put the console output in a log file. I have never been able to get it to work successfully in Windows 10 ver 19 or 20 on a created administrative user.
You can prefix the command with "cmd /c" to start a new command prompt, and redirect the output of the command prompt:
cmd /c YOUR CODE > TextFileName.txt
Note : Use ONLY single greater than (>)
Since the output of cmd is going to TextFileName.txt.
Whereas this misses the error output, so you are not able to see : Request to UnKnown timed-out for each failed address.

How to combine batch file and expect script in cygwin?

i have an application on windows that requires user name and password to start, but i don't want user to enter the user/password, so i created a script to interact with CMD interface to enter the password, using cygwin on windows 8.1, but i can't find expect command on the Cygwin, and i would like to ask also if my script has any issue.
below is the script
#!/usr/bin/expect
sh C:\Users\Osama.Barakat\Desktop\batchfile.bat
expect "Enter the password for administrator:"
send "Pa$$w0rd"
interact
I identified two issues in your question:
How to perform batch files in cygwin/bash?
How to get expect installed/running in cygwin/bash?
1. How to perform batch files in cygwin/bash?
In your sample code, I found
---8<---
sh C:\Users\Osama.Barakat\Desktop\batchfile.bat
--->8---
IMHO, this is a mistake. I believe that bash will try to execute anything as script regardless of the script file extension. But if batchfile.bat is really a batch file then it should be called with the correct interpreter (i.e. cmd.exe) instead.
I tried it to see if there is any issue in the cygwin bash but it worked. My sample batch file test-expect.bat:
#echo off
rem output
echo Hello %USERNAME%
rem input
set /p INPUT= Enter input:
rem output
echo Input: %INPUT%
...tested in bash on cygwin:
$ cmd /c test-expect.bat
Hello Scheff
Enter input: Hello cmd
Input: Hello cmd
$
OK, done.
2. How to get expect installed/running in cygwin/bash?
To install expect on cygwin I googled a little bit and found Installation of Cygwin, expect and Ssh. Then, I started the cygwin-setup setup-x86.exe and tried something else:
On the "Select Packages" page, I set View to Full and Search to expect. I got a list of four entries only where the first was: "expect: Tool for automating interactive applications" (Category: Tcl). I choosed this for installation and had to confirm another package as dependency.
After installation, I tried this in an interactive bash:
$ which expect
/usr/bin/expect
$
OK - looks quite good.
Combining CMD.EXE and expect
To put all together, I wrote another test script test-expect.exp:
#!/usr/bin/expect
spawn cmd /c test-expect.bat
expect "Enter input: "
send "Hello expect\r"
interact
Tested in bash on cygwin:
$ ./test-expect.exp
spawn cmd /c test-expect.bat
Hello Scheff
Enter input: Hello expect
Input: Hello expect
$
Well, it seems to work.

VBscript - wscript.echo perfect in Windows 7 - does not work in Window 2012

I've created the following vbs script to show my problem
Wscript.echo "My very first script."
Dim price, vat, net
vat = 16.0
net = 100.0
price = net * (1.0 + vat/100.0)
WScript.Echo "Price: ", price, "US $ Tax: ", vat, "% ", price - net, " US $"
When I run this on my laptop (Windows 7 Professional) everything is beautiful
It displays the first echo message - I click on OK
It then displays the second echo message - again I get to click OK and the script ends
I then upload it to our server (Windows Server 2012 Standard) and
It displays the first Wscript.echo for about 2 seconds then ends.
If I comment out the first message it then displays the second message - again for a couple of seconds then ends.
Can anyone shed any light on this?
It looks like the Timeout
//T:nn Time out in seconds: Maximum time a script is permitted to run
is set to a low value. You can check this assumption by executing
WScript.Echo WScript.Timeout
See the section "Setting a Time-out Value for a Script" in the docs.
You can change the (default) timeout via the command line interface (//T, //S):
cscript
Usage: CScript scriptname.extension [option...] [arguments...]
Options:
//B Batch mode: Suppresses script errors and prompts from displaying
//D Enable Active Debugging
//E:engine Use engine for executing script
//H:CScript Changes the default script host to CScript.exe
//H:WScript Changes the default script host to WScript.exe (default)
//I Interactive mode (default, opposite of //B)
//Job:xxxx Execute a WSF job
//Logo Display logo (default)
//Nologo Prevent logo display: No banner will be shown at execution time
//S Save current command line options for this user
//T:nn Time out in seconds: Maximum time a script is permitted to run
//X Execute script in debugger
//U Use Unicode for redirected I/O from the console
and/or the "Script" properties of the .vbs file.
Before experimenting, however, you should talk to the admin of that server.
(BTW: Whatever you do, don't change your correct WScript.Echo lines to something wrong like MsgBox("Price"))

vbs how to get result from a command line command

I want to get the result of a simple command from the command line (cmd.exe) using a Windows script (.vbs). How is this done? I haven't been able to find a good/simple example or explanation. You could use the "date" or "time" command to provide an example with.
Such as:
P.S. I am able to write the script code that opens cmd.exe and sends the command.
Thanks!
When in doubt, read the documentation. You probably want something like this:
Set p = CreateObject("WScript.Shell").Exec("%COMSPEC% /c date /t")
Do While p.Status = 0
WScript.Sleep 100
Loop
WScript.Echo p.StdOut.ReadAll
Edit: When using Exec() you pass input via the .StdIn descriptor, not via SendKeys() (which is a rather unreliable way of passing input anyway).
%COMSPEC% is a system environment variable with the full path to cmd.exe and the /c option makes cmd.exe exit after the command (date /t in the example) is finished.
If the command indicates success/failure with an exit code, you can check the ExitCode property after the command finished.
If p.Status <> 0 Then WScript.Echo p.ExitCode
Edit2: Instead of using atprogram interactively, can you construct commandlines that will perform particular tasks without user interaction? With non-interactive commandlines something like this might work:
prompt = "C:\>"
atprogram_cmdline_1 = "atprogram.exe ..."
atprogram_cmdline_2 = "atprogram.exe ..."
'...
Function ReadOutput(p)
text = ""
Do Until Right(text, Len(prompt)) = prompt
text = text & p.StdOut.Read(1)
Loop
ReadOutput = text
End Function
Set cmd = CreateObject("WScript.Shell").Exec("%COMSPEC% /k")
ReadOutput cmd ' skip over first prompt
cmd.StdIn.WriteLine(atprogram_cmdline_1)
WScript.Echo ReadOutput(cmd)
cmd.StdIn.WriteLine(atprogram_cmdline_2)
WScript.Echo ReadOutput(cmd)
'...
cmd.Terminate ' exit CMD.EXE
%COMSPEC% /k spawns a command prompt without running a command. The /k prevents it from closing. Because it isn't closing automatically, you can't use the While p.Status = 0 loop here. If a command needs some time to finish, you need to WScript.Sleep a number of seconds.
Via cmd.StdIn.WriteLine you can run commandlines in the CMD instance. The function ReadOutput() reads the output from StdOut until the next prompt appears. You need to look for the prompt, because read operations are blocking, so you can't simply say "read all that's been printed yet".
After you're finished you quit CMD.EXE via cmd.Terminate.

Passing values to intermediate (runtime) input prompts of Windows command

I have a windows exe which displays some copyright information, connects to a server and then prompts for input of username and password.
So whenever I run this, I have to wait for the prompt to input username and password.
I generally type ahead the username, , password after the command starts displaying copyright information, but that is a crude way.
Is there a better way to pass parameters to a input prompt of windows command, in a batch file, so that i can avoid typing them always?
P.S. In Linux we do this using the << operator like this
linux_command <<delimiter
inputparamvalue1
inputparamvalue2
delimiter
linux_command will run and on first input prompt, it reads inputparamvalue1 and at next input prompt, it reads inputparamvalue2
In response to James, thanks for the advice on security. I will take care of that.
I tried to implement your solution but that did not work.
These are my files. Please see if you get any hint.
vpn.bat
# echo off
"C:\Program Files (x86)\Cisco\Cisco AnyConnect VPN Client\vpncli.exe" connect "mycompanyvpnsite.com"
login.txt
myusername
mypassword
startvpn.bat
#ECHO OFF
CALL vpn.bat < login.txt
ECHO I'm back!
Result
D:\>startvpn.bat
Cisco AnyConnect VPN Client (version 2.5.6005) .
Copyright (c) 2004 - 2010 Cisco Systems, Inc.
All Rights Reserved.
>> state: Disconnected
>> notice: Ready to connect.
>> registered with local VPN subsystem.
>> state: Disconnected
>> notice: Ready to connect.
VPN> >> contacting host (mycompanyvpnsite.com) for login information...
>> notice: Contacting mycompanyvpnsite.com.
VPN>
>> Please enter your username and password.
Username: [myusername] Password:
Username myusername which it is showing is cached from my previous manual logins. So it appears that this run did not take any values from the login.txt.
If I had executed my vpn.bat alone without any params, i get prompt like this
VPN>
>> Please enter your username and password.
Username: [myusername] <i press enter to take the cached value>
Password: ******** <i enter password and press enter>
and it connects.
The vpn client does not have privilege to specify password on command line, that's why I am trying this way.
i've got a working code! It's similar to James K's but with a few bugs hammered out. Once again, I want to reiterate that this is rather insecure because it exposes your password in an unencrypted setting. that being said:
'Anyconnect login script
Dim oShell
Set oShell = WScript.CreateObject("WScript.Shell")
' rather clunky way of selecting the correct directory - open to suggestion
oShell.Run "cmd /k cd %PROGRAMFILES(x86)%\Cisco & cd Cisco* & vpncli.exe connect MYCOMPANYVPN.COM"
' sleep of 100 neccessary or else it opens multiple cmd windows
Wscript.sleep 100
' activate correct window
oShell.AppActivate "Connect"
' optional ipsec Identifier used for multiple VPN profiles on the same server
'(if you don't have one, just comment this out)
oShell.SendKeys "IPSECID{ENTER}"
' Send Username and Password to Active Window.
oShell.SendKeys "USERNAME{ENTER}"
oShell.SendKeys "USERPASSSWORD{ENTER}"
oShell.SendKeys "exit{ENTER}"
Good luck!
Saving your username and password in a file to automate login processes is a very bad idea and invalidates any security that requiring usernames and passwords supplies because anyone who get's electronic or physical access to your computer will have access to your plain-text username and password.
That said, in DOS / Windows Command Prompt you will need an extra file containing your username and password like so:
LOGIN.TXT
MyUserName
MyPassword
Then pipe that file into your command like this:
#ECHO OFF
CALL Command_Or_Batch < login.txt
ECHO I'm back!
This will act just as if you were at the console and typed MyUserName[ENTER] MyPassword[ENTER].
login.txt is just a plain vanilla text file, and does not need the .txt extension, or any extension at all for that matter.
The CALL statement is only necessary when launching another batch file, if you want it to, when finished, continue executing in the original calling batch file. Using CALL makes no difference when calling an executable (anything other than a batch file).
EDIT: As per your comments, I believe that you need to do this to get it to work:
# echo off
"C:\Program Files (x86)\Cisco\Cisco AnyConnect VPN Client\vpncli.exe" connect "mycompanyvpnsite.com" < login.txt
In this case you redirect to your vpncli.exe, but I believe that this will have the side-effect of making vpncli.exe ONLY accept input from login.txt, and not from the keyboard at all until vpncli.exe exits. Meaning that you'll need to automate (store in login.txt) all the stuff you would normally need to type in. This should not be a problem unless you need to manually interact with vpncli.exe later on.
EDIT: Since vpncli.exe seems to be clearing the buffer before reading any keystrokes, I suggest that possibly using VBS might get you where you're wanting to go.
VPN.VBS
'VBScript Example
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "C:\Program Files (x86)\Cisco\Cisco AnyConnect VPN Client\vpncli.exe connect mycompanyvpnsite.com"
' You need to know the name of the window, It should be in the upper left corner
' I'm guessing that it will be the filename of the executible
WshShell.AppActivate "vpncli.exe"
' Send Username and Password to Active Window.
WshShell.SendKeys "MyUserName{ENTER}"
WshShell.SendKeys "MyPassword{ENTER}"
But I can't be sure. I've had problems testing this, though I'm just bouncing back and forth between batch files and VBS scripts.
Though I do know if you replace the WshShell.Run and WshShell.AppActivate with the following two lines that...
WshShell.Run "%windir%\notepad.exe"
WshShell.AppActivate "Notepad"
...notepad will open and the following two lines will appear:
MyUserName
MyPassword
If this doesn't work for you, I'm thinking about deleting this answer entirely since it only contains suggestions that haven't worked.

Resources