rubyruby-2.2popen3

Open3.popen3 returns wrong error Errno::ENOENT on Windows


I have the following code in test.rb:

require 'open3'
cmd = 'C:\Program Files\foo\bar.exe'
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
  puts "stdout: #{stdout.read}"
  puts "\n\n"
  puts "stderr: #{stderr.read}"
end

bar.exe is a console application that I created, located in C:\Program Files\foo\. When I run bar.exe:

When I run ruby test.rb I get this error:

C:\RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/open3.rb:193:in 'spawn': No such file or directory - C:\Program Files\foo\bar.exe (Errno::ENOENT)
from C:\RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/open3.rb:193:in 'popen_run'
from C:\RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/open3.rb:193:in 'popen3'
from test.rb:3:in '<main>'

If I change the code to call popen3:

Open3.popen3(cmd, '')

I don't get the Errno::ENOENT error, instead I get the help message, but I want the "Hello World" output.

I searched for a solution but nothing is working, including the answer to "Why does Open3.popen3 return wrong error when executable is missing?".

Why am I getting this error and how do I solve it?


Solution

  • You are having trouble because "Program Files" is a folder with a space in it. Whenever that happens, you need to double quote it, just as you would on a cmd.exe prompt. And when you're double-quoting, you must remember that your backslash character "\" is an escape character, so you have to double-backslash to get the proper folder separators for Windows. I'm going to use code which actually returns something in my environment; adjust it to your taste. So your code should look like:

    require 'open3'
    cmd = "\"C:\\Program Files\\Git\\bin\\git.exe\""
    Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
      puts "stdout: #{stdout.read}"
      puts "\n\n"
      puts "stderr: #{stderr.read}"
    end
    

    If you have command line parameters to pass to git, you'd do it like this:

    require 'open3'
    cmd = "\"C:\\Program Files\\Git\\bin\\git.exe\" --version"
    Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
      puts "stdout: #{stdout.read}"
      puts "\n\n"
      puts "stderr: #{stderr.read}"
    end