Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0006978OCamlplatform support (windows, cross-compilation, etc)public2015-09-02 08:332017-02-20 14:25
Reportermodlfo 
Assigned To 
PrioritynormalSeverityminorReproducibilityalways
StatusresolvedResolutionno change required 
PlatformOSOS Version
Product Version4.02.3 
Target VersionundecidedFixed in Version 
Summary0006978: Unix.create_process fails to call .bat scripts with spaces in path given arguments with spaces
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 ReproduceSee the example in the description
Additional InformationI 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 [^]
TagsNo tags attached.
Attached Files

- Relationships

-  Notes
(0014433)
dim (developer)
2015-09-09 16:15

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"
(0014437)
modlfo (reporter)
2015-09-09 17:27

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.
(0014688)
xleroy (administrator)
2015-11-15 18:04

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?
(0017381)
xleroy (administrator)
2017-02-20 14:25

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".

- Issue History
Date Modified Username Field Change
2015-09-02 08:33 modlfo New Issue
2015-09-09 16:15 dim Note Added: 0014433
2015-09-09 17:27 modlfo Note Added: 0014437
2015-11-15 18:04 xleroy Note Added: 0014688
2015-11-15 18:04 xleroy Status new => acknowledged
2015-11-15 18:04 xleroy Target Version => 4.03.0+dev / +beta1
2016-04-15 15:42 doligez Target Version 4.03.0+dev / +beta1 => 4.03.1+dev
2017-02-16 14:01 doligez Target Version 4.03.1+dev => undecided
2017-02-20 14:25 xleroy Note Added: 0017381
2017-02-20 14:25 xleroy Status acknowledged => resolved
2017-02-20 14:25 xleroy Resolution open => no change required
2017-02-20 14:25 xleroy Summary Unix.create_process fails to call programs with spaces in path given arguments with spaces => Unix.create_process fails to call .bat scripts with spaces in path given arguments with spaces
2017-02-20 14:25 xleroy Description Updated View Revisions
2017-02-23 16:46 doligez Category OCaml windows => platform support (windows, etc)
2017-02-23 17:16 doligez Category platform support (windows, etc) => platform support (windows, cross-compilation, etc)


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker