2009-03-01 5 views
18

Estoy ejecutando un exe a través de mi programa java. la ruta está codificada en Java.ejecutar exe que se empaqueta dentro de jar

He empaquetado mi exe en el jar.

Pero estoy atascado ya que tengo el nombre de ruta codificado en el archivo java. así que no puedo ejecutar mi jar como un programa independiente.

¿Alguna sugerencia para el empaquetado de tales jar, es decir, tener un exe dentro y capaz de ejecutarlo como un programa independiente?

Gracias, Krisp

Respuesta

30

extraño que parezca que tengo que escribir código similar esta mañana ... gracias por empujarme a lograr eso :-)

Esto extraerá el .exe en un archivo local en el disco local. El archivo se eliminará cuando el programa Java exista.

Editar: ¡Vaya, se olvidó de hecho copiar el archivo ...

import java.io.Closeable; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.URI; 
import java.net.URISyntaxException; 
import java.net.URL; 
import java.security.CodeSource; 
import java.security.ProtectionDomain; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipException; 
import java.util.zip.ZipFile; 

public class Main 
{ 
    public static void main(final String[] args) 
     throws URISyntaxException, 
       ZipException, 
       IOException 
    { 
     final URI uri; 
     final URI exe; 

     uri = getJarURI(); 
     exe = getFile(uri, "Main.class"); 
     System.out.println(exe); 
    } 

    private static URI getJarURI() 
     throws URISyntaxException 
    { 
     final ProtectionDomain domain; 
     final CodeSource  source; 
     final URL    url; 
     final URI    uri; 

     domain = Main.class.getProtectionDomain(); 
     source = domain.getCodeSource(); 
     url = source.getLocation(); 
     uri = url.toURI(); 

     return (uri); 
    } 

    private static URI getFile(final URI where, 
           final String fileName) 
     throws ZipException, 
       IOException 
    { 
     final File location; 
     final URI fileURI; 

     location = new File(where); 

     // not in a JAR, just return the path on disk 
     if(location.isDirectory()) 
     { 
      fileURI = URI.create(where.toString() + fileName); 
     } 
     else 
     { 
      final ZipFile zipFile; 

      zipFile = new ZipFile(location); 

      try 
      { 
       fileURI = extract(zipFile, fileName); 
      } 
      finally 
      { 
       zipFile.close(); 
      } 
     } 

     return (fileURI); 
    } 

    private static URI extract(final ZipFile zipFile, 
           final String fileName) 
     throws IOException 
    { 
     final File   tempFile; 
     final ZipEntry  entry; 
     final InputStream zipStream; 
     OutputStream  fileStream; 

     tempFile = File.createTempFile(fileName, Long.toString(System.currentTimeMillis())); 
     tempFile.deleteOnExit(); 
     entry = zipFile.getEntry(fileName); 

     if(entry == null) 
     { 
      throw new FileNotFoundException("cannot find file: " + fileName + " in archive: " + zipFile.getName()); 
     } 

     zipStream = zipFile.getInputStream(entry); 
     fileStream = null; 

     try 
     { 
      final byte[] buf; 
      int   i; 

      fileStream = new FileOutputStream(tempFile); 
      buf  = new byte[1024]; 
      i   = 0; 

      while((i = zipStream.read(buf)) != -1) 
      { 
       fileStream.write(buf, 0, i); 
      } 
     } 
     finally 
     { 
      close(zipStream); 
      close(fileStream); 
     } 

     return (tempFile.toURI()); 
    } 

    private static void close(final Closeable stream) 
    { 
     if(stream != null) 
     { 
      try 
      { 
       stream.close(); 
      } 
      catch(final IOException ex) 
      { 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 
+7

No te olvides de configurar la bandera del ejecutable; de ​​lo contrario, tu código solo funciona en Windows. – akuhn

+2

+1 para crear un archivo temporal y marcarlo al salir. – gencoreoperative

+0

Sé que esta es una vieja pregunta, pero estoy tratando de usar un código similar a este con Windows 7, pero no puedo ejecutar '.exe's en el directorio temporal. Le agradecería si pudiera ver mi pregunta: http://stackoverflow.com/questions/18559835/access-denied-when-trying-to-execute-a-exe-in-appdata – Andy

11

El sistema operativo no le importa ni saber sobre el archivo .jar, por lo que tendrá que descomprimir el archivo .exe en cierta ubicación temporal antes de ejecutarlo.

+0

he copiado el archivo de recursos en el directorio raíz del proyecto utilizando el método descrito D.Snap y ahora me refiero al archivo así: "del archivo = new File (" your.exe"); ". Para que pueda abrir el archivo para escribir en el directorio raíz desde el directorio de recursos (si está utilizando un proyecto maven) así: "InputStream is = getClass(). GetResource (" su.exe "). OpenStream();" – hipokito

-5

Puede escribir un programa java simple para iniciar el exe usando Runtime.exec(). Luego podría establecer el atributo "Clase principal" del jar para que sea esa clase de iniciador. Los usuarios podrían ejecutar su jar y ejecutaría el exe.

+0

En este caso necesitaré codificar el camino exe en código java. Quiero hacerlo portátil. – krisp

+0

@Krisp. No es verdad.Puede usar Class/ClassLoader.getResource() para encontrar una ruta relativa dentro del jar – Kevin

+0

gracias ... esto parece ser una esperanza ... lo probaré y le haré saber. – krisp

3

Mientras que los demás usuarios no han respondido a la pregunta correcta, a continuación, extraer y ejecutar la limpieza. Otro punto a considerar es ir completamente nativo.

Ya está utilizando un binario nativo para realizar una tarea específica. ¿Por qué no también crear un instalador nativo que instalará su aplicación e instalará el binario en la ubicación específica del sistema operativo (Archivos de programa en Win32) y creará accesos directos adecuados.

De esta manera su aplicación se sentirá más nativa y significa que no necesita escribir o administrar el código para evitar este hecho. Por el momento, Jar parece una pieza de código multiplataforma (Jar se ejecuta en cualquier lugar, ¿verdad?) Pero contiene un binario nativo que no se ejecutará en todas partes. Esto se siente como una contradicción.

Para los instaladores puedo recomendar Nullsoft Installation System (NSIS) ya que tienen muchos excelentes tutoriales y muestras de código para aprender.

2

Uso

getClass().getResource(what).openStream() 

y copiar a otro archivo en el disco.

3
//gets program.exe from inside the JAR file as an input stream 
InputStream is = getClass().getResource("program.exe").openStream(); 
//sets the output stream to a system folder 
OutputStream os = new FileOutputStream("program.exe"); 

//2048 here is just my preference 
byte[] b = new byte[2048]; 
int length; 

while ((length = is.read(b)) != -1) { 
    os.write(b, 0, length); 
} 

is.close(); 
os.close(); 
Cuestiones relacionadas