2010-10-14 17 views
8

He estado luchando para encontrar la "descripción" de la computadora en la que se ejecuta mi aplicación Java.¿Cómo puedo encontrar mi "descripción de la computadora" en una aplicación Java en Windows y/o Mac?

Lo que busco es el nombre que se usa para DNS al anunciar mi computadora en la red local ("iMac Mattijs" en las capturas de pantalla a continuación).

En Windows XP, este nombre se puede encontrar aquí: Panel de control -> Sistema -> Nombre del equipo -> Descripción de la computadora.

alt text

En Mac OS 10.6, este nombre se puede encontrar aquí: Preferencias del sistema -> Compartir -> Nombre de equipo

alt text

Los métodos a continuación no entregan el nombre I Estoy buscando. Echar un vistazo a este código:

System.out.println("COMPUTERNAME environment variable: " + System.getenv("COMPUTERNAME")); 
    try { System.out.println("localhost name: " + InetAddress.getLocalHost().getHostName()); } 
    catch (UnknownHostException e1) {} 

    try { 
     Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); 
     while (interfaces.hasMoreElements()) { 
      NetworkInterface thisInterface = interfaces.nextElement(); 
      Enumeration<InetAddress> addresses = thisInterface.getInetAddresses(); 

      System.out.println("* network interface: " + thisInterface.getDisplayName()); 
      while (addresses.hasMoreElements()) { 
       InetAddress address = addresses.nextElement(); 
       System.out.println(" - address: " + address.getCanonicalHostName()); 
      } 
     }   
    } catch (SocketException e) {} 

En Windows, esta impresiones:

COMPUTERNAME environment variable: ARTTECH-51CA5F5 
localhost name: arttech-51ca5f5 
* network interface: MS TCP Loopback interface 
- address: localhost 
* network interface: NVIDIA nForce Networking Controller - Packet Scheduler Miniport 
* network interface: Broadcom 802.11n Network Adapter - Packet Scheduler Miniport 
- address: arttech-51ca5f5.lan 
* network interface: Bluetooth Device (Personal Area Network) 

En Mac, me sale:

COMPUTERNAME environment variable: null 
localhost name: imac-mattijs.lan 
* network interface: en1 
- address: imac-mattijs.lan 
- address: imac-mattijs.local 
* network interface: lo0 
- address: localhost 
- address: fe80:0:0:0:0:0:0:1%1 
- address: localhost 

pero estoy en busca de la cadena completa "iMac Mattijs ".

¡Cualquier pista sería bienvenida!

Gracias, Mattijs

+0

"Descripción" no debería tener nada que ver con DNS –

+0

Hola Matt, este "Descripción PC" (Windows)/"Nombre de equipo "(Mac OS) es lo que veo cuando encuentro mi computadora en la red local. Aparentemente, este nombre ingresado manualmente es anunciado por Bonjour/DNSSD, ¿no crees? – Mattijs

+0

Esto parece ser específico de la plataforma, por lo que tendrá que recuperar el nombre de la computadora que desea de forma diferente para cada plataforma que desea admitir en su aplicación Java. – Bernard

Respuesta

3

Mac OS X almacena el nombre de la computadora en el almacén dinámico de configuración del sistema. La interfaz estándar para esto es a través del marco de configuración del sistema. La herramienta de línea de comandos ejercicio de esta API es scutil: (. He cambiado temporalmente mi nombre de equipo para algo con espacios y puntuacion por lo que sería fácilmente distinguible del nombre de host, que en este caso sería algo así como hermes-is-awesome.local)

$ scutil --get computerName 
Hermes is awesome! 

puede interactuar con este bonito fácilmente usando JNI:

class SCDynamicStore { 
    public native String copyComputerName(); 
    static { 
    System.loadLibrary("SCDynamicStore"); 
    } 
} 

class HostnameSC { 
    public static void 
    main(String[] args) { 
    SCDynamicStore store = new SCDynamicStore(); 
    String computerName = store.copyComputerName(); 
    System.out.format("computer name: %s\n", computerName); 
    } 
} 

Ahora javac FILE.java y luego javah SCDynamicStore. Esto produce SCDynamicStore.h. Copia esto en SCDynamicStore.c y editar para que se lea:

#include "SCDynamicStore.h" 
#include <SystemConfiguration/SystemConfiguration.h> 

