# NetworkInterface.getHardwareAddress liefert null zurück



## Boggy (18. Apr 2012)

Hallo zusammen, 

bei folgendem Code erhalte ich auf mehreren Windows Rechnern für jedes Interface das durchlaufen wird für die Hardware Adresse null zurück. 
Auf Mac und Linux funktioniert es. 

Ich nutze java 1.6 und die Anwendung läuft in einem JBoss. 

ich hoffe ihr könnt mir helfen

viele Grüße


```
private String getMac() {
		try {
			Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
			while (ifaces.hasMoreElements()) {

				NetworkInterface net = ifaces.nextElement();
				byte[] byteArray = net.getHardwareAddress();

				// build readable mac address
				StringBuilder mac = new StringBuilder();
				if (byteArray != null) {
					for (int i = 0; i < byteArray.length; i++) {
						mac.append(String.format((i == 0 ? "" : ":") + "%02X",
								byteArray[i]));
					}

					Enumeration<InetAddress> addresses = net.getInetAddresses();

					
					while (addresses.hasMoreElements()) {
						InetAddress address = addresses.nextElement();
						
						if (!address.isLoopbackAddress() && net.isUp()) {
							return mac.toString();
						}
					}
				} else
					log.info("Iface  :" + net.getName() + "/"
							+ net.getDisplayName()
							+ " HardwareAdresse(MAC) is null");
			}
		} catch (Exception e) {
			log.warning("Mac nicht gefunden" + e.getLocalizedMessage());
		}
		return "empty";
	}
```


----------



## nillehammer (18. Apr 2012)

Du hast einen logischen Fehler in Deinem Code. Auf der einen Seite willst Du das erste Interface, das up ist, das nicht loopback ist und das eine HW-Adresse hat, finden und dessen Adresse als String zurückgeben. Auf der anderen Seite willst über *alle*Interfaces iterieren und mit log-Statements anzeigen lassen. Das erste hast Du geschafft. Mit dieser Zeile hier verlässt Du die komplette Methode, wenn Du ein Interface gefunden hast, dass alle o.g. Bedingungen erfült:

```
if (!address.isLoopbackAddress() && net.isUp()) {
							return mac.toString();
						}
```
Wenn Du bis zu diesem Ausstiegspunkt nur über Interfaces iteriert hast, die keine HW-Adresse haben (und das sind bei Windows einige), kriegst Du eben null angezeigt. Mach mal zum Vergleich ein

```
ipconfig /all
```
 und Du wirst sehen, dass dort mehr Interfaces angezeigt werden, als auf der Konsole Deines Javaprogramms.

P.S. Refactor unbedingt Deine Methode und zerlege sie in mehrere kleine. Faustregel: Ein Konzept/Algorithmus je Methode, nicht mehrere. Ich zähle in Deiner Methode mindestens 3 Konzepte (Macs finden, IPs finden, Byte-Array in HEX-String umwandeln).


----------



## Boggy (18. Apr 2012)

Danke nillehammer für deine schnelle Antwort. 
Ich habe die Methode nicht selbst geschrieben, sondern versuche nur den Bug zu finden. 
Selbstverständlich hast du recht und ich sollte sie splitten. Hohe Kappselung ist schließlich wichtig 
Allerdings werden mir bei ipconfig -all weniger interfaces angezeigt als in der Java Konsole. 

Ich habe zum testen mal return mac.toString(); auskommentiert und versucht den gleichen Code in einer normalen java applikation laufen zu lassen (ohne JBoss). Dort gibt er mir alle Macs aus. 
Kann es sein dass das Problem bei JBoss in Verbindung mit Windows liegt?
Bei Unix und iMac funktioniert es ja.


----------



## nillehammer (18. Apr 2012)

> Allerdings werden mir bei ipconfig -all weniger interfaces angezeigt als in der Java Konsole.


Sorry, mein Fehler. Ist bei mir auch so.


> Ich habe zum testen mal return mac.toString(); auskommentiert und versucht den gleichen Code in einer normalen java applikation laufen zu lassen (ohne JBoss). Dort gibt er mir alle Macs aus.
> Kann es sein dass das Problem bei JBoss in Verbindung mit Windows liegt?


Da kann ich nur spekulieren, aber ich würde annehmen, dass wenn du den Code mit auskommentiertem "_return mac.toString();_" im JBoss laufen lässt, Du dann auch alle MACs siehst. Oder hast Du auch das schon ausprobiert?


> Bei Unix und iMac funktioniert es ja.


Vielleicht sind die Interfaces dort schlicht down gewesen und er konnte deswegen komplett durch iterieren.


----------



## Boggy (18. Apr 2012)

> Da kann ich nur spekulieren, aber ich würde annehmen, dass wenn du den Code mit auskommentiertem "return mac.toString();" im JBoss laufen lässt, Du dann auch alle MACs siehst. Oder hast Du auch das schon ausprobiert?



Mir werden alle Interfaces ausgegeben aber keine einzige Mac Addresse. 



> Vielleicht sind die Interfaces dort schlicht down gewesen und er konnte deswegen komplett durch iterieren.



Halte ich für eher unwahrscheinlich, da die genauso im Netz hängen wie die Windowsrechner

Ich bin gerade dabei den Code zu refakturieren, evtl finde ich dann leichter den Bug.

Ich melde mich wenn es was neues gibt ^^


----------



## irgendjemand (18. Apr 2012)

alleine die signatur "String" ist schon ungewöhnlich wenn du "mehr als eine MAC" haben willst ...
klar kann man alles in einen string klatschen *ala XX:XX:XX:XX:XX/XX:XX:XX:XX:XX* ... aber dann muss man es im caller erst mit "split("/")" wieder in ein array auftrennen ... da kannst du auch gleich ein array returnen ...

am einfachsten vielleicht mit ner ArrayList und dann am ende toArray() *oder sowas* callen ...


----------



## Boggy (24. Apr 2012)

danke irgendjemand, aber das hat schon seinen zweck, ich brauche nur eine MAC und zwar die erste aktive. 
Zudem ist das leider nicht das problem  das wär nämlich schnell gelöst ^^


----------



## Boggy (24. Apr 2012)

Ich habe es jetzt mit einem kleinen workaround gelöst. 
Ist zwar nicht das schönste aber es tuts. 
Wenn jemand eine bessere möglichkeit weiß darf er sich gerne bei mir melden .


```
private ArrayList<String> getMacs(){

		ArrayList<String> macs = new ArrayList<String>();
		//Windows command to get a csv containing all macs without header
		Process proc = Runtime.getRuntime().exec("getmac /fo csv /nh");

		java.io.BufferedReader in = 
new java.io.BufferedReader(new java.io.InputStreamReader(proc.getInputStream()));

		String line = null;

		while ((line = in.readLine()) != null) {
			//split lines and get clean macs
			String[] result = line.split(",");
			macs.add(result[0].replace('"', ' ').trim());
		}
		
		return macs;
}
```


----------



## irgendjemand (24. Apr 2012)

da würde mir so einiges einfallen wie man das sauberer hinbekommt ... aber ein system-command callen ist immer die falsche wahl ...

muss mal sehen ob ich das nachher auf die schnelle zusammen bekomme *hatte sowas mal rumliegen .. aber datenträger crash* ...

geht auf jeden fall mit pure-java ... muss mich da nachher mal ransetzen ...


----------

