exec problem is JDK 1.7.0_21

R

Roedy Green

This code no longer works in JDK 1.7.0_21

Process p = exec( "F:\\Program Files (x86)\\netload\\netload.exe",
true/* wait */ );

I thought perhaps it wanted some embedded quotes, but that does not
work either.

Will experiment further.

Command works fine at the prompt.
 
L

Lew

Roedy said:
This code no longer works in JDK 1.7.0_21

Process p = exec( "F:\\Program Files (x86)\\netload\\netload.exe",
true/* wait */ );

I thought perhaps it wanted some embedded quotes, but that does not
work either.

What about

Process p = exec( "F:\\Program\\ Files\\ \\(x86\\)\\netload\\netload.exe", true);
?

Process p = exec( "F:/Program\\ Files\\ \\(x86\\)/netload/netload.exe", true);
?

Process p = exec( "F:/Progra~1/netload/netload.exe", true);
?
 
S

Sven Köhler

Am 17.04.2013 01:48, schrieb Roedy Green:
This code no longer works in JDK 1.7.0_21

Process p = exec( "F:\\Program Files (x86)\\netload\\netload.exe",
true/* wait */ );

Which kind of exec method is that? The standard ones don't take a
boolean paramater.


Regards,
Sven
 
J

Joerg Meier

This code no longer works in JDK 1.7.0_21
Process p = exec( "F:\\Program Files (x86)\\netload\\netload.exe",
true/* wait */ );
I thought perhaps it wanted some embedded quotes, but that does not
work either.
Will experiment further.

No need: just read the change notes for the update:

http://www.oracle.com/technetwork/java/javase/7u21-relnotes-1932873.html#jruntime

---------8<---------

Changes to Runtime.exec

On Windows platform, the decoding of command strings specified to
Runtime.exec(String), Runtime.exec(String,String[]) and
Runtime.exec(String,String[],File) methods, has been improved to follow the
specification more closely. This may cause problems for applications that
are using one or more of these methods with commands that contain spaces in
the program name, or are invoking these methods with commands that are not
quoted correctly.

For example, Runtime.getRuntime().exec("C:\\My Programs\\foo.exe bar") is
an attempt to launch the program "C:\\My" with the arguments
"Programs\\foo.exe" and "bar". This command is likely to fail with an
exception to indicate "C:\My" cannot be found.

The example Runtime.getRuntime().exec("\"C:\\My Programs\\foo.exe\" bar")
is an attempt to launch the program "\"C:\\My". This command will fail with
an exception to indicate the program has an embedded quote.

Applications that need to launch programs with spaces in the program name
should consider using the variants of Runtime.exec that allow the command
and arguments to be specified in an array.

Alternatively, the preferred way to create operating systems processes
since JDK 5.0 is using java.lang.ProcessBuilder. The ProcessBuilder class
has a much more complete API for setting the environment, working directory
and redirecting streams for the process.

---------8<---------

Specifically, you use a path with a space in it. Frankly, I'm surprised
that ever worked. That being said, this seems to be a step back, not
forward.

Liebe Gruesse,
Joerg
 
S

Stanimir Stamenkov

Tue, 16 Apr 2013 15:48:10 -0700, /Roedy Green/:
This code no longer works in JDK 1.7.0_21

Process p = exec( "F:\\Program Files (x86)\\netload\\netload.exe",
true/* wait */ );

I thought perhaps it wanted some embedded quotes, but that does not
work either.

Will experiment further.

Command works fine at the prompt.

You may also read in the release notes - "Changes to Runtime.exec"
On Windows platform, the decoding of command strings specified to
Runtime.exec(String), Runtime.exec(String,String[]) and
Runtime.exec(String,String[],File) methods, has been improved to
follow the specification more closely. This may cause problems for
applications that are using one or more of these methods with
commands that contain spaces in the program name, or are invoking
these methods with commands that are not quoted correctly.

For example, Runtime.getRuntime().exec("C:\\My Programs\\foo.exe
bar") is an attempt to launch the program "C:\\My" with the
arguments "Programs\\foo.exe" and "bar". This command is likely to
fail with an exception to indicate "C:\My" cannot be found.
[...]
 
S

Sven Köhler

Am 20.04.2013 16:13, schrieb Joerg Meier:
Specifically, you use a path with a space in it. Frankly, I'm surprised
that ever worked. That being said, this seems to be a step back, not
forward.

I have a question for everybody here:

What would you expect
new ProcessBuilder("c:\test.exe", "a b").start();
to do on Windows?

Read the documentation of ProcessBuilder very careful.
In particular this passage:
a command, a list of strings which signifies the external program
file to be invoked and its arguments, if any. Which string lists
represent a valid operating system command is system-dependent. For
example, it is common for each conceptual argument to be an element
in this list, but there are operating systems where programs are
expected to tokenize command line strings themselves - on such a
system a Java implementation might require commands to contain
exactly two elements
http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html


What is should do:
1) It should pass the command line parameter string "a b" to the program
test.exe. Note: on Windows, command line parameters are a single string
- there is no array as on UNIX.
2) What Java currently does: Since "a b" contains spaces, Java adds
quotes to it. Hence, the parameter string that test.exe sees is "\"a
b\"" which is wrong.
3) Workaround: use "\"a\" \"b\"" instead of "a b" because Java doesn't
add quotes if the first and last character are quotes.


The current implementation of ProcessBuilder for Windows is simply broken.


Regards,
Sven
 
M

markspace

What would you expect
new ProcessBuilder("c:\test.exe", "a b").start();
to do on Windows?
2) What Java currently does: Since "a b" contains spaces, Java adds
quotes to it.

Which is correct, because if you wanted two separate arguments, you
would have read the docs and given the process builder two separate
arguments.

new ProcessBuilder("c:\\test.exe", "a", "b").start();

Note also that "\t" is Java escape for tab, so you didn't get either
argument correct, unless you had a Windows executable with a tab as the
first character.
 
S

Sven Köhler

Am 20.04.2013 19:24, schrieb markspace:
Which is correct, because if you wanted two separate arguments

Well, you should have read the part of the documentation I quoted.
Windows is one of the operating systems, where programs tokenize the
command line parameters by themselves - in which case the array passed
to the ProcessBuilder should contain exactly two elements. q.e.d.
 
M

markspace

Am 20.04.2013 19:24, schrieb markspace:

Well, you should have read the part of the documentation I quoted.
Windows is one of the operating systems, where programs tokenize the
command line parameters by themselves - in which case the array passed
to the ProcessBuilder should contain exactly two elements. q.e.d.

Uh, but the ProcessBuilder is obviously preventing tokenization by
putting quotes around the argument, because you only used one parameter....
 
J

Joerg Meier

Am 20.04.2013 19:24, schrieb markspace:
Well, you should have read the part of the documentation I quoted.
Windows is one of the operating systems, where programs tokenize the
command line parameters by themselves - in which case the array passed
to the ProcessBuilder should contain exactly two elements. q.e.d.

ProcessBuilder acts exactly the way Windows needs it to:

C:\Users\Maya>dir "c:\Program Files\Java"
Volume in drive C has no label.

Directory of c:\Program Files\Java

10/03/2012 09:55 PM <DIR> .
10/03/2012 09:55 PM <DIR> ..
10/03/2012 09:55 PM <DIR> jdk1.7.0_07
03/31/2013 12:46 PM <DIR> jre7
0 File(s) 0 bytes
4 Dir(s) 10,930,348,032 bytes free

C:\Users\Maya>dir c:\Program Files\Java
The system cannot find the file specified.

If you want to supply a single argument that contains a space under
Windows, it needs to be surrounded by quotes. Which is exactly what
ProcessBuilder does.

Liebe Gruesse,
Joerg
 
S

Sven Köhler

Am 20.04.2013 21:01, schrieb markspace:
Uh, but the ProcessBuilder is obviously preventing tokenization by
putting quotes around the argument, because you only used one parameter....

How would you propose to pass two arguments to a program on Windows, if
the documentation clearly states, that one should pass an array with
exactly two elements to the ProcessBuilder constructor?


Regards,
Sven
 
S

Sven Köhler

Am 20.04.2013 23:03, schrieb Joerg Meier:
If you want to supply a single argument that contains a space under
Windows, it needs to be surrounded by quotes. Which is exactly what
ProcessBuilder does.

I ask you the same question that I asked markspace:
How would you propose to pass two arguments to a program on Windows, if
the documentation clearly states, that one should pass an array with
exactly two elements to the ProcessBuilder constructor?
(The first element of course being the program name)
 
S

Sven Köhler

Am 20.04.2013 23:03, schrieb Joerg Meier:
ProcessBuilder acts exactly the way Windows needs it to:

Oh, and of course the ProcessBuilder doesn't behave as it is supposed
to. As mentioned in my first post, the String "\"a b\"" would be passed
unmodified to the program invoked. However, clearly, the string passed
to the program should have been
"\"\\\"a b\\\"\""

Only with the quotes and backslashes added, CommandLineToArgv would
decode it to "\"a b\"". With the current ProcessBuilder implementation,
a Windows program will see the parameter "a b" while on UNIX the program
will see "\"a b\"".

See
http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx
for details.

Note, that I assume that the program invoked uses CommandLineToArgv to
decode the command line. Which is by no means clear, as any program can
implement their own tokenizer.

Don't you find that a bit strange?


Regards,
Sven
 
D

Daniel Pitts

Am 20.04.2013 23:03, schrieb Joerg Meier:

I ask you the same question that I asked markspace:
How would you propose to pass two arguments to a program on Windows, if
the documentation clearly states, that one should pass an array with
exactly two elements to the ProcessBuilder constructor?
(The first element of course being the program name)
I think you've misinterpreted the documentation.

<http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html>

The first element of the array is the process name, the *rest* of the
elements are each exactly one parameter.

The documentation says some *programs* may tokenize the argument
themselves. If you are passing to such a program, then you need to use
exactly two element array.
 
S

Sven Köhler

Am 21.04.2013 01:03, schrieb Daniel Pitts:
The first element of the array is the process name, the *rest* of the
elements are each exactly one parameter.

The documentation says some *programs* may tokenize the argument
themselves. If you are passing to such a program, then you need to use
exactly two element array.

The documentation speaks of "operating systems where programs are
expected to tokenize command line strings themselves". Windows is that
type of operating systems. For that type of operating system, the list
of strings shall contain exactly two elements.

Here's the quote again:
a command, a list of strings which signifies the external program
file to be invoked and its arguments, if any. Which string lists
represent a valid operating system command is system-dependent. For
example, it is common for each conceptual argument to be an element
in this list, but there are operating systems where programs are
expected to tokenize command line strings themselves - on such a
system a Java implementation might require commands to contain
exactly two elements
Source:
http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html

And in fact, I can confirm that ProcessBuilder passes the second element
of the string list to the invoked external program - however only if the
argument starts and ends with a quote.

Regards,
Sven
 
S

Sven Köhler

Am 21.04.2013 00:56, schrieb Martin Gregorie:
Where do you get the two elements bit? My documentation (Java 6 Javadocs)
says you can pass either a List<String> list of items or one or more
Strings. Neither form requires exactly two elements. The only requirement
is that the first element must be the command name and the rest are the
arguments you're passing to it. If you're not looking at the Javadocs
documentation set for the JDK or JRE you using, then you're working from
incorrect information.

Start reading from the top of the page:
http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html

The first bullet points explains, that on some operating systems (e.g.
Windows), a valid command exist of exactly two Strings.

The constructor of ProcessBuilder on the other hand states that it does
not check whether the provided list of strings is a valid command.


Regards,
Sven
 
K

Knute Johnson

Nothing like experiment :) But two questions: what version of windows were
you using ? And what kind of external application were you testing it with ?
-- chris

I haven't followed this thread closely enough to really understand the
controversy. But I like experiments. And I never get to write anything
in C any more.

Windows XP (the results on Xubuntu 12.10 are identical)

One quoted argument "hello world"

C:\Documents and Settings\Knute Johnson>java test
argc=2
argv[0]=C:\Documents and Settings\Knute Johnson\test.exe
argv[1]=hello world
exitValue=123

Two arguments

C:\Documents and Settings\Knute Johnson>java test
argc=3
argv[0]=C:\Documents and Settings\Knute Johnson\test.exe
argv[1]=hello
argv[2]=world
exitValue=123

---

#include <stdio.h>

int main(int argc, char** argv) {
int i = 0;

printf("argc=%d\n",argc);
for (i=0; i<argc; i++)
printf("argv[%d]=%s\n",i,argv);

return 123;
}

---

import java.io.*;

public class test {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = new ProcessBuilder("test.exe","hello world");
// ProcessBuilder pb = new
ProcessBuilder("test.exe","hello","world");
pb.redirectError(new File("error"));

Process p = pb.start();
final InputStream is = p.getInputStream();

Thread t = new Thread(new Runnable() {
public void run() {
int n;
try {
while ((n = is.read()) != -1)
System.out.print((char)n);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
});
t.start();
t.join();

System.out.println("exitValue=" + p.exitValue());
}
}
 
A

Arved Sandstrom

Am 21.04.2013 00:56, schrieb Martin Gregorie:

Start reading from the top of the page:
http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html

The first bullet points explains, that on some operating systems (e.g.
Windows), a valid command exist of exactly two Strings.
It says *some* operating systems. No mention of Windows. It also says
"there are operating systems where programs are expected to tokenize
command line strings themselves" which is not Windows IME - the C, C++
and Java CLI programming interface is the same for these in UNIX, Linux,
OS-9 and Windows. There are probably some programming languages/
environments in which you'd be required to split out the CLI arguments
yourself (IIRC TAL on a Guardian NonStop system is one), but if you're
programing in that sort of environment then you'd be familiar with that
sort of CLI parsing and expect to do it.
The constructor of ProcessBuilder on the other hand states that it does
not check whether the provided list of strings is a valid command.
Of course. Its perfectly reasonable to expect the OS to determine whether
the first argument identifies a an executable file - every oyhet language
system (e.g. all the C standard library exec() functions work that way),
just as all command line arguments are passed to the called executable
for validation.

In short, if you've tried something like this:

ProcessBuilder pb = new ProcessBuilder("cmnd.exe", "arg1", "arg2",
"arg3");
pb.start();

and it doesn't work, try this:

ProcessBuilder pb = new ProcessBuilder("cmnd.exe", "arg1 arg2 arg3");
pb.start();

And for simplicity first try these with a program that is the equivalent
of:

public class Tester
{
public static main(String args)
{
for (int i = 0; i < args.length; i++)
System.out.println(args);
}
}

but written is written in the same language as the program(s) you want to
run with ProcessBuilder. What results did you see?

Great advice, you and Chris Uppal both. Every time I've had to run an
external program from Java (well, from anything) as an executable, it's
usually an OS-specific and app-specific thing. In each case I more or
less end up doing what you guys suggest: experimentation.

On one long-running set of related projects that's lasted over a year
now, this process of experimentation was even more extensive. The
problem involved accessing PostgreSQL data on a RHEL Linux box that
required SSH, with password. The access was/is from an ESB, Java-based.

To date I've found that tunneling and port forwarding works in some
situations, with the ssh command and Expect, in other cases it was
easier to use 'ssh' and 'empty' and to execute scripts on both the
client and DB server. These were all ProcessBuilder situations.

But in one situation the experiments made it clear that JSch was the
most reliable, dispensing with ProcessBuilder entirely.

In all of these cases I was able to discern what arguments were being
received by various targets, and that's what matters. That's what you
work with.

AHS
 
M

markspace

I haven't followed this thread closely enough to really understand the
controversy. But I like experiments. And I never get to write anything
in C any more.

I'm just too lazy to do this sort of thing. I applaud those of you who
are able to go above and beyond all reasonable efforts helping people.
I think the OP has just got a bee up his butt about the documentation
and won't stop to consider he may be reading it wrong. Your experiments
match what I assumed to be the case.
ProcessBuilder pb = new ProcessBuilder("test.exe","hello world");
argc=2
ProcessBuilder pb = new ProcessBuilder("test.exe","hello","world");
argc=3

Yup, that's what I thought. I'm really uncertain what the heck the OP
is on about.
 
A

Arved Sandstrom

I'm just too lazy to do this sort of thing. I applaud those of you who
are able to go above and beyond all reasonable efforts helping people. I
think the OP has just got a bee up his butt about the documentation and
won't stop to consider he may be reading it wrong. Your experiments
match what I assumed to be the case.



Yup, that's what I thought. I'm really uncertain what the heck the OP
is on about.
I think the points that Martin and Chris made is that for
system-specific access of this nature you don't even make too many
assumptions at all. You just do the experimentation that they described,
for the specific OS and program in question.

I can see why the guys work up a problem, it's fun, I've done it myself.
I do it when I don't actually know for a fact, so I code up a simple
app, in whatever. I'm the first one to admit, I often don't know off the
top of my head, which is why I am empirical. :)

I'm impressed with the guys that master a platform or language so well
that they are Knuthian, no need to run code, they know their statements
are correct. I can't do that myself, just in the last 12 months I've had
to deal with maybe 8-10 different programming languages, several dozen
new systems and APIs, and several dozen specifications. I have no idea
what the guys do that understand languages or OS systems programming or
concurrency like mother's milk come from, but they aren't EAI
consultants. :)

AHS
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top