How to write a ping to a text file using VBS - scripting

If I am using VBS to run some CMD commands, in this example ping, how could I write the command to a text file using VBS not DOS?
Set objCmdTest = WScript.CreateObject ("WScript.Shell")
Set Output = CreateObject("Scripting.FileSystemObject").OpenTextFile("C:\vbs\test.txt",8,true)
Output.WriteLine (objCmdTest.run ("ping failboat"))
Output.WriteLine (objCmdTest.run ("ping 8.8.8.8"))
So this is what I'm working with however what happens is; The script runs, the file is made, 2 command prompts open to run the pings and finally the text inside the file reads:
0
0
When I'd much prefer it to have the ping output.
FYI: Please don't offer suggestions that require me to use DOS for the writing, I'd like to see how VBS can do what I need for multiple reasons, thanks!

The instruction Output.WriteLine (objCmdTest.run ("ping failboat")) will write the return value of the Run method to the output file. If you want to append the command output to an output file you have to either redirect the output in the command:
objCmdTest.run "%COMSPEC% /c ping failboat >>C:\vbs\test.txt", 0, True
or use Exec instead of Run:
Set ping = objCmdTest.Exec("ping failboat")
Do While ping.Status = 0
WScript.Sleep 100
Loop
Output.WriteLine ping.StdOut.ReadAll

WScript.Shell's run method returns the process's exit code. In order to get access to an application's output, you need to use the exec method instead, and use the object that returns to get access to the process's standard output through its StdOut property.

Related

how to Add multiple cmd shell command lines vb.net

I want to run a few command lines by shell after I run the first command
I use the following command but it does not work
Shell("cmd.exe /k" + "<adb shell 1> & <su 2> & <mv /data/local/tmp/build2.prop /system/build.prop 3>")
For example, I execute the following commands in cmd
adb shell
su
mv /data/local/tmp/build2.prop /system/build.prop
How can I run vb.net?
edite -----------------------------------------------------
Honestly, we need to transfer the file to vb.net into the Android device /system folder
We use androidlib by the following command, but it does not work
Adb.ExecuteAdbCommand(Adb.FormAdbCommand("shell", "su", "-c", "mount -o remount, rw /system"))
Adb.ExecuteAdbCommand(Adb.FormAdbCommand("shell", "su", "-c", "cat /data/local/tmp/build2.prop > /system/build.prop"))
This command executes the read-only file system error
What you appear to be after is executing additional commands inside adb, in which case what you're currently doing will not work. Combining commands with the ampersand & will execute each command separately, not in a previously opened process.
To do what you want you've got to redirect standard input for the adb process, not CMD.
Redirecting the input is simply a way of changing where the process gets its input from. Instead of getting it from the keyboard input stream (the user) you can redirect it to a different stream which you have control over.
Untested, but something like this should work:
Dim psi As New ProcessStartInfo("adb", "shell 1")
psi.UseShellExecute = False
psi.RedirectStandardInput = True
Dim p As Process = Process.Start(psi)
Dim InputStream As StreamWriter = psi.StandardInput
InputStream.WriteLine("su 2")
InputStream.WriteLine("mv /data/local/tmp/build2.prop /system/build.prop 3")

Execute any bash command, get the results of stdout/stderr immediatly and use stdin

I would like to execute any bash command. I found Command::new but I'm unable to execute "complex" commands such as ls ; sleep 1; ls. Moreover, even if I put this in a bash script, and execute it, I will only have the result at the end of the script (as it is explain in the process doc). I would like to get the result as soon as the command prints it (and to be able to read input as well) the same way we can do it in bash.
Command::new is indeed the way to go, but it is meant to execute a program. ls ; sleep 1; ls is not a program, it's instructions for some shell. If you want to execute something like that, you would need to ask a shell to interpret that for you:
Command::new("/usr/bin/sh").args(&["-c", "ls ; sleep 1; ls"])
// your complex command is just an argument for the shell
To get the output, there are two ways:
the output method is blocking and returns the outputs and the exit status of the command.
the spawn method is non-blocking, and returns a handle containing the child's process stdin, stdout and stderr so you can communicate with the child, and a wait method to wait for it to cleanly exit. Note that by default the child inherits its parent file descriptor and you might want to set up pipes instead:
You should use something like:
let child = Command::new("/usr/bin/sh")
.args(&["-c", "ls sleep 1 ls"])
.stderr(std::process::Stdio::null()) // don't care about stderr
.stdout(std::process::Stdio::piped()) // set up stdout so we can read it
.stdin(std::process::Stdio::piped()) // set up stdin so we can write on it
.spawn().expect("Could not run the command"); // finally run the command
write_something_on(child.stdin);
read(child.stdout);

Remote Netstat to STDOUT with WMIC?

