I want to use a batch file as a rule command in ninja like this
rule test
command = some-batch-file
but it results in
CreateProcess failed: The system cannot find the file specified.
It works when I prefix the command with cmd /c, but then I face the problem of the command-line length cap at 8191 or so characters. I found it hard finding information on why this doesn't work. My guess is that windows can really only execute .exe files with CreateProcess().
Can I make it work when it is passed directly to CreateProcess() or do I have to use cmd /c?
Related
I am trying to start a .bat file from gow bash. I can sucessfully start a batch and return to bash with the following (I am in C:\tmp\a\ directory), the content of the file a.bat file consists a single command cd (to print the current working directory):
$ cat a.bat
cd
$ cmd "/C a.bat"
c:\tmp\a>cd
c:\tmp\a
$
Now if I try to start the program from c:\tmp (one level higher in the hierarchy of directory structure), I get an error:
$ cmd "/C a\\a.bat"
'a' is not recognized as an internal or external command,
operable program or batch file.
$ cmd '/C a\a.bat'
'a' is not recognized as an internal or external command,
operable program or batch file.
$ cmd '/C a/a.bat'
'a' is not recognized as an internal or external command,
operable program or batch file.
How can I start a batch script given a path to it, and return to bash?
I guess I found a very simple solution:
Add a dot before /C
cmd ". /C a\a.cmd"
After that gow (and cygwin and alikes) stop treating the argument as containing paths and converting it to POSIX paths.
And cmd ignores everything up to /C (well, almost everything, I think).
a.cmd:
#echo off
echo it's working
output:
bash-3.1$ cmd ". /C a\a.cmd"
it's working
bash-3.1$
[Update]
After some research I found that POSIX path conversion has a very clean description of conversion rules.
In your case the rule An argument with a leading / is converted up to the first /.. seems to be applied.
Conversion results in changing '\' to '/'. So, you get a/a.cmd, that is a with a switch /a.cmd. And this results in the observed error, of course.
The link above addresses MSYS and seems to be a bit outdated, but I've checked some of the rules in bash from my fresh Git for Windows installation (based on MSYS2), and they look working as described.
After a bit of research and posting questions to other forums I found the following additional info to run the job "correctly":
cmd //D . //C "a\a.cmd"
References:
Github issue #244, Unix to Windows path translation may corrupt command switches/arguments
Github issue #243, when bash starts a cmd, it adds a buggy double quote symbol at the end of the line
I have a problem whenever I try to run some paths,
for example :
C:\Users\Dell\Desktop\Menu\program.lnk
I had this error:
not recognized as an internal or external command operable program or batch file.
As you can see this not a problem of space in the path, how can I solve this?
Having Tested This in the command prompt myself I found that on my windows 7 machine the command prompt doesn't like me appending the '.lnk' file extension on the end yet it seems to work to when I remove it. Other than I am not too sure. Could be a problem with the shortcut or the executable but I doubt it.
i just had to add cmd /C as prefix of the command
I have a ./configure file that I'm supposed to run by putting it in the command prompt. It works when I run it in the git prompt but when I run it in the Windows command prompt it gives me:
C:\cygwin\home\doxygen\configure> configure
'configure' is not recognized as an internal or external command,
operable program or batch file.
Even though I'm in the correct directory (and running dir shows me that the file is there) it still stays that it cannot find the file. This is the same for all files that don't have an extension on them. Why does this happen and how can I get this to work?
./configure is not a program. It's more of a shell script usually. My analogy may not be good but consider it to be the equivalent of windows batch files (in this case you can say it's a .sh without the extension).
It will only run from a cygwin/unix shell.
I run a batch file as an external tool (by adding it in Tools->External tools) in VS2010 (I've checked the "Use Output Window" option). This batch file performs compilation as in VS command prompt. The project that I'm working on has makefiles for various folders, so I use the mk command to build.
In the batch file, I set up the VS environment and then run the following commands:
cd $directoryWhichContainsFileToBuild
mk
cd main //This directory contains the executable that is to be built
mk
I see the output of the first mk in the Output window but after that it just hangs. I also tried to use an echo after the first mk but even that doesn't get printed in the output window (the ones before it can be seen).
Somewhere I read that there is an issue with VS 2010 output window where it hangs after showing some output, although I couldn't really be sure that that is what's the issue here.
Do I need to enable some other VS setting? Has anybody else encountered this issue?
Thanks.
Update: I unchecked the "Use Output Window" and "Close on exit" option, and I see an extra statement: "Press any key to continue". On doing that however, their is no further processing of the batch file.
Update2: Got it to work by prefixing mk with "call".
Thanks all who tried.
It is always good in batch files to specify executables with full path and file extension instead of just the file name. This avoids often lots of problems.
Here was just mk used instead of mk.bat. Therefore on every compile the command line processor cmd.exe searches for mk.* and then checks if any of the found files have an extension listed in environment variable PATHEXT. The order of file extensions separated by a semicolon in PATHEXT defines the order of execution in case of a directory contains multiple mk.* files.
If a command being specified in a batch file not being an internal command of cmd.exe without path, command line processor searches first for a file with given name in current working directory. This is often one more cause of error. What is the current working directory on execution of the batch file?
Next if no file to execute can be found in current working directory, the command line processor searches in all folders being listed in environment variable PATH separated by semicolons.
So specifying in batch files edited only rarely an external application or another batch file with full path, file name and file extension, in double quotes if necessary because of 1 or more spaces in path or file name, helps command line processor to more quickly execute that application or batch file and avoids problems because of executable not found (unknown command).
Sure, when typing commands in a command prompt window, nobody wants to enter the executables with full path, name and extension. But for batch files it is always good to be not lazy and type files to be executed with full path and extension.
TripeHound has given already the explanation why the observed behavior occurred here.
If a batch file is executed from another batch file without using command call, the command line processor continues batch execution in the other batch file and does never come back. In a C/C++ program this is like using goto with the difference that parameters can be passed to the batch file containing the further commands to be executed next.
But running from within a batch file another batch file with call results in continuation of execution below the line calling the other batch file once the other batch file reaches end, except command exit is used in the called batch file without parameter /B.
So the solution here is using:
cd /D "Directory\Which\Contains\File\To\Build"
call "Path\Containing\Batch\File\To\Build\mk.bat"
rem With mk.bat not changing current working directory change working
rem directory to the directory containing the executable to be built.
cd main
call "Path\Containing\Batch\File\To\Build\mk.bat"
BTW: exit exits command processor, exit /B exits just current batch file. I'll give you three guesses why the parameter is B and not a different letter. Yes, B is the first letter of batch.
Writing as a separate answer instead of an update in the question itself as many readers see the header and skim to the answer: got it to work by prefixing mk with "call". (#TripleHound has also posted the conceptual reason for it in the comment above.)
I'm using Ruby (2.0) %x{dir} under Windows 7 to run a DOS dir command. The dir being executed is different depending on whether or not dir is quoted.
When the command is bare I get the full output of a DOS dir command:
# sends output of cmd back to program
puts 'run %x{dir}'
puts "dir= " + %x{dir}
What I see on the command line:
run %x{dir}
dir= Volume in drive C is System
Volume Serial Number is FFFF-FFFF
Directory of C:\Users\ ...etc...
08/26/2013 09:16 AM <DIR> .
08/26/2013 09:16 AM <DIR> ..
01/28/2013 02:28 AM 10,958 AJAX RUG Test.tsc
...etc...
When I quote the dir command with either single or double quotes, I get back the output of GnuWin32 dir.exe command which is in the PATH. It took me a while to figure out that the GNU dir was being run. What is causing Ruby to use the dir built into CMD.EXE vs. c:\PROGRA~2\GnuWin32\bin\dir.EXE ???
Also, I've just noticed that my "Pickaxe" and "Ruby Cookbook" use the "%x{}" syntax (BRACES), where the online docs use "%x()" (PARENS) ... is this just a case of general delimiter matching by Ruby?
This is a peculiarity of Windows, not Ruby. What's going on is this:
Dir is not an executable but a native function of Windows/cmd.exe. (It's part of cmd.exe - so cmd.exe "traps" when you type dir and runs an internal function rather than looking for "dir.exe" or something out on your file path).
When you put something in quotes in cmd, it forces cmd.exe to look for that command on the path, not via it's internal functions.
You can test this by opening a command prompt in Windows and typing a built-in command (that doesn't exist in gnuwin32) such as copy:
>copy
The syntax of the command is incorrect.
>"copy"
'"copy"' is not recognized as an internal or external command,
operable program or batch file.
If you then create "copy.cmd" file with contents:
echo copy.cmd executed
when you run, you'll see:
>"copy"
copy.cmd executed
Make sense? Basically quoting the command you send to the shell (cmd.exe) from Ruby will cause a different interpretation by cmd.exe - it will prevent internal/built-in cmd.exe commands (such as dir and copy) from working, whereas external utils such as xcopy will work fine.