I've seen two different ways of calling icacls from VBScript:
oShell.Exec("icacls ...
or
oShell.Exec("%COMSPEC% /c Echo Y| icacls ...
What's the difference?
Usually you don't need to run it in a Command Prompt if it's an external command (executable, script, etc.). So if you can go to Start → Run… and run it from there, then you can run your application directly with all arguments, etc.
However, if you're using CMD builtin features, like internal commands (dir, echo, mklink, …), the pipe (|), or I/O redirection (>, >>, <), you must run the commandline in CMD, because otherwise these features wouldn't be available. The parameter /c is just to tell CMD to terminate after the command completes. It's not required, but it's good practice to put it there, so you can easily replace it with /k (keep CMD open after the command completes) for debugging purposes.
Have a look at the documentation for the /C switch using CMD /?.
The /C switch tells the cmd.exe program to return after it runs the specified command line. If it does not return, you will be left in a cmd shell. I do not know what this would look like from VBS.
My guess would be that, yes, you need /C.
Related
Note: A solution is posted below.
Problem:
When required to start a batch file (cmd script) (i.e. CALLEE.CMD) in a new console window, from within another batch file (i.e. CALLER.CMD) , the obvious choice would be to use the internal START command: START "" "%~DP0CALLEE.CMD".
However, if we need to pass quoted parameters to CALLEE.CMD, such as START "" "%~DP0CALLEE.CMD" "ARGUMENT_1", you get an error such as 'CALLEE.CMD" "ARGUMENT_1' is not recognized as an internal or external command,
operable program or batch file.
At first glance, it's not obvious why this command should fail, as the requirements for calling the START command seem to be met. This question is posted because the reason for failure is not immediately apparent, and others may find the reference useful.
So, why is this command failing, and how to resolve the issue?
What is happening here, is that when the START command detects the command to be invoked is either an internal command (internal to cmd.exe) or a batch file, it will invoke cmd.exe to handle the command (cmd.exe /K ... will be used). The additional arguments passed to START will be translated and passed to cmd.exe. When this happens, the rules change: cmd.exe expects the command and arguments to be quoted differently from START, so this has to be taken into account when writing the original command.
The quoting for cmd.exe is documented elsewhere, such as:
correct quoting for cmd.exe for multiple arguments
http://ss64.com/nt/cmd.html.
So, to start a batch file, with quoted arguments in a new console window, we could do as follows:
START cmd.exe /K ""%~DP0CALLEE.CMD" "ARGUMENT_1" "ARGUMENT_2""
Of course, this problem only occurs if you need to quote the arguments, either because a called program expects it or if there are spaces in the argument.
Also, as a plus, if you don't require the new console window to remain open after finishing the batch file, you can substitute the switch /K with /C.
The requirement for always needing to provide a window title when calling a quoted command is avoided here, but if you do require to prefix the title of the new console window, you can do as follows:
START "<Title>" cmd.exe /K ""%~DP0CALLEE.CMD" "ARGUMENT_1" "ARGUMENT_2""
Example code:
CALLEE.CMD
#ECHO %*
#PAUSE
CALLER.CMD
#START "<Title>" cmd.exe /C ""%~DP0CALLEE.CMD" "ARGUMENT_1" ARGUMENT_2 "ARGUMENT_3""
I am trying to write a batch file to run a .exe with a parameter and that gives and output in .csv
I wrote:
start "" "C:\Users\Me\Desktop\AnalysisSoftware\Video.exe" S1.avi>S1.csv
This command is working but the created .csv file is empty. What's wrong?
I also tried with ^ like that:
start "" "C:\Users\Me\Desktop\AnalysisSoftware\Video.exe" S1.avi^>S1.csv
Not working too...
Thank you
Cec
The start command starts the command in another process and so the output is not captured, instead you are capturing the output of the start command, which is nothing.
What you need is
start "" "cmd /c C:\Users\Me\Desktop\AnalysisSoftware\Video.exe S1.avi>S1.csv"
The distinction here is that the redirection operator is within the quotes. In your example above the redirection operator was outside the quotes and so it captured the output of the start command instead of the Video.exe. Note you also need to use cmd /c at the beginning. This is because you need a shell in order to redirect the output of the Video.exe. The /c argument tells cmd to exit as soon as the command finishes executing.
Ok, so I have this batch script and what I want to happen is that when you run the script it does some standard stuff like change the path and access files etc... but after it's done that it goes back to being a normal cmd prompt/terminal where I can type in commands at free will.
Can this be done (in either dos or bash)? Is there like an execute command that I can put in an internal while loop or is there a command where when the scirpt ends it can go back to the normal cmd/terminal?
Do you need a full bash prompt?
Or would something like this be enough?
#!/bin/bash
echo -n "Enter cmd: "
read COMMAND
echo ${COMMAND} | bash
Also, in a script, you can just execute bash and get a full prompt in the current environment.
In Dos / windows command prompt if you run the batch file from command line you will get the prompt back always by default. Just like running any other command in command prompt.
Also in windows when the batch file execution is complete you can just put Cmd.exe when everything has finished running I.e at the end of the batch file.
Hope this helps!
E.g
#echo off
Echo running
.
.
.
Cmd.exe
Or even at the end
Echo %command% | Cmd.exe
Never mind, I got a good solution using this code: (for windows)
set /p command=CMD:
%command%
What is the best WinAPI function to use when you only want to run a simple shell command like hg > test.txt?
To simply run a file, then ShellExecute() and CreateProcess() are the best options.
As you want to redirect output to a file/run a shell command, it complicates things...
Output redirection is a feature of the command prompt, and as such, the command you want to run needs to be passed to cmd.exe (on NT/XP+) passing /c and your command as the parameters (either ShellExecute or CreateProcess will do).
cmd /c "ipconfig >c:\debug\blah.txt"
The best way however is to use CreateProcess() and create your own pipes to talk to the stdin and stdout of the program (This is all cmd does internally)
You could use ShellExecute(), but why not try system() first? I am not so sure that ShellExecute() can actually do piping or redirection. There is also CreateProcess(), but that requires a bit more work. CreateProcess() gives you the best control, though.
There are two ways of issuing commands: the Windows Shell way, and the command line way.
Windows Shell issues commands by executing verbs on files. Verbs are associated with file types in the registry. Examples of common verbs are Open and Print. The WinAPI to use for this is ShellExecute. Windows Shell does not help you pipe the output of a process to a file. You can do it using CreateProcess, but it is a little bit involved.
The command line way is to use the system function.
I have a batch file that I usually invoke like this:
longjob.cmd >result.txt 2>&1
This works fine, but the script changes directory during its execution leaving my shell in that directory - which is a nuisance.
Is there a way to run the command within a sub-shell - while still allowing the output to be captured ?
I have tried
cmd longjob.cmd >result.txt 2>&1
which just sits waiting for an exit command.
Also I tried
start longjob.cmd >result.txt 2>&1
which does run the script, but in a new window and all output is sent to that window instead of the file.
Try
CMD /C longjob.cmd >result.txt 2>&1
Not sure how it'll deal with the redirection, but CMD /C lets you tell CMD what to run and that it should exit when done. (CMD /K lets you tell it to run something but stick around when done.) It will re-use the existing console window if run within one.
The call command might be what you want.
i.e.
call longjob.cmd >result.txt 2>&1