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
Related
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
I have this kind of batch file
start /b ruby script.rb && echo done
...
However, it write 'done' immediately after i run the batch file, which is incorrect, as the script took about 5 mins.
So, how to echo done only after the bg task succesfully end?
thank you!
note: I think that && operator work this way if it is not used in batch file nor in usage to run bg task.
start "" /b cmd /c "ruby script.rb && echo done"
Without the quotes the conditional execution command is seen as the continuation of the start command instead of continuation of the ruby command.
As the && is an operator handled by cmd we need to start a new instance.
The "" at the start are needed as the first quoted argument to start is handled as a window title.
note: && is an conditional execution operator. If the previous command does not generate an error then the following command is executed. In this case with the process running in background, probably, &, the command concatenation operator, should be used to know that the script ended.
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.
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.
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"