I would like to use WMIC to retrieve the output of a "netstat" command on a remote computer. The actual execution of the following command executes without error and I see the output popup briefly within a new window:
wmic /node:server1 process call create "netstat.exe -ano"
With that being said, I need to pipe the output of the process window to STDOUT, and have tried:
wmic /node:server1 process call create "netstat.exe -ano > C:\temp\test.txt"
However, that does not work. I have also tried the /output:STDOUT option, however, that only reports the execution of the command:
Executing (Win32_Process)->Create() Method execution successful. Out Parameters: instance of __PARAMETERS {
ProcessId = 5044;
ReturnValue = 0; };
Does anyone know how I can go about using WMIC to retrieve the actual output from the new window that was opened in order to process the data?
Thanks in advance!
The > symbol behaves as operator of redirection in cmd.exe, not in netstat.exe.
In fact, wmic process call create "netstat.exe -ano > C:\temp\test.txt" is about to run the same as netstat.exe -ano ^> files\nstat.txt (try it from command line).
Next command works (unfortunately, I can't try it with /node:"server1" against a remote computer at the moment):
wmic process call create "cmd /C > C:\temp\test.txt 2>&1 netstat.exe -ano"

Why "Process" class in vb.net doesn't capture errors from cmd.exe?

I'm trying to run dos commands within vb.net program and capture output. I have the following code:
Dim CMDServer As Diagnostics.ProcessStartInfo
Dim CMDReply As Diagnostics.Process
CMDServer = New Diagnostics.ProcessStartInfo
CMDServer.FileName = "cmd.exe"
CMDServer.UseShellExecute = False
CMDServer.RedirectStandardOutput = True
CMDServer.CreateNoWindow = True
CMDServer.Arguments = "/C " + command
CMDReply = Process.Start(CMDServer)
Dim Reply As String = CMDReply.StandardOutput.ReadToEnd()
The code runs successfully if command is a valid dos command, and I get the output in Reply. If the command have no output ( eg: cd\ ) Reply is null. The problem is Reply is null even when the command is invalid. How to capture errors like "command is not recognized as an internal or external command...", "The system cannot find the path specified.." etc.. Please help me. Thanks..
Error messages come in a different output stream called StandardError. Just use a StreamReader or read it directly. Of course, the RedirectStandardError-Property of your ProcessStartInfo instance must be set to True.
Also, there is a ExitCode-Property which returns the ExitCode of the program after it has finished. 0 means 'successful'. Other error codes can be found in the MSDN Documentation. Here is a list of the common exit codes. For example, 2 means The system cannot find the file specified..
Errors are probably output on CMDReply.StandardError, not CMDReply.StandardOutput; try reading it, too. (And set CMDServer.RedirectStandardError to True as well.)

Expect script does not work under crontab

I have an expect script which I need to run every 3 mins on my management node to collect tx/rx values for each port attached to DCX Brocade SAN Switch using the command #portperfshow#
Each time I try to use crontab to execute the script every 3 mins, the script does not work!
My expect script starts with #!/usr/bin/expect -f and I am calling the script using the following syntax under cron:
3 * * * * /usr/bin/expect -f /root/portsperfDCX1/collect-all.exp sanswitchhostname
However, when I execute the script (not under cron) it works as expected:
root# ./collect-all.exp sanswitchhostname
works just fine.
Please Please can someone help! Thanks.
The script collect-all.exp is:
#!/usr/bin/expect -f
#Time and Date
set day [timestamp -format %d%m%y]
set time [timestamp -format %H%M]
#logging
set LogDir1 "/FPerf/PortsLogs"
et timeout 5
set ipaddr [lrange $argv 0 0]
set passw "XXXXXXX"
if { $ipaddr == "" } {
puts "Usage: <script.exp> <ip address>\n"
exit 1
}
spawn ssh admin#$ipaddr
expect -re "password"
send "$passw\r"
expect -re "admin"
log_file "$LogDir1/$day-portsperfshow-$time"
send "portperfshow -tx -rx -t 10\r"
expect timeout "\n"
send \003
log_file
send -- "exit\r"
close
I had the same issue, except that my script was ending with
interact
Finally I got it working by replacing it with these two lines:
expect eof
exit
Changing interact to expect eof worked for me!
Needed to remove the exit part, because I had more statements in the bash script after the expect line (calling expect inside a bash script).
There are two key differences between a program that is run normally from a shell and a program that is run from cron:
Cron does not populate (many) environment variables. Notably absent are TERM, SHELL and HOME, but that's just a small proportion of the long list that will be not defined.
Cron does not set up a current terminal, so /dev/tty doesn't resolve to anything. (Note, programs spawned by Expect will have a current terminal.)
With high probability, any difficulties will come from these, especially the first. To fix, you need to save all your environment variables in an interactive session and use these in your expect script to repopulate the environment. The easiest way is to use this little expect script:
unset -nocomplain ::env(SSH_AUTH_SOCK) ;# This one is session-bound anyway
puts [list array set ::env [array get ::env]]
That will write out a single very long line which you want to put near the top of your script (or at least before the first spawn). Then see if that works.
Jobs run by cron are not considered login shells, and thus don't source your .bashrc, .bash_profile, etc.
If you want that behavior, you need to add it explicitly to the crontab entry like so:
$ crontab -l
0 13 * * * bash -c '. .bash_profile; etc ...'
$