JNIEXPORT jstring JNICALL 
Java_SCDynamicStore_copyComputerName(JNIEnv *env, jobject o) 
{ 
    SCDynamicStoreRef store = NULL; 
    CFStringRef computerName = NULL; 
    CFStringEncoding UTF8 = kCFStringEncodingUTF8; 
    CFIndex length; 
    Boolean ok; 
    jstring computerNameString = NULL; 
    CFStringRef process = CFSTR("com.me.jni.SCDynamicStore"); 

    store = SCDynamicStoreCreate(NULL, process, NULL/*callout*/, NULL/*ctx*/); 
    if (!store) { 
    fprintf(stderr, "failed to get store\n"); 
    goto CantCreateStore; 
    } 

    computerName = SCDynamicStoreCopyComputerName(store, NULL); 
    if (!computerName) { 
    fprintf(stderr, "failed to copy computer name\n"); 
    goto CantCopyName; 
    } 

    length = CFStringGetLength(computerName); 
    length = CFStringGetMaximumSizeForEncoding(length, UTF8); 
    { 
    char utf8[length]; 
    if (!CFStringGetCString(computerName, utf8, sizeof(utf8), UTF8)) { 
     fprintf(stderr, "failed to convert to utf8\n"); 
     goto CantConvert; 
    } 
    computerNameString = (*env)->NewStringUTF(env, utf8); 
    } 

CantConvert: 
    CFRelease(computerName); 
CantCopyName: 
    CFRelease(store), store = NULL; 
CantCreateStore: 
    return computerNameString; 
} 

(Usted podría simplificar el código mediante el uso de Obj-C puente de teléfono gratuito y aprovechando -[NSString UTF8String].Podría ser conveniente lanzar una excepción en lugar de solo devolver NULL en algunos casos de error.)

Puede compilar esto usando clang -shared -I/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Headers/ -framework CoreFoundation -framework SystemConfiguration SCDynamicStore.c -o libSCDynamicStore.dylib.

Ahora, siempre es libSCDynamicStore.dylib lo largo LD_LIBRARY_PATH, que será cuando se encuentra en el directorio actual, puede ejecutar la aplicación:

$ java HostnameSC 
computer name: Hermes is awesome! 
+0

esta es una gran respuesta, es muy completa, y funciona !! ¡Muchas gracias! En aras de la integridad, tal vez podrías cambiar 'java FILE.java' por' javac FILE.java' (asumiendo que eso es lo que querías decir). Una vez más, ¡gracias por tu ayuda! – Mattijs

1

¿Seguro que no estás justo después de la variable de entorno NOMBREDEEQUIPO, que es lo que se ve en la ventana del panel de control?

+0

Hola Michael, gracias por tu respuesta. La variable COMPUTERNAME devuelve el nombre completo de la computadora, una cadena algo críptica que incluye algunos números y caracteres aparentemente aleatorios. Lo que necesito es la descripción más legible de la computadora (Windows)/nombre de la computadora (mac os), como se explicó anteriormente. – Mattijs

+1

@Mathijs: ese nombre no suele estar en DNS. – reinierpost

3

Debe saber que una sola computadora puede tener varios nombres de DNS.

Prueba esto para obtener un nombre:

  • llamada java.net.NetworkInterface.getNetworkInterfaces() para obtener todas las interfaces de red;
  • devuelto, llame al java.net.NetworkInterface.getInetAddresses() para obtener todas las direcciones IP de una interfaz;
  • Para cada dirección IP devuelta, llame al java.net.InetAddress.getCanonicalHostName() para obtener el nombre de host asociado;
  • Elija uno de los nombres de host.
+0

Hola Steve, gracias por tu respuesta. Intenté su sugerencia, pero desafortunadamente esta ruta no entrega el nombre de la computadora que necesito, como se describe en mi pregunta, sino el nombre completo de la computadora. – Mattijs

+0

@Mattijs Impar La documentación en 'InetAddress.getCanonicalHostName()' indica que devuelve el nombre de host completo si es posible. ¿Qué devuelve? –

+0

Hola Steve, agregué capturas de pantalla a mi publicación original para ilustrar el problema. 'InetAddress.getCanonicalHostName()' devuelve arttech-51ca5f5, pero estoy buscando el nombre "iMac Mattijs" – Mattijs

2

¿Qué le parece usar InetAddress. getHostName()?

System.out.println(
"Name: " + java.net.InetAddress.getLocalHost().getHostName()); 

Editar: Así que la respuesta anterior obviamente no es lo que quería. Sin embargo ... El proyecto MAST proporciona un método para recuperar la descripción de la computadora. Ver SysUtils. getComputerDescription(). Este método es específico del sistema operativo. La página de inicio del proyecto dice que una versión de OSX está en proceso.

