Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unix.create_process fails to call .bat scripts with spaces in path given arguments with spaces #6978

Closed
vicuna opened this issue Sep 2, 2015 · 4 comments

Comments

@vicuna
Copy link

vicuna commented Sep 2, 2015

Original bug ID: 6978
Reporter: modlfo
Status: resolved (set by @xavierleroy on 2017-02-20T13:25:56Z)
Resolution: not a bug
Priority: normal
Severity: minor
Version: 4.02.3
Target version: undecided
Category: platform support (windows, cross-compilation, etc)
Monitored by: @gasche @diml @hcarty @alainfrisch

Bug description

[ Original summary was: Unix.create_process fails to call programs with spaces in path given arguments with spaces ]

The problem shows when trying to create a process in which the path of the executable and one of the arguments have spaces, for example:

let cmd = "C:/Program Files/Something/something.exe" ;;
let args = ["arg1"; "arg2"; "C:/Program Files/arg3"] ;;

let pid = Unix.create_process cmd (cmd::args |> Array.of_list) Unix.stdin Unix.stdout Unix.stderr ;;

Unix.waitpid [] pid ;;

As soon as there's an argument with spaces, the process fails to run. I tried many different combinations with quoting, backlashes, forwardslashes, backslashed space, etc, but nothing seemed to work.

Steps to reproduce

See the example in the description

Additional information

I have found a solution for it.

When calling CreateProcess the first argument needs to be NULL

CreateProcess(NULL",""C:/some.exe" arg1 arg2",.........);

Rather than:

CreateProcess("C:/some.exe",""C:/some.exe" arg1 arg2",.........);

Here's the documentation https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx

I saw that Qt qprocess does the same, which makes me think that this change is stable and well tested.

https://github.com/Vitallium/qt5/blob/master/qtbase/src/corelib/io/qprocess_win.cpp

@vicuna
Copy link
Author

vicuna commented Sep 9, 2015

Comment author: @diml

I tried something similar but couldn't reproduce the issue.

Here is what I tried:

$ cat echo_args.ml
let () = Array.iteri (Printf.printf "argv.(%d) = %S\n") Sys.argv
$ cat run_process.ml
let cmd = "C:/Documents and Settings/jdimino/echo args.exe"
let args = [ "arg1"
; "arg2"
; "C:/Documents and Settings/arg3"
]

let pid =
Unix.create_process cmd (Array.of_list (cmd :: args))
Unix.stdin Unix.stdout Unix.stderr

let _ = Unix.waitpid [] pid
$ ocamlopt -o "echo args.exe" echo_args.ml
$ ocamlopt -o run_process.exe unix.cmxa run_process.ml
$ cp "echo args.exe" "C:/Documents and Settings/jdimino/"
$ ./run_process.exe
argv.(0) = "C:/Documents and Settings/jdimino/echo args.exe"
argv.(1) = "arg1"
argv.(2) = "arg2"
argv.(3) = "C:/Documents and Settings/arg3"

@vicuna
Copy link
Author

vicuna commented Sep 9, 2015

Comment author: modlfo

Hi, here are more detailed steps of what I'm doing to reporduce the problem.

1.- Create a dir "C:\Path With Spaces"
2.- Create the following files:

Name: echoargs.bat

echo %1
echo %2
echo %3

Name: test.ml

let cmd = "C:/Path With Spaces/echoargs.bat"
let args = [ "arg1"
; "arg2"
; "C:/Documents and Settings/arg3"
]

let pid =
Unix.create_process cmd (Array.of_list (cmd :: args))
Unix.stdin Unix.stdout Unix.stderr

let _ = Unix.waitpid [] pid

3.- Compile test.native with:

$ ocamlbuild -use-ocamlfind -pkg unix test.native

4.- Execute ./test.native

The error I get is:

'C:/Path' is not recognized as an internal or external command,
operable program or batch file.

If I make the proposed change, works correctly. Note: in this case I'm calling a .bat file but I have the same result calling a regular exe file.

I'm using the MSVC 64 bits compiled with VS2013 running on Windows 10.

@vicuna
Copy link
Author

vicuna commented Nov 15, 2015

Comment author: @xavierleroy

This one is mysterious. The MSDN page says that the first parameter lpApplicationName can be NULL, in which case the beginning of the command-line determines the application name. But nowhere it says that a non-NULL lpApplicationName can cause problems with spaces in file names... Indeed, the "Security Remarks" section of the MSDN page cautions against passing NULL as lpApplicationName.

Any Windows expert here to help us understand?

@vicuna
Copy link
Author

vicuna commented Feb 20, 2017

Comment author: @xavierleroy

I can reproduce the problem when the executable is a .bat batch file, but not when it is a proper .exe executable.

I'm not even sure that the Win32 CreateProcess() system call is supposed to handle .bat files as executables. The examples I found on the Web involve calling cmd.exe as executable and "/c" "foo.bat" as arguments.

Resolving this PR as "not an OCaml issue".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant