0

I have an issue that is similar to what is found here but the behavior seems to be a bit different on Windows 10: Setting the environment for ProcessBuilder

I want to set up the Path environment variable in a ProcessBuilder environment to send to a cmd /C call.

Consider:

if(platform.startsWith("Windows"))
{
    cmd = "cmd";
    command = new String[] {"/C", "prog.exe"};
}

String[] args = new String[]();
args.add(cmd);
args.add(command[0]);
args.add(command[1]);
ProcessBuilder pb = new ProcessBuilder(args);
Map<String, String> env = pb.environment();

// set environmental variables for libraries
if(platform.startsWith("Windows"))
{
    env.put("Path", env.get("Path") + ";" + "C:\\test");
}

Process process = pb.start();

Using Path is what is advised in the previous SO post, and that continues to work on Windows 7, but moving to Windows 10, it no longer finds prog.exe. What I dont understand is that if I change env.put("Path"... to env.put("PATH"... it now correctly finds prog.exe. Has environment variables changed in Windows 10? Im also under the impression that Windows environment variables are case insensitive, but if I set both PATH and Path I see each distinctly listed in the environment for Windows 7 and 10.

eckes
  • 10,103
  • 1
  • 59
  • 71
0-0
  • 482
  • 4
  • 11
  • 2
    Did you mean `"C:\\test"`? `"C:\test"` is actually the text `C:est`. – Andreas Aug 17 '16 at 17:59
  • 1
    Unable to reproduce. Code updates `Path` environment variable the same on Windows 7 and Windows 10. – Andreas Aug 17 '16 at 18:20
  • Yes sorry, that was a typo, converting from the original source to something smaller. – 0-0 Aug 17 '16 at 19:24
  • I would filter the environment to relace any caps forms of PATH and not put new ones. Or at least delete Path and PATH first before adding the new one. – eckes Aug 18 '16 at 00:26
  • 1
    Java's SDK does this already. See http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/windows/classes/java/lang/ProcessEnvironment.java#l195 – 0-0 Aug 18 '16 at 21:29

2 Answers2

2

In your Java application, the keys of a Map are case-sensitive. On the other hand, environment variable names are case-insensitive. The Map returned by ProcessBuilder.environment() will be able to keep separate entries keyed by "Path" and "PATH". You can see the two separate entries when you list the contents of the Map. However, when the Windows process is created, one of these two entries will overwrite the other in the process's environment table, since the name of the variable is deemed to be the same. To see that it has created a single entry for path, you need to give the ProcessBuilder the command list {"cmd","/c","SET"} and look at the output of the process.

I'm not sure why you say this behaviour differs between Windows 7 and 10. It shouldn't make any difference.

Klitos Kyriacou
  • 10,634
  • 2
  • 38
  • 70
  • 1
    This was my thought as well but HotSpot overrides the comparison for the Environment map. Refer to : http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/windows/classes/java/lang/ProcessEnvironment.java#l195 – 0-0 Aug 18 '16 at 17:34
1

This problem seems to be covered by https://bugs.openjdk.java.net/browse/JDK-8245431 which talks about ProcessBuilder.environment()'s map being case-sensitive even when System.getenv() is case-insensitive. The reporter expects the two to be consistent (as do I).

Gili
  • 86,244
  • 97
  • 390
  • 689
  • A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted.](/help/deleted-answers) – Marco Bonelli Oct 13 '20 at 19:45