# Betriebssystemunabhängig Umgebungsvariablen auslesen



## guni (8. Jul 2008)

Hallo,

ich versuche vergeblich, eine Umgebungsvariable auszulesen.
Mein Script muss später 
a) in verschiedenen Java-Versionen
b) unter Windows und Linux funktionieren.

wie kann ich Umgebungsvariablen auslesen, ohne System.getenv zu verwenden?!

mfg, guni


----------



## thE_29 (8. Jul 2008)

Welche Java Version?

Ab Java 1.5 sollte das mit getEnv funktionieren.


----------



## guni (8. Jul 2008)

java version "1.4.2_16"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_16-b05)
Java HotSpot(TM) Client VM (build 1.4.2_16-b05, mixed mode)

... und ich habe keine Chance das zu ändern.
wenn ich kompilieren möchte (javac -classpath . -deprecation Integration.java) bekomme ich folgende Meldung:

Integration.java:4: warning: getenv(java.lang.String) in java.lang.System has been deprecated
      System.out.println(System.getenv("PATH"));
                               ^
1 warning


----------



## guni (8. Jul 2008)

hmm ... ich hätte da jetzt einen Workaround gefunden, aber der stellt mich auch nicht wirklich zufrieden ...
nachdem ich nach der ganzen getenv-Fehlermeldung gegoogelt hab, bin ich auf folgende Lösung gestoßen:

in meinem Programm schreibe ich:

```
System.out.println(System.getProperty("env.variable"));
```
dann kompiliere ich das Programm.
und dann muss ich das Programm mit

```
java -Denv.variable=%IRGENDEINE_UMGEBUNGSVARIABLE% <programmname>
```
aufrufen.
das Problem an der Ganzen Sache ist aber folgendes:
unter Linux und unter Windows werden die Umgebungsvariablen ja unterschiedlich aufgerufen:

Windows: %VARIABLE%
Linux:      $VARIABLE

mein Problem ist, dass ich für Linux und Windows weder 2 verschiedene Aufrufe machen will noch kann!
also kommt diese Lösung für mich nicht in Frage!
Ausserdem versteh ich sowieso nicht, was diese Variante großartig davon unterscheidet, wenn ich die Umgebungsvariable einfach an mein args[]-Array der main-Methode übergeben würde ...

hmm ... hat irgendwer von euch eine schönere Lösung?!

mfg, guni


----------



## guni (8. Jul 2008)

hmm ... ich hätte da jetzt einen Workaround gefunden, aber der stellt mich auch nicht wirklich zufrieden ...
nachdem ich nach der ganzen getenv-Fehlermeldung gegoogelt hab, bin ich auf folgende Lösung gestoßen:

in meinem Programm schreibe ich:

```
System.out.println(System.getProperty("env.variable"));
```
dann kompiliere ich das Programm.
und dann muss ich das Programm mit

```
java -Denv.variable=%IRGENDEINE_UMGEBUNGSVARIABLE% <programmname>
```
aufrufen.
das Problem an der Ganzen Sache ist aber folgendes:
unter Linux und unter Windows werden die Umgebungsvariablen ja unterschiedlich aufgerufen:

Windows: %VARIABLE%
Linux:      $VARIABLE

mein Problem ist, dass ich für Linux und Windows weder 2 verschiedene Aufrufe machen will noch kann!
also kommt diese Lösung für mich nicht in Frage!
Ausserdem versteh ich sowieso nicht, was diese Variante großartig davon unterscheidet, wenn ich die Umgebungsvariable einfach an mein args[]-Array der main-Methode übergeben würde ...

hmm ... hat irgendwer von euch eine schönere Lösung?!

mfg, guni


----------



## Wolfram (8. Jul 2008)

Hi,

ich vermute, Du hast auch das "Real howto" gefunden - was passt Dir denn an der ReadEnv-Klasse nicht?

Grüße,
Wolfram


----------



## guni (8. Jul 2008)

Hallo Wolfram, 

hmm ... nein, die Methode selber hab ich in der Form noch nicht gesehen; vom Prinzip aber ist mir der Ansatz schon untergekommen ...
nun ja - irgendwie find ich die Lösung ein bisschen unschön: "IF os = windows THEN ... ELSE ..."
gibts da echt nix anderes ?!

