2009-12-09 13 views
6

Quiero iniciar un navegador y cargar una página web utilizando el Runtime exec de Java. La llamada exacto es el siguiente:Java Runtime Exec en Windows falla con Unicode en Argumentos

String[] explorer = {"C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE", 
    "-noframemerging", 
    "C:\\ ... path containing unicode chars ... \\Main.html"}; 
Runtime.getRuntime().exec(explorer); 

En mi caso, la ruta contiene "\u65E5\u672C\u8A9E", los caracteres & # x65e5; & # x672c; & # x8a9e ;. Hay una solución viable que se pueda hacer solamente usando Java:

Al parecer es un error de Java: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4947220

Mi pregunta es? Parece que es posible escribir una biblioteca JNI para esto, pero me gustaría evitar eso si es posible. He intentado URI-codificación de la ruta como ascii y escribir los comandos en un archivo por lotes, sin éxito.

Respuesta

0

Estas son las dos soluciones que yo consideraba, cada uno de los cuales son más o menos soluciones:

  1. Crear un archivo html temperatura que redirigir el navegador a la página correcta redirigir. Tenga en cuenta que IE esperará unicode no codificado para archivos locales, mientras que otros navegadores solo aceptarán rutas de archivos codificadas en uri

  2. Utilice el nombre abreviado para el archivo de Windows. No contendrá caracteres Unicode.

-1

Creo que se puede utilizar Apache Commons Exec biblioteca o ProcessBuilder para dar una oportunidad;)

+0

ProcessBuilder parece tener el mismo problema con unicode en su cadena de argumento de comando. Lamentablemente, no puedo traer una biblioteca externa para mi caso particular. – Bear

+0

¿Qué le parece inicializar sus argumentos a las variables utilizando el método getPath() y usarlos en ProcessBuilder sin tocar ningún elemento que no sea unicode dentro del código fuente? – israkir

+0

Apache Commons Exec usa internamente la API Runtime.exec(), igual tendrá el mismo problema que antes. – Renan

2

En el mencionado Java bug page se encuentra una solución que se presentó a trabajar usando ProcessBuilder y envolviendo los parámetros de las variables de entorno. Aquí está el código fuente de la Parag Thakur:

String[] cmd = new String[]{"yourcmd.exe", "Japanese CLI argument: \ufeff\u30cb\u30e5\u30fc\u30b9"};   
Map<String, String> newEnv = new HashMap<String, String>(); 
newEnv.putAll(System.getenv()); 
String[] i18n = new String[cmd.length + 2]; 
i18n[0] = "cmd"; 
i18n[1] = "/C"; 
i18n[2] = cmd[0]; 
for (int counter = 1; counter < cmd.length; counter++) 
{ 
    String envName = "JENV_" + counter; 
    i18n[counter + 2] = "%" + envName + "%"; 
    newEnv.put(envName, cmd[counter]); 
} 
cmd = i18n; 

ProcessBuilder pb = new ProcessBuilder(cmd); 
Map<String, String> env = pb.environment(); 
env.putAll(newEnv); 
final Process p = pb.start(); 
0

Hemos estado utilizando un JNI para iniciar procesos de Java durante años. Ni Runtime.exec ni ProcessBuilder funcionarán, y parece poco probable que lo arreglen, dado cuánto tiempo ya ha pasado.

Sin embargo, debe ser capaz de evitar el problema mediante el flujo de entrada, un socket o variables de entorno para pasar los parámetros. Si no tiene control directo sobre el ejecutable, tendrá que crear un contenedor.

0

Puede usar JNA. Con la versión 3.3.0 o posterior llaman CreateProcess:

WinBase.PROCESS_INFORMATION.ByReference processInfo = 
    new WinBase.PROCESS_INFORMATION.ByReference(); 
WinBase.STARTUPINFO startupInfo = new WinBase.STARTUPINFO(); 

String command = "C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE " + 
    "-noframemerging \"C:\\\u65E5\u672C\u8A9E\\Main.html\""; 

if (!Kernel32.INSTANCE.CreateProcess(
    null,   // Application name, not needed if supplied in command line 
    command,  // Command line 
    null,   // Process security attributes 
    null,   // Thread security attributes 
    true,   // Inherit handles 
    0,    // Creation flags 
    null,   // Environment 
    null,   // Directory 
    startupInfo, 
    processInfo)) 
{ 
    throw new IllegalStateException("Error creating process. Last error: " + 
     Kernel32.INSTANCE.GetLastError()); 
} 

// The CreateProcess documentation indicates that it is very important to 
// close the returned handles 
Kernel32.INSTANCE.CloseHandle(processInfo.hThread); 
Kernel32.INSTANCE.CloseHandle(processInfo.hProcess); 

long pid = processInfo.dwProcessId.longValue(); 

redirigir la salida del proceso hijo es un poco más difícil, pero no imposible.

0

Crea un archivo .bat/.sh. Escriba sus comandos en ese archivo y ejecútelo. Asegúrese de haber cambiado la página de códigos a unicode en el caso de Windows (chcp 65001). Por ejemplo, para ejecutar el siguiente comando en Windows:

String[] command ={"C:\\aconex\\学校\\mysql\\bin\\mysql", "-esource", "大村箕島a\\data.sql"}; 

crear un archivo temporal denominado temp.bat y ejecutar con el Runtime.getRuntime() exec temp..bat

chcp 65001 
C:\aconex\学校\mysql\bin\mysql -esource 大村箕島a\data.sql 
Cuestiones relacionadas