Eigene CMD GUI zum Starten von JAR

Hallo Community.

Zurzeit habe ich ein kleines Projekt und hänge an einer Stelle. Da habe ich mir gedacht, ich meld mich hier mal an und frag nach. Ich habe schon viel Zeit in Suchen investiert und nur teilweise Ergebnisse gefunden, falls jedoch noch ähnliche Beiträge rum sind, wäre es sehr nett diese hier zu verlinken.

Und ich weiß nicht ob ich dieses Thema in das richtige Unterforum gepostet habe. Ansonsten bitte verschieben.

Mein Problem:
Ich möchte gerne eine GUI machen welche ähnlich der CMD-Konsole aussschaut. Mit dieser GUI möchte ich dann andere JAR-Dateien laden.

Der Code für das umleiten der Input/Output-Streams sowie der GUI ist von hier.
Der Code:
Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.concurrent.Executors;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
 
public class JCLGUI extends JFrame {

	private static final long serialVersionUID = -2161140285398426243L;
	JTextArea txtConsole;
    JTextField txtCommand;
 
    public JCLGUI() {
        super("JavaCommandLineWrapperExample");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
 
        txtConsole = new JTextArea(20, 80);
        txtConsole.setBackground(Color.BLACK);
        txtConsole.setForeground(Color.WHITE);
        txtConsole.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
        txtConsole.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                txtCommand.requestFocus();
                txtCommand.dispatchEvent(e);
            }
        });
        txtCommand = new JTextField(80);
        txtCommand.setBackground(Color.BLACK);
        txtCommand.setForeground(Color.WHITE);
        txtCommand.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
 
        txtConsole.setEditable(false);
 
        JScrollPane scrollPane = new JScrollPane(txtConsole);
 
        add(scrollPane);
        add(txtCommand, BorderLayout.SOUTH);
 
        setSize(900, 400);
        setVisible(true);
        txtCommand.requestFocus();
 
        startShell();
    }
 
    void startShell() {
        ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe")
                .redirectErrorStream(true);
 
        try {
            final Process process = processBuilder.start();
            final PrintWriter processInput = new PrintWriter(process
                    .getOutputStream());
            captureProcessOutput(process);
            txtCommand.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    processInput.println(txtCommand.getText());
                    processInput.flush();
                    txtCommand.setText("");
                }
            });
 
            int exitCode = process.waitFor();
            System.exit(exitCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    void captureProcessOutput(final Process process) {
        Executors.newSingleThreadExecutor().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    char c = (char) -1;
                    InputStream processOutput = process.getInputStream();
                    while ((c = (char) processOutput.read()) != -1) {
                        if ((byte) c == 12) {
                            /*
                             * der Byte-Code, der gesendet wird, wenn der
                             * Bildschirm gelöscht werden soll, in cmd.exe der
                             * Befehl "cls"
                             */
                            txtConsole.setText("");
                        } else {
                            // String s = Character.toString(c);
                            // txtConsole.append(new
                            // String(s.getBytes("CP1225")));
                            txtConsole.append(String.valueOf(c));
                        }
                        txtConsole.setCaretPosition(txtConsole.getText()
                                .length());
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
 
    public static void main(String[] args) throws Exception {
        new JCLGUI();
 
    }
}

Funktioniert ganz gut. Da die auszuführende JAR jedoch Dateien braucht die im selben Ordner liegen muss ich zuerst mit "cd" den Pfad ändern. Geht auch. Die JAR lässt sich mit "java -jar test.jar" auch starten jedoch kann ich keine Eingaben in der JAR machen. Bei der in diesem Fall auszuführenden JAR handelt es sich um die CraftBukkit.jar welche für Minecraft-Server gemacht wurde. Diese empfängt meine Befehle nicht. Jedoch ein einfacher Taschenrechner, gemacht mit Scannern, funktioniert.

Kann mir hier jemand helfen?

Gruß PNGamingPower
 
Zuletzt bearbeitet:
Du musst, ähnlich zur Ausgabe,
Code:
Process.getOutputStream()
nehmen und an den deine Eingaben senden.
 
Da ich den Code nur teilweise verstehe, weiß ich jetzt nicht genau wie ich vorgehen muss.
Könntest du mir vielleicht auch den Code den ich kopiert habe erklären bzw. wie ich das implementieren kann, dass die Eingaben auch ankommen?

EDIT:
Ich hab mir den Code nochmal angeschaut und etwas gegoogelt.
Jedoch weiß ich immer noch nicht wie ich das lösen kann.

@KrokoDiehl
Wo müsste ich das dann einbauen?
 
Zuletzt bearbeitet:
Ok, ich war etwas zu voreilig. Es wird tatsächlich schon etwas an den externen Prozess (cmd.exe) gesenden, und zwar das was du in das Textfeld schreibst.
Sieht soweit ok aus, also sollte es funktionieren.

Zur (Kurz-)Erklärung des geposteten Codes:

JCLGUI() - Baut die GUI auf: Eine TextArea in das die Ausgabe des Prozesses geschrieben werden und ein TextField in das man selbst Befehle an den Prozess schreiben kann.

startShell() - Startet den externen Prozess (cmd.exe), und "hängt" sich an die Ausgabeströme. Das Senden an den Prozess wird in dem ActionListener gemacht.

captureProcessOutput() - Startet einen Thread der auf die Ausgaben des Prozesses lauscht und diese dann in die TextArea schreibt.
 
Danke für die Erklärung.

Jedoch frag ich mich immernoch warum ich keine Befehle an die JAR schicken kann.
Ich schau mal in den Quellcode der JAR woran das liegen könnte.

Gruß PNGamingPower
 
Ich glaube das ansprechen der In/Outputstreams von cmd funktioniert nicht rightig, da hats schon einige Threads darüber gegeben afaik. Hast du schon mal probiert das jar direkt zu starten - also die java.exe aufzurufen?
 
Es ist so, dass man die JAR nur mithilfe eines bat Befehls starten kann.it dem simplen "java -jar craftbukkit.jar". Hast du das gemeint?

EDIT:
Dass stimmt so nicht. Es ist wahrscheinlich ein Manifest hinterlegt, jedoch beim Doppelklick wird dann ein javaw.exe Prozess gestartet. Jedoch ist dies eine reine Konsolenanwendung!
 
Zuletzt bearbeitet:
Abend miteinander.

Ich habe mir den Source mal angeschaut und herausgefunden, dass die einen eigenen ConsoleReader haben. Dass wird dann wohl der Grund sein warum ich keine Eingaben machen kann.

Selber lösen kann ich dieses Problem leider nicht, da ich den Source-Code nicht genug verstehe als dass ich meinen Code darauf umändern könnte (habe mit den Streams noch nicht so viel gearbeitet).

Vielleicht kann mir ja jemand von euch eine Lösung geben. Hier ist der Link zum ConsoleReader (denke mal dass das derjenige ist): ConsoleReader

Hier ab Zeile 86 wird er dann angewandt.

Hoffe jemand kann mir da helfen. Bin wie gesagt unerfahren im Bereich der Streams 🙂

Gruß PNGamingPower
 
Es hat sich erledigt.

Habs selber hinbekommen. Hab mir einfach ein Plugin gemacht welches mir den System.in der craftbukkit.jar ausliest (BufferedReader) und jetzt klappts.

Trotzdem danke an alle.

Thema kann geschlossen werden.

Gruß PNGamingPower
 

Neue Themen


Zurück
Oben