mfg, guni


----------



## thE_29 (8. Jul 2008)

Hier mal meine Helper Klasse!

Hoffe das geht bei dir, bei mir klappts immer


```
package at.jta;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.File;
import java.io.BufferedWriter;
import java.io.FileWriter;

/************************************************************************************************************************************
 * 

Title: Reads out Environment, check for OS, check for Java version, etc...</p>
 *
 * 

Description: under LGPL</p>
 *
 * 

Copyright: Copyright (c) 2008</p>
 *
 * 

Company: Taschek Joerg</p>
 *
 * @author Taschek Joerg
 * @version 1.0
 ***********************************************************************************************************************************/
public class Helper
{

  /**********************************************************************************************************************************
   * Methode gibt das Environment zurück, aber mit einem Defaultwet
   * @param strWhat String
   * @param strDefault String
   * @return String
   *********************************************************************************************************************************/
  public static String getEnviroment(String strWhat, String strDefault)
  {
    String strRet = strDefault;
    //probiert es schon vorher über Java auszulesen wenn es > 1.5 ist
    strRet = getEnv15(strWhat);
    if (strRet != null)
      return strRet;
    else
      strRet = strDefault;
    String strTmp = "";
    if (checkOS().equals("linux"))
    {
      if (strWhat.indexOf("$") != -1)
      {
        strWhat = strWhat.replaceAll("$", "");
      }
      strTmp = "env";
    }
    else
    {
      if (strWhat.indexOf("%") != -1)
      {
        strWhat = strWhat.replaceAll("%", "");
      }
      strTmp = "set";
    }
    BufferedReader br = null;
    br = runScript(strTmp);
    try
    {
      while ( (strTmp = br.readLine()) != null)
      {
        //gefunden
        if (strTmp.toLowerCase().startsWith(strWhat.toLowerCase()) && strTmp.indexOf("=") != -1)
        {
          strRet = strTmp.substring(strTmp.indexOf("=") + 1);
          while ( (strTmp = br.readLine()) != null && strTmp.indexOf("=") == -1)
          {
            strRet += strTmp;
          }
        }
      }
      br.close();
    }
    catch (Exception ex)
    {
      ex.printStackTrace(System.out);
    }
    //ansonsten wenn es in der hashtable ist
    return strRet;
  }

  /***********************************************************************************************************************************
   * Methode holt über die Standardmethode von System den Wert raus
   * @param strVar String
   * @deprecated just works in >1.5
   * @return String
   **********************************************************************************************************************************/
  private static String getEnv15(String strVar)
  {
    String strRet = null;
    //wenn version nicht null ist und nicht mit 1.4 anfängt
    if (isGtJava15())
    {
      strRet = System.getenv(strVar);
    }
    return strRet;
  }

  /**********************************************************************************************************************************
   * Methode holt die Enviroment-Variablen
   * @param strWhat String welche Variable
   * @return String rückgabewert
   ********************************************************************************************************************************/
  public static String getEnviroment(String strWhat)
  {
    return getEnviroment(strWhat, null);
  }

  /**********************************************************************************************************************************
   * Methode sieht nach ob die Version >= Java 1.5 ist über die Methode setAlwaysOnTop in der Window Klasse
   * @return boolean
   *********************************************************************************************************************************/
  public static boolean isGtJava15()
  {
    boolean bRet = false;
    try
    {
      //sieht nach ob die Methode setAlwaysOnTop existiert ==> falls ja bist du >= java 1.5
      java.awt.Window.class.getDeclaredMethod("setAlwaysOnTop", new Class[] {boolean.class}); //wenn die Methode gefunden wurde
      bRet = true;
    }
    catch (java.lang.NoSuchMethodException ex)
    {
      bRet = false;
    }
    return bRet;
  }

  /**********************************************************************************************************************************
   * Gibt zurück welches OS du hast! Klein geschrieben!!
   * @return das kleingeschriebene OS!
   *********************************************************************************************************************************/
  public static String checkOS()
  {
    String strOSystem = "default";
    if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1)
      strOSystem = "windows";
    else if (System.getProperty("os.name").toLowerCase().indexOf("linux") != -1)
      strOSystem = "linux";
    else if (System.getProperty("os.name").toLowerCase().indexOf("unix") != -1)
      strOSystem = "unix";
    else if (System.getProperty("os.name").toLowerCase().indexOf("mac") != -1)
      strOSystem = "mac";
    return strOSystem;
  }  
  
  /**********************************************************************************************************************************
   * 
   * @param strCommand String
   * @return BufferedReader
   *********************************************************************************************************************************/
  public static BufferedReader runScript(String strCommand)
  {
    return runScript(new String[]{strCommand});
  }
  
  /***************************************************************************
   * Eigentliche Funktion diie ein Script macht und dieses dann ausführt!!
   * @param strCommands Befehl
   * @return den Reader auf den Prozess
   **************************************************************************/
  public static BufferedReader runScript(String[] strCommands)
  {
    BufferedReader in = null;
    in = new BufferedReader(new InputStreamReader(runScriptProc(strCommands).getInputStream()));
    return in;
  }

  /**********************************************************************************************************************************
   * Funktion führt die Befehl aus und gibt den Prozess zurück
   * @param strCommands befehle
   * @return gibt den Process zurück
   *********************************************************************************************************************************/
  public static Process runScriptProc(String strCommands[])
  {
    Process proc = null;
    String strFile = System.getProperty("java.io.tmpdir"); //speichert es ins tmp verzeichnis
    if (!strFile.endsWith(File.separator))
      strFile += File.separator;
    strFile += "tmpsc" + System.currentTimeMillis();
    if (checkOS().equals("windows"))
      strFile += ".bat";
    else
      strFile += ".sh";
    try
    {
      BufferedWriter out = null;
      out = new BufferedWriter(new FileWriter(new File(strFile))); //der writer
      for (int x = 0; x != strCommands.length; x++)
      {
        out.write(strCommands[x]);
        out.newLine();
      }
      if (checkOS().equals("windows"))
      {
        out.write("del " + strFile);
        out.flush();
        out.close();
      }
      else
      {
        out.write("rm " + strFile);
        out.flush();
        out.close();
        _waitForFile(strFile); //sollte warten bis File da ist
        Runtime.getRuntime().exec("chmod +x " + strFile).waitFor(); //setzt ausführbar
        new File(strFile).setExecutable(true); //probiert es so nochmals, sicher ist sicher
        Thread.currentThread().sleep(10);
      }
//      manageOldScripts(strFile); //fehlt hier
      if(_waitForFile(strFile))
         proc = Runtime.getRuntime().exec(strFile);
    }
    catch (Exception ex)
    {
      ex.printStackTrace(System.out);
    }
    return proc;
  }
  
  /****************************************************************************
   * Methode probiert 30mal ob es eine Datei schon gibt, falls ja = true
   * ansonsten false
   * @param strFile String
   * @return boolean
   **************************************************************************/
  public static boolean _waitForFile(String strFile)
  {
    boolean _abort = false, bRet = false;
    int _x = 0;
    try{
      while(!_abort)
      {
        File f = new File(strFile);
        if(f.exists())
        {
          _abort = true;
          return true;
        }
        Thread.currentThread().sleep(20);
        _x++;
        //wenn mehr als 30 Durchläufe sind
        if(_x >= 30)
        {
          System.out.println("DATEI::   " + strFile  +   " NOCH IMMER NICHT DA!! BRECHE AB!");
          _abort = true;
          return false;
        }
      }
    }
    catch(Exception ex)
    {}
    return bRet;
  }
}
```

