redirecting output from cmd /c - windows

I have the following command (which I'm running from CScript but testing on the command line).
This command will consciously fail, but I want the output to go to the temp file radA9D4F.tmp
cmd /c java -jar "saxon9he.jar" -o:"radF45AB.tmp" -s:"WOnReportTemp_3816933937777_1.xml" -xsl:"filename.xsl1" > radA9D4F.tmp
but it simply print the error to the console (correct error but I want it to be redirected)
filename.xsl1 does not exist
and there is no redirected output in radA9D4F.tmp.
looking at https://ss64.com/nt/cmd.html it has a similar example
Spaces in Program Path + parameters with spaces:
CMD /k ""c:\batch files\demo.cmd" "Parameter 1 with space" "Parameter2 with space""
So I THINK I need to enclose the whole java piece in double quotes somehow like
cmd /c ""java -jar "saxon9he.jar" -o:"radF45AB.tmp" -s:"WOnReportTemp_3816933937777_1.xml" -xsl:"filename.xsl1""" > radA9D4F.tmp
but this just outputs
The system cannot find the path specified.
in fact even this
cmd /c ""java -jar "saxon9he.jar" ""
outputs
The system cannot find the path specified.
So I think the basic issue is how to run a command using cmd /c where potentially all paths may contain spaces

Related

cmd.exe opens the file path with notepad.exe instead of interpreting it as an argument

Given cmd.exe, I observed a special case which I do not understand, and which does not seemed to be explained by https://stackoverflow.com/a/4095133/16545605:
This simple command is executed as one would expect:
> type ..\..\..\..\..\..\windows\win.ini
; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1
But what happens when done this way? Well, it opens Notepad with the given file and the shell is blocked until Notepad is closed again:
> cmd.exe /c "type ..\..\..\..\..\..\windows\win.ini"
On the other hand, those three variants behave as someone would expect (as the first example):
> cmd.exe /c type ..\..\..\..\..\..\windows\win.ini
...
> cmd.exe /c "type" "..\..\..\..\..\..\windows\win.ini"
...
> cmd.exe /c "type C:\windows\win.ini"
...
To open Notepad, it is also possible to just give the file name. It seems cmd.exe opens the file with the default program if only the path is given:
> ..\..\..\..\..\..\windows\win.ini
> C:\windows\win.ini
So, it seems that cmd.exe is interpreting the given command as two commands, and only "executes" the second one (opening the file, everything before is ignored). Furthermore, it seems the path has to be relative. My question now is, why, and under which circumstances this behavior happens. Please note, that type is just an example. It also works with echo, ping, ipconfig,...
If you already liked this behavior, lets add another one:
> cmd.exe /c "echo a > output.txt ..\..\..\..\..\..\windows\win.ini"
> type output.txt
a ..\..\..\..\..\..\windows\win.ini
If you do this without cmd.exe \c, additionally a newline is introduced:
> echo a > output2.txt ..\..\..\..\..\..\windows\win.ini
> type output2.txt
a
..\..\..\..\..\..\windows\win.ini
As Linux user, I'm just baffled how unintuitive a shell can be. Is there some documentation why it is as it is, and how to prevent this behavior (without removing the cmd.exe /c part)?
I stumbled over a blog-post analyzing the behavior in the first part of my question in detail: https://hackingiscool.pl/cmdhijack-command-argument-confusion-with-path-traversal-in-cmd-exe/
Basically, given the following command:
> cmd.exe /c "type ..\..\..\..\..\Windows\System32\ipconfig.exe"
Windows interprets type .. as "directory" and then enters the parent directories multiple times as ..\ does until the drive root is reached. Using this exact location we can point to arbitrary known files or executables. Given an path, cmd.exe detects that there is a file at this location and thus executes the found executable instead of interpreting the command as originally intended.

use root cmd window to execute commands in new cmd window

i'm trying to make a batch script for running my Java files. I've found out that there is no way to prevent auto-closure of a batch script(except using pause keyword, tho it just waits for key press). I've also discovered that starting a new window will cause only main windows to close, not the new one too so i want a way that the command SET /P file=Java file: is executed in the new window(I got the new window by using the start keyword. Is there any way to accomplish this without downloading other softwares? this is the code i came up with yet:
cd "C:\Users\DEVDHRITI\Desktop\Files&Folders\HMMMMM\programs\java programmes"
set /P file=Java file to execute:
java %file%^.jar
start
I guess you're looking for that :
cd "C:\Users\DEVDHRITI\Desktop\Files&Folders\HMMMMM\programs\java programmes"
start cmd /V:ON /K "#set /P "file=Java file to execute: " && java -jar !file!^.jar"
EDIT: Using expansion with /V and use of /K instead of /C to keep the cmd windows open.
Explanations : To launch a console process in another windows and keep it open after the end of this process console we launch another cmd process with the start command. We use /V:ON to use delayed expansion by default, meaning modified variables (like the one we prompt, %file%) will be expanded on the fly with ! (so !file! instead of %file%). We use /K to tell to this cmd process to not close when provided commands end. To this cmd process, we provide the following commands :
#set /P "file=Java file to execute: "
This one will ask for the jar filename (without extension) to launch.
The # means "do not echo the command itself on the console stdout" for a nice display.
java -jar %file%^.jar
This one launch the java interpreter (JVM) with the filename of a jar file to execute through the -jar parameter, filename build from the previous prompt and the .jar extension. The ^ here escapes the ., it seems not useful here but maybe your script/env requires it.
We link the both commands with && which means : _if left command from && is successful (it exits with ERRORLEVEL 0) then execute the right command from &&.

Making a batch file for multiple CMDs

Lets say I have 2 services I want to start and a property file.
-svc1.cmd
-svc2.bat
-svc2prop.properties
Lets have directories as C:\program1\bin\ and C:\program2\bin\ + C:\program2\config\
then I tried to do it like this:
start cmd /k call C:\program1\bin\svc1.cmd
start cmd /k cd C:\program2\ .\bin\svc2.bat .\config\svc2prop.properties
I can start them both separately by opening a local CMD. The thing is, if I am in the directory C:\program2\ I can open up a local CMD and run this statement without problems " .\bin\svc2.bat .\config\svc2prop.properties"
But I want to create a batch file that: first, opens a new cmd and starts the svc1.cmd, then opens another cmd in which it goes to C:\program2\ and runs the "" .\bin\svc2.bat .\config\svc2prop.properties" " statement ... but for some reason it doesnt work.
Any possible solution ?
the second line should use /D option to start the process in the required directory:
start /D C:\program2 cmd /k .\bin\svc2.bat .\config\svc2prop.properties
(in your example, you were just passing a lot of arguments to an useless cd command)
If you have some current directory problems with the first line, just do the same:
start /D C:\program1\bin cmd /k call svc1.cmd

Running File from Notepad Plus Plus and Current Directory

There are a number of examples on the web of how to run a file from the Notepad Plus Plus (NPP). But they all fail to account for the fact that the current working directory is the location of the NPP's executable, and not the location of the file.
Usually they go something like this:
cmd /K "$(FULL_CURRENT_PATH)"
Consider the following Python script:
with open('somefile.txt', 'a') as file:
file.write('Hello there.\n')
This file will be created in the NPP folder, which is not at all what most people would expect. Most people would want it in the same location as the Python file.
You could also do something like this, and it works as expected, but this limits you to Python files only:
<Command name="Run This Python File" Ctrl="no" Alt="no" Shift="yes" Key="116">cmd /K python "$(FULL_CURRENT_PATH)"</Command>
I would not want to add extra code to the Python script to change the current working directory, as normally this would not be needed.
I have been trying to solve this and came up with the following. This line goes in "shortcuts.xml" in the NPP folder.
<Command name="Run This File" Ctrl="yes" Alt="no" Shift="no" Key="116">cmd /K "cd "$(CURRENT_DIRECTORY)" && "$(FULL_CURRENT_PATH)""</Command>
So you shut down the NPP, edit the "shortcuts.xml" by adding this line, using another editor, then launch the NPP.
To run the file, use Ctrl+F5 key combination.
This works in Windows 10, but fails in Windows XP.
How can I tweak it to work in Windows XP?
Try this:
cmd /k cd /d $(CURRENT_DIRECTORY) && python $(FULL_CURRENT_PATH)
My guess would be that the problem is the improperly nested quotes in the command; I'm not sure exactly why it would work on later Windows' while failing on XP.
The command
cmd /K "cd "$(CURRENT_DIRECTORY)" && "$(FULL_CURRENT_PATH)""
represents
cmd /K "cd "$(CURRENT_DIRECTORY)" && "$(FULL_CURRENT_PATH)""
Even from the syntax highlighting you can see that the quotes are not quoting what you expect.
To get the desired effect, you can use this command:
cmd /K cd "$(CURRENT_DIRECTORY)" ^&^& "$(FULL_CURRENT_PATH)"
:: XML-ified:
cmd /K cd "$(CURRENT_DIRECTORY)" ^&^& "$(FULL_CURRENT_PATH)"
I run several Windows .bat files from Notepad++. To achieve this one of the entries in the <UserDefinedCommands> section of the file C:\Users\AdrianHHH\AppData\Roaming\Notepad++\shortcuts.xml is:
<Command name="CD and run file" Ctrl="no" Alt="no" Shift="no" Key="0">cmd /C "cd /d $(CURRENT_DIRECTORY) && $(FULL_CURRENT_PATH)"</Command>
With the .bat as the current file I then use menu => Run => CD and run file.
The command line shown in the question appears to have too many " symbols. The current directory includes the drive specifier and so the CD needs the \D option.
The command I use starts cmd \C ... (rather than the \K in the question) so the command window closes automatically. My .bat files normally finish with choice /t 60 /C Y /d Y /n so I can see the command's output.
Notepad++ > F5 (Run) > then type following command
cmd /K cd "$(CURRENT_DIRECTORY)" && python "$(FULL_CURRENT_PATH)"
assuming you have setup the path, or you may use C:\Python27\python.exe or the path of your python binary, and you will run the python at the folder where the python resides in. You can also save this command to shortcut by clicking button Save....
Afterwards, you also can modify the command in toolbar > Run > Modify shortcut/delete command.

Windows command line using directory and EXE file parameters

I have been trying to run an application I built and output it to a file. However, I am running into problems with the command line arguments required to do this.
This is an example of my problem using ipconfig.
The following command works:
ipconfig > output.txt
Whereas this will create the file, but not populate it with the ipconfig output:
start /D "C:\>WINDOWS\system32" ipconfig.exe > output.txt
I think it is the use of start that is causing this issue, but I'm not sure.
SOLUTION
This is the code which managed to solve the problem for me:
char path[500]; // Create character array
strcpy (path, "cd "); // Copy 'cd' into the array
strcat (path, toolLocation); // Copy the path of the tool into the array
strcat (path, " & ip.exe > output.txt"); // Append on the name of the exe and output to a file
system (path); // Run the built array
I am creating a character array and then appending to it. The vital bit here was the & being used in the system call. This is working as an and and first cd'ing to the directory before executing the .exe file.
In your command, the > is redirecting the output of start rather than the output of ipconfig. That explains why you are seeing nothing – start is simply not outputting anything.
Based on the comments to the question, you can achieve your goals with ShellExecute like this:
ShellExecute(
0,
"open",
"cmd.exe",
"/C ipconfig > output.txt",
NULL,
SW_HIDE
);
Rather than using start I think you might want to use cd to change the directory.
Try this batch file:
cd "C:\Program Files\Tools\2012"
ip.exe >output.txt
Or for use without a batch and just command line:
"C:\Program Files\Tools\2012" ip.exe >output.txt"
Although system32 is in PATH so I'm not sure why you are accessing the ipconfig exe by it's full path, but this should work.
The error is this:
start /D "C:\>WINDOWS\system32" ipconfig.exe > output.txt
should be
start /D "C:\WINDOWS\system32" ipconfig.exe > output.txt
without > in the path. Although C:\> is shown at the prompt with cmd.exe it is not part of the path name and > is actually invalid for the purpose, to my knowledge.
Additionally I would strongly suggest you use:
start /D "%SystemRoot%\system32" ipconfig.exe > output.txt
Furthermore because start creates a new console (and new stderr and stdout) you are catching the output of start not of ipconfig. So you may wanna use:
pushd "%SystemRoot%\system32" & ipconfig.exe > output.txt & popd
but that will attempt to write output.txt into %SystemRoot%\system32 and will fail on most systems unless you are admin. So give an absolute path or simply leave out the crud:
ipconfig.exe > output.txt
ipconfig.exe is always in the default system PATH variable, so it will work unless the admin has "fixed" the system in which case you can still do:
%SystemRoot%\system32\ipconfig.exe > output.txt

Resources