0

I want to set and echo a Windows variable in Java:

public static void main(String[] args) throws IOException
{

    Runtime rt = Runtime.getRuntime();
    String[] cmd = { "cmd.exe", "/c", "set HOSTNAME=%COMPUTERNAME% "
            + "&& echo %HOSTNAME%" };
    Process proc = rt.exec(cmd);

    BufferedReader stdInput = new BufferedReader(
            new InputStreamReader(proc.getInputStream()));

    BufferedReader stdError = new BufferedReader(
            new InputStreamReader(proc.getErrorStream()));

    System.out.println("Output:\n");
    String s = null;
    while ((s = stdInput.readLine()) != null)
    {
        System.out.println(s);
    }

    System.out.println("Error (if any):\n");
    while ((s = stdError.readLine()) != null)
    {
        System.out.println(s);
    }
}

I expect the program will print out my computer host name or I will use this value for another purpose. But the output is just like this:

Output:

%HOSTNAME%
Error (if any):

How could I get the value that I have set in the command set HOSTNAME=%COMPUTERNAME%

Hoang Nguyen
  • 61
  • 1
  • 13

2 Answers2

2

Your syntax for running two commands at once is wrong. Try using a single & in the command line instead of &&.

The real problem, I think, is that cmd.exe does all variable substitution before executing the command line (including parsing the &&). When it finds the syntax %HOSTNAME% for a variable that doesn't exist (yet), it leaves the text as is: %HOSTNAME%. So try issuing two commands to the same process, followed by an exit command.

Another approach is to change the command to:

set HOSTNAME=%COMPUTERNAME% & SET HOSTNAME

Then you will get back the string "HOSTNAME=my_computer_name", from which you can strip out the leading "HOSTNAME=" prefix.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • Not correct. `&&` can be used to run the next command only if the first one is successful. '&' is to run commands unconditionally. – Michael Markidis Aug 02 '17 at 03:56
  • @MichaelMarkidis - Yes, I realized that after posting. Too late at night to be doing this stuff. My answer is evolving into what I think the real problem is. :) – Ted Hopp Aug 02 '17 at 03:57
  • It's sorry, I have changed `&&` to `&` but the result does not change. – Hoang Nguyen Aug 02 '17 at 04:06
  • So, copy all your code `set HOSTNAME=%COMPUTERNAME% & SET HOSTNAME` I could get the right result. – Hoang Nguyen Aug 02 '17 at 04:09
  • this only works if you only want to print the variable out. It doesn't work if you want to use the variable string in command like `dir %HOSTNAME%\somedir` or `echo The hostname is %HOSTNAME%`. The correct way is delayed expansion – phuclv Aug 02 '17 at 04:20
2

It's irrelevant to Java because it's how cmd parses the command. The whole command will be parsed at once for variable expansion. At the time the command is parsed the variable is not yet available, so it'll be replaced with nothing in a batch file or leave as-is in command line

You need to use delayed expansion and print the variable with !!

cmd.exe /V:ON /c set HOSTNAME=%COMPUTERNAME% && echo !HOSTNAME!

The /V:ON is for enabling delayed expansion

CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF]
    [[/S] [/C | /K] string]
...
/V:ON   Enable delayed environment variable expansion using ! as the
        delimiter. For example, /V:ON would allow !var! to expand the
        variable var at execution time.  The var syntax expands variables
        at input time, which is quite a different thing when inside of a FOR
        loop.

In a batch file it can be enabled by setlocal EnableDelayedExpansion

However for that purpose just cmd.exe /V:ON /c echo %COMPUTERNAME% is enough. Yet it's still not the efficient way. There are better ways to get hostname in Java

Map<String, String> env = System.getenv();
if (env.containsKey("COMPUTERNAME"))
    return env.get("COMPUTERNAME");

or

InetAddress.getLocalHost().getHostName()
phuclv
  • 37,963
  • 15
  • 156
  • 475
  • Yes, my purpose is using the value of the variable but when I use your command I got an exception – Hoang Nguyen Aug 02 '17 at 07:05
  • Yes, my purpose is using the value of the variable but when I use your command `Process proc = rt.exec("cmd.exe /c /V:ON set HOSTNAME=%COMPUTERNAME% && echo !HOSTNAME!");` an exception is thrown: `The filename, directory name, or volume label syntax is incorrect.`. – Hoang Nguyen Aug 02 '17 at 07:13
  • 1
    @HoangNguyen - For this to work, the `/V:ON` needs to come before the `/C` on the command line. Otherwise `cmd.exe` gets confused. – Ted Hopp Aug 02 '17 at 07:26
  • @TedHopp - It works . The final code is `Process proc = rt .exec("cmd.exe /V:ON /c set HOSTNAME=%COMPUTERNAME% && echo !HOSTNAME!");`Thank you for your devotion. +1 – Hoang Nguyen Aug 02 '17 at 07:34
  • @TedHopp thanks about `/V:ON` order. I didn't check it – phuclv Aug 02 '17 at 07:51