Die alten Script Dateien werden aber nicht gelöscht.. Müsste man also noch einbauen!


----------



## FArt (8. Jul 2008)

guni hat gesagt.:
			
		

> Hallo,
> 
> ich versuche vergeblich, eine Umgebungsvariable auszulesen.
> Mein Script muss später
> ...



Kurz und knapp: geht nicht unter deinen Voraussetzungen.


----------



## guni (8. Jul 2008)

hmm ... sieht so aus als hätte ich also

a) die Implementierung einer seitenlangen Klasse
b) irgendeinen komischen Workaround wo ich die Umgebungsvariable als Parameter übergebe

zur Auswahl. Toll ... da werd ich mich eher für zweiters entscheiden.
hmm .... so gut mir Java bis jetzt gefallen hat, aber das ist echt schwach!
da muss man immer genau mit dem richtigen Compiler kompilieren - sonst geht da nix mehr


----------



## thE_29 (8. Jul 2008)

Was an a) so schlimm ist, verstehe ich zwar nicht..

Da ist b) eher noch schlimmer, weil wie kriegst du einen Benutzer dazu, dass er dir das Programm so aufruft?!


----------



## guni (8. Jul 2008)

der benutzer ruft das programm gar nicht auf. ich rufe das programm auf!
und zwar aus einem anderen programm heraus ...
insofern is es nicht so schlimm ...