+0

de hecho, mirando la API, parece que MAST encontró una manera de hacer lo que necesito en Windows. Desafortunadamente, su fuente no parece estar abierta. – Mattijs

+0

Sí, noté que el proyecto está cerrado. Bastante desafortunado Me imagino que acaban de escribir una biblioteca JNI para hacer todo el trabajo sucio, por lo que podrías hacer lo mismo si lo necesitas lo suficiente. – Andy

0

Esa Descripción/Nombre del equipo es el nombre de host del servidor local.Esto se puede comprobar mediante la comprobación de su línea de órdenes, que por lo general muestra ComputerName:CurrentDirectory User$ correspondiente a una fiesta por defecto pedirá export PS1="\[email protected]\h\w: "

Así usando:

try { 
    InetAddress addr = InetAddress.getLocalHost(); 

    // Get hostname 
    String hostname = addr.getHostName(); 
} catch (UnknownHostException e) { } 

usted debería ser capaz de obtener el nombre localhost como desee. Espero que esto ayude.

ref:

`

+0

¿En qué se diferencia esto de la respuesta que publiqué? – Andy

+0

además del pequeño párrafo no hay diferencia particular ... Podría haberlo perdido, mi mal ... – posdef

+0

como puede ver en mi pregunta, lamentablemente este método no devuelve el nombre que necesito. – Mattijs

0

Allright, he encontrado una manera de hacer esto por mí mismo, pero sólo en Mac OS. La recompensa aún está abierta para las personas que pueden encontrar una manera de responder mi pregunta sobre Windows.

La ejecución de esta aplicación devuelve Computer Description: iMac Mattijs

import java.net.InetAddress; 
import java.net.UnknownHostException; 
import java.util.HashMap; 

import com.apple.dnssd.*; 

/** 
* Example of finding your computer description. Tested on Mac OS 10.6, Java 1.6 
* 
* Note: make sure you're not compiling with JavaSE-1.6 but with JVM 1.6.0 (MacOS X Default), otherwise access to DNSSD libraries will be restricted. 
* 
* @author mattijskneppers 
*/ 

public class DescriptionFinder implements BrowseListener, ResolveListener { 
    InetAddress local = null; 
    HashMap<DNSSDService, String> fileSharingNameMap = new HashMap<DNSSDService, String>(); 

    public static void main(String[] args) { 
     new DescriptionFinder(); 
    } 

    public DescriptionFinder() { 
     try { local = InetAddress.getLocalHost(); } catch (UnknownHostException e) { System.out.println("Error, couldn't resolve local host"); } 

     try { 
      DNSSD.browse("_afpovertcp._tcp", this); 
     } catch (DNSSDException e) { 
      System.out.println("DeviceFinder: problem browsing for new file sharing"); 
      e.printStackTrace(); 
     }  
    } 

    @Override 
    public void operationFailed(DNSSDService arg0, int arg1) {} 

    @Override 
    public void serviceResolved(DNSSDService resolver, int flags, int ifIndex, String fullName, String hostName, int port, TXTRecord txtRecord) { 
     InetAddress[] addresses = null; 
     try { 
      addresses = InetAddress.getAllByName(hostName); 
     } catch (UnknownHostException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     InetAddress ip = null; 
     for (InetAddress address : addresses) { 
      if (!address.isLinkLocalAddress()) { 
       ip = address; 
       break; 
      } 
     } 

     String fileSharingName = fileSharingNameMap.get(resolver); 
     if (fileSharingName != null) { 
      if (ip.equals(local)) { 
       System.out.println("Computer Description: " + fileSharingName); 
      } 
     }  
    } 

    @Override 
    public void serviceFound(DNSSDService service, int flags, int ifIndex, String serviceName, String regType, String domain) { 
     //System.out.println("found file sharing: " + serviceName + ", domain: " + domain + ", regType: " + regType + ", flags: " + flags); 
     try { 
      DNSSDService resolver = DNSSD.resolve(flags, ifIndex, serviceName, regType, domain, this); 
      fileSharingNameMap.put(resolver, serviceName); 
     } catch (DNSSDException e) { 
      System.out.println("DeviceFinder: problem resolving new filesharing device"); 
      e.printStackTrace(); 
     }   
    } 

    @Override 
    public void serviceLost(DNSSDService service, int flags, int ifIndex, String serviceName, String regType, String domain) {} 
} 
+0

Esto solo funcionará si el usuario tiene Uso compartido de archivos activado. –

+0

@Jeremy: tienes razón. Su solución es absolutamente el camino a seguir. – Mattijs

3

No creo que es posible conseguir esto sin ir nativo. Si puede encontrar una biblioteca java que le dé acceso a WMI, puede obtenerla desde el objeto Win32_OperatingSystem en el campo Descripción.

Google ofrece algunas posibles opciones;

http://henryranch.net/software/jwmi-query-windows-wmi-from-java/
Muy simple (y gratis) si un poco hacky. Parece que funciona escribiendo scripts .vbs en un directorio de temperatura e invocándolos con Runtime.getRuntime().exec() y cscript.exe.

https://com4j.dev.java.net/

http://sourceforge.net/projects/jacob-project/
puente de Java COM.

Creo que Microsoft JVM tiene bits nativos incluidos que pueden ayudar también.

+0

gracias por estos consejos! Echaré un vistazo y veré si puedo encontrar la forma de :) :) – Mattijs

4

Esto es lo que he encontrado en algunos experimentos. El equipo Descripción se almacena en la clave de registro

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ LanmanServer \ Parameters \ srvcomment

Por lo tanto, si tenemos cualquier API que podemos utilizar para obtener los valores clave reg, podemos encontrarlo.

Además, encontramos el siguiente enlace que da una buena clase para consultar los valores clave reg:

http://www.rgagnon.com/javadetails/java-0630.html

Y, Utilización de la clase WinRegistry da en el sitio anterior, no pude encontrar con éxito el equipo Descripción utilizando el código:

String computerName = WinRegistry.readString(WinRegistry.HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\services\\LanmanServer\\Parameters", "srvcomment"); 
+0

¡Esta es una gran respuesta, funciona perfectamente! Aunque marqué la respuesta de Jeremy para Mac como "la" respuesta, esta solucionó mi problema para Windows, y usted es un nuevo usuario, ¡así que le otorgué la recompensa! ¡Gracias! – Mattijs

+0

Gracias Mattijs !!! – Balaram

+0

Por favor, por favor, no haga esto. Esta clave de registro está [técnicamente documentada] (http://technet.microsoft.com/en-us/library/cc787346 (v = ws.10) .aspx), pero esta no es la forma admitida de consultar esta información. Use 'NetServerGetInfo' con' SERVER_INFO_101'; esto estará disponible a través de C/C++, Pinvoke o JNI. En particular, algunos productos de AV bloquean la clave de registro, pero la API de red continúa funcionando. –

3
  1. Obtener com4j (enlace de descarga directa) whic h es una biblioteca de Java para realizar llamadas a COM.

  2. Descomprime y en la carpeta de muestra encontrarás una muestra de WMI .

  3. Cambie Main.java a lo siguiente y debe configurarlo.

 
    package wmi; 

    import com4j.Com4jObject; 
    import wmi.events.ISWbemSinkEvents; 

    public class Main { 
     public static void main(String[] args) throws Exception { 
      System.out.println("Connecting to WMI repository"); 
      ISWbemLocator wbemLocator = ClassFactory.createSWbemLocator(); 
      ISWbemServices wbemServices = 
        wbemLocator.connectServer(
         "localhost","Root\\CIMv2","","","","", 
         0,null); 

      System.out.println("connected"); 
      { 
       System.out.println("Query Computer Description"); 
       ISWbemObjectSet result = wbemServices.execQuery(
         "Select Description from Win32_OperatingSystem", 
          "WQL",48,null); 
       for(Com4jObject obj : result) { 
        ISWbemObject wo = obj.queryInterface(ISWbemObject.class); 
        System.out.println(wo.getObjectText_(0)); 
       } 
      } 
     } 
    } 
 
+0

Aunque esto parece un poco más elaborado que consultar la clave de registro directamente, esta es probablemente la forma oficial de hacerlo en Windows. ¡Y es un gran ejemplo! Me gustaría poder otorgar el premio dos veces, o al menos marcar varias respuestas como la respuesta aceptada. ¡Probé esto y funciona! ¡¡Gracias!! – Mattijs

1

"puro" nombre de equipo para MAC:

private static String getComputerName() { 
      String s = ""; 
      try { 
       Process proc = Runtime.getRuntime().exec("scutil --get ComputerName"); 
       InputStream in = proc.getInputStream(); 
       int b; 
       while ((b = in.read()) >= 0) { 
        s += (char)b; 
       } 
       in.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      return s; 
     } 
Cuestiones relacionadas