sending ctrl+c using sendkeys in ruby - ruby

I need to close the command prompt window using sendkeys function, but when I used the below code it did not work as running of some betch file is in progress so its not taking these below options.
require 'win32ole'
system("start cmd.exe")
sleep(5)
# Create an instance of the Wscript Shell:
wsh = WIN32OLE.new('Wscript.Shell')
# Try to activate the command window:
if wsh.AppActivate('cmd.exe')
sleep(1)
wsh.SendKeys('cd \\')
wsh.SendKeys('{ENTER}')
# change the directory path where mtn folder is residing
wsh.SendKeys('cd ')
wsh.SendKeys "C://mtn-3//mtn-2.2//"
wsh.SendKeys('{ENTER}')
wsh.SendKeys('cd bin')
wsh.SendKeys('{ENTER}')
#run the cad test node file
wsh.SendKeys('CadTestNode.bat')
wsh.SendKeys('{ENTER}')
wsh1.SendKeys('Exit')
wsh1.SendKeys('{ENTER}')
I also tried replacing last two lines with the below to terminate the process.
wsh.SendKeys "^(c)"
wsh.SendKeys('{ENTER}')
but still it's not able to terminate the process running in command prompt.
Is there any other way to terminate the batch process running in command prompt window?

Try this:
wsh.SendKeys("^C")
In the MSDN SendKeys Method specifies the following characters for this keys:
SHIFT: +
CTRL: ^
ALT: %
Examples:
wsh.SendKeys("+{TAB}") # SHIFT+TAB
wsh.SendKeys("^V") # CTRL+V
wsh.SendKeys("%{F4}") # ALT+F4

Key combinations can be sent by putting the keys into an array.
text_field.send_keys [ :shift, 'a']
puts a 'A' into the text_field. In your example,
wsh1.send_keys [ :control, 'c']
should work.

Related

exec cmd commands using tcl without opening terminal window

I am trying to use exec to run a command such as dir with cmd using tcl code, however the terminal window opens up and I am unable to store the result, when the command has run, into a variable ?
This is what I've been trying so far,
set res [exec cmd.exe /c "dir" &];
When I print out the variable using,
puts $res
I get back just three or four digit codes instead of the actual result when the command was run.
Any help is appreciated.
set res [exec cmd.exe /c "dir" &]
The & at the end of the exec indicates that the command will be processed in the background. The result returned is the process id of the command.
To do what you want, use:
set res [exec cmd.exe /c "dir"]
It would be far more efficient and less resource hungry to use the built-in glob command to get a list of files or search for a file.
set res [glob *.txt]
set res [glob -directory {C:/Program Files} *]
References: exec glob

Close CMD within Ruby

I wrote a function in Ruby that hibernates, restarts, or shuts down the system based on the argument. Here's how it looks:
def sysaction(action)
sleep 0.2
if action == "h"
countdown(60)
`shutdown.exe /h`
elsif action == "r"
countdown(60)
`shutdown.exe -r -f t 00`
elsif action == "s"
countdown(60)
`shutdown.exe -s -f t 00`
end
end
I want to add a piece of code that would exit the parent CMD windows instead. I couldn't find any solution without running the ruby script through a batch file. I tried the following commands:
`exit`
exec `exit`
system('exit')
`cmd /C exit`
But neither seems to work. Any way I can close the window from within Ruby?
Maybe you can use the FreeConsole function:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683150(v=vs.85).aspx
http://www.ruby-doc.org/gems/docs/w/win32console-1.3.1/Win32/Console/API.html#method-c-FreeConsole
For example:
require 'win32console'
puts 'Hello, world!
# free console so it can be shut after the program terminates.
Win32::Console::API.FreeConsole
One way is to kill all cmd.exe applications:
taskkill /f /im cmd.exe

How to parse user inputs in ruby script

I am trying to learn ruby scripting. Currently I am creating a script which should accept user input and do some action like below:
Go to server1 and restart mysqld
Below is my Script:
#!/usr/bin/ruby
puts "on which environment you want to run the script?"
srenv = STDIN.gets.chomp()
puts "#{srenv}"
puts "Hi you have chosen to run the script on #{srenv}, now is it Cluster or not?"
srenvdl = STDIN.gets.chomp()
puts "#{srenvdl}"
if srenvdl == "y"
text = String.new
File.open("cluster.txt") { |f| text = f.read }
words = text.split(/[^a-zA-Z1-9]/)
puts "Now enter your services names:"
sernm = STDIN.gets.chomp()
sernmw = sernm.split(/[^a-zA-Z1-9]/)
for x in words
for each in sernmw
puts "Go to #{x} and restart #{each}!!"
end
end
else
puts "Sorry now we are only supporting Clusters."
exit
end
It is an interactive script and it's asking user to enter the service name and reads the cluster server names from the file which I want to skip. Also I am not able to skip the cluster name while reading from the file.
ruby script.rb cluster1:mysqld,nginx cluster2:memcache,sendmail
I have anoter file cluster.txt where I have stored the cluster server names as below:
cluster1:server1,server11,server111
cluster2:server2,server22,server222
Now I want the script should return me the result as like below:
Go to server1 and restart mysqld
Go to server1 and restart nginx
Go to server11 and restart mysqld
Go to server11 and restart nginx
Go to server111 and restart mysqld
Go to server111 and restart nginx
Go to server2 and restart memcache
Go to server2 and restart sendmail
Go to server22 and restart memcache
Go to server22 and restart sendmail
Go to server222 and restart memcache
Go to server222 and restart sendmail
You may encounter a situation in which you need to pass an argument with a space in it to a Ruby program. It seems impossible at first, since the shell separates arguments on spaces. However, there is a provision for this: any arguments in double quotes will not be separated. The double quotes are removed by the shell before passing it to the Ruby program. The following example passes a single argument to the test.rb Ruby script, test1 test2.
$ ./test.rb "test1 test2"
Using Command-line Arguments
In your Ruby programs, you can access any command-line arguments passed by the shell with the ARGV special variable. ARGV is an Array variable which holds, as strings, each argument passed by the shell. The following program iterates over the ARGV array and prints out its contents.
#!/usr/bin/env ruby
ARGV.each do|a|
puts "Argument: #{a}"
end
The following is an excerpt of a bash session launching this script (saved as the file test.rb) with a variety of arguments.
$ ./test.rb test1 test2 "three four"
Argument: test1
Argument: test2
Argument: three four

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.

How to wait for system command to end

I'm converting an XLS 2 CSV file with a system command in Ruby.
After the conversion I'm processing the CSV files, but the conversion is still running when the program wants to process the files, so at that time they are non-existent.
Can someone tell me if it's possible to let Ruby wait the right amount of time for the system command to finish?
Right now I'm using:
sleep 20
but if it will take longer once, it isn't right of course.
What I do specifically is this:
#Call on the program to convert xls
command = "C:/Development/Tools/xls2csv/xls2csv.exe C:/TDLINK/file1.xls"
system(command)
do_stuff
def do_stuff
#This is where i use file1.csv, however, it isn't here yet
end
Ruby's system("...") method is synchronous; i.e. it waits for the command it calls to return an exit code and system returns true if the command exited with a 0 status and false if it exited with a non-0 status. Ruby's backticks return the output of the commmand:
a = `ls`
will set a to a string with a listing of the current working directory.
So it appears that xls2csv.exe is returning an exit code before it finishes what it's supposed to do. Maybe this is a Windows issue. So it looks like you're going to have to loop until the file exists:
until File.exist?("file1.csv")
sleep 1
end
Try to use threads:
command = Thread.new do
system('ruby programm.rb') # long-long programm
end
command.join # main programm waiting for thread
puts "command complete"

Resources