a) gefällt mir einfach nicht - elends lange klasse nur um eine systemvariable richtig auszulesen ...


----------



## thE_29 (8. Jul 2008)

Wenn 255 Zeilen bei dir elendslange ist kann ich dir auch nicht mehr helfen. (ohne Kommentar 196)

Aber wenn du das Programm sowieso selbst aufrufst, kannst du Variante B nehmen.


----------



## guni (8. Jul 2008)

... und wenn ich schon eine extra Funktion dafür schreiben würde, dann würd die bei mir ca. so aussehen:


```
public static String getenv(String var) {

   String               this_os  = System.getProperty("os.name").toLowerCase();
   Map<String,String>   list_os  = new HashMap<String,String>();
   String               comn_cmd = "cmd.exe /c set "+var;
   String               curr_cmd = null;
   Runtime              r        = Runtime.getRuntime();
   Process              p        = null;
   
   list_os.add("windows 9",   "command.com /c set "+var);
   list_os.add("nt",          comn_cmd);
   list_os.add("windows 2",   comn_cmd);
   list_os.add("windows xp",  comn_cmd);
   list_os.add("others",      "echo $"+var);
   
   Iterator i = list_os.entrySet().iterator();
   
   while (i.hasNext()) {
      Map.Entry cur  = (Map.Entry)i.next();
      curr_cmd       = (this_os.indexOf(cur.getKey()) > -1) ? cur.getValue() : null;
   }
   
   curr_cmd          = (curr_cmd == null) ? list_os("others") : curr_cmd;
   p                 =  r.exec(curr_cmd);
   BufferedReader br =  new BufferedReader(new InputStreamReader(p.getInputStream()));
   return br.readLine();
}
```

... ob das jetz 100% Java-Code is kann ich nicht sagen, weil ich hab's nur im Notepad runtergetippt und ich bin ein Anfänger und hab bei der foreach-Iteration der Map / die Doku für BufferedReader nicht mehr extra nachgeschlagen ...
aber so in etwa müsste es doch eigentlich auch gehen!

mfg, guni


----------



## thE_29 (8. Jul 2008)

Problem ist/war, das manchmal der cmd /c set Befehl bei mir nicht ausführen ging.

Deswegen der Umweg über ein Script und was ist wenn eine Variable bei dir mehr als über eine Zeile lang ist (zB PATH).

Was noch ist, das ich auf Java 1.5 Abfrage und falls es das ist, dann nimm das Java 1.5 getEnv! Und wenn dein Programm in 1.4.2 ist, geht das da oben sowieso nicht 

Edit: oho, also das länger als eine Zeile geht zumindest unter Windows  Wie gesagt, ich hatte meistens das Problem unter Linux, deswegen die Umwege.

Nachtrag2: Im Linux gehts nicht.. Gibt er $VARIABLE aus..


----------



## guni (9. Jul 2008)

hmm ... ok - danke für die Antwort - hab mir ehrlich gesagt zu wenig Gedanken über das Ganze gemacht ... das scheint dein Skript doch etwas professioneller und durchdachter zu sein ... schade, dass es da keine (versionsunabhängige!) einfache Fertiglösung gibt!


----------

