# Dateien vom Windows-Explorer zum Programm senden



## RedFox (7. Mrz 2011)

Moin,

ich hab ein Programm geschrieben mit dem ich Dateien Multiplizieren/Kopieren/usw. kann.
Jetzt will ich Dateien im Windows-Explorer Makieren und die mit rechtsklick mit meinem Programm öffnen und die jeweiligen Aktionen ausführen, dabei läuft das Programm, also es darf kein neues Programm geöffnet werden, sondern beim geöffneten Programm die Dateien eingefügt werden, ählich wie ein Download-Manager mit Links, nur halt mit Dateien/Ordnern vom Windows-Explorer, weiß einer wie man das lösen kann?

Ich wiederhole nochmal: Das Programm läuft bereits, und darf nicht erneut geöffnet werden. Ich hab vielleicht gedacht ein art Programm zu schreiben, das die Dateien weiter leitet zu mein anderes Programm...

Bin schlecht im erklären, hab euch hoffentlich nicht verwirrt ^^

MFG RedFox


----------



## Dit_ (7. Mrz 2011)

Hi,

da muss doch das java-Programm tief im System integriert sein oder?

würde mich auch sehr interessieren ob sowas nur mit Java geht, wenn nicht dann einfach andere Sprache zu Hilfe nehmen oder in deinem Programm einen eigenen Explorer implementieren 

gruß


----------



## Andi_CH (7. Mrz 2011)

Wenn ich es richtig verstanden haben möchtest du im Kontextmenue -> senden an Dein Programm sehen.
Worauf dein Programm auf "magische" Art und Weise erfährt, dass es die entsprechende Datei zu lesen hat.

Stimmt das soweit? (Wenn ja, bin ich sehr gespannt auf die Antworten weil es mich auch interessiert)

Ich verstehe nur nicht, warum es so extrem relevant ist, dass das Programm schon läuft - üblicherweise wird ein Programm so gestartet (Mail, Texteditor .....) aber wenn sich über das Kontextmenue nur ein Programm starten lässt, ist das auch kein grösseres Problem. Das neu gestartete schickt dann halt dem anderen, schon laufenden Programm eine Meldung und terminiert dann.


----------



## maki (7. Mrz 2011)

> Jetzt will ich Dateien im Windows-Explorer Makieren und die mit rechtsklick mit meinem Programm öffnen und die jeweiligen Aktionen ausführe


Wenn ich mich nicht komplett irre reicht dafür ein Eintrag in die Registry.
Eingabeaufforderung direkt über das Kontextmenü des Explorers öffnen



> dabei läuft das Programm, also es darf kein neues Programm geöffnet werden, sondern beim geöffneten Programm die Dateien eingefügt werden


Das aufgerufene Progamm muss sich selber darum kümmern dass es nur einmal gestartet wird.


----------



## Andi_CH (7. Mrz 2011)

maki hat gesagt.:


> Wenn ich mich nicht komplett irre reicht dafür ein Eintrag in die Registry.
> Eingabeaufforderung direkt über das Kontextmenü des Explorers öffnen
> 
> Das aufgerufene Progamm muss sich selber darum kümmern dass es nur einmal gestartet wird.



Ein Eintrag in "öffnen mit" kann über das Kontextmenu selbst erstellt werden - vielleicht reicht der ja auch vielleicht muss es nicht zwingend "senden an" sein- 

Weisst du gerade wie Windows das gewählte File übergibt. (Ich habe dummerweise gerade keine Zeit für Versuche)


----------



## RedFox (7. Mrz 2011)

Also das mit dem Kontextmenü is kein problem damit kenne ich mich aus. Einfach in [HKEY_CLASSES_ROOT/*/shell/] einen neuen Key erstellen, unter diesem noch ein Key mit dem Namen Command und da bei Standard als value den Dateipfad angeben und danach noch nen %1 drannhängen, damit wird dann das jeweilige Programm gestarten mit der Datei.



Andi_CH hat gesagt.:


> [..]Ich verstehe nur nicht, warum es so extrem relevant ist, dass das Programm schon läuft[...]



Ich habe so eine art Betriebssystem gebaut, das darf nur einmal gestartet werden.



maki hat gesagt.:


> Das aufgerufene Progamm muss sich selber darum kümmern dass es nur einmal gestartet wird.



Ja da weiß ich nicht wie ich das anstelle, da ich nicht weiß wie man überprüfen kann ob solche instanz schon existiert.


----------



## maki (7. Mrz 2011)

> Weisst du gerade wie Windows das gewählte File übergibt. (Ich habe dummerweise gerade keine Zeit für Versuche)


Denke als Kommandozeile (wie im Link beschreiben), in den 90er Jahren gab es noch die Möglichkeit per OLE, aber das ist zu lange her als dass ich mich noch an die Details erinnere (konnte mit OLE auch komplett daneben liegen).



> Ja da weiß ich nicht wie ich das anstelle, da ich nicht weiß wie man überprüfen kann ob solche instanz schon existiert.


Man kann einen Port belegen, wenn dieser bereits belegt ist, läuft das Programm schon, alternativ geht das auch mit Dateien (aber nicht so sicher), oder man mischt beide Methoden (Datei + Port).
http://www.java-forum.org/allgemeine-java-themen/34662-verhindern-programm-mehrmals-geoeffnet.html


----------



## Andi_CH (7. Mrz 2011)

RedFox hat gesagt.:


> Ich habe so eine Art Betriebssystem gebaut, das darf nur einmal gestartet werden.
> 
> Ja da weiß ich nicht wie ich das anstelle, da ich nicht weiß wie man überprüfen kann ob solche Instanz schon existiert.



Ok, dann kannst du den Weg gehen den Maki beschreibt (Port) oder meinen (Hilfsprogramm), wobei du genau dasselbe Problem lösen musst. Du musst mit der schon laufenden Instanz kommunizieren.

Von der Denkweise her ist das mit dem Hilfsprogramm möglicherweise einfacher zu verstehen, aber es hat auch Nachteile (was wenn dein BS noch nicht läuft?)

Nächstes Thema dürfte Interprozesskommunikation sein


----------



## Andi_CH (8. Mrz 2011)

maki hat gesagt.:


> Wenn ich mich nicht komplett irre reicht dafür ein Eintrag in die Registry.
> Eingabeaufforderung direkt über das Kontextmenü des Explorers öffnen



Dummerweise passt der Link nicht so ganz - es soll ja keine "Eingabeaufforderung" sondern eben ein anderes Programm gestartet werden - ich suche dann schon noch, aber weiss gerade jemand wie man einen solchen Eintrag machen muss?


----------



## Michael... (8. Mrz 2011)

Andi_CH hat gesagt.:


> aber weiss gerade jemand wie man einen solchen Eintrag machen muss?


Unter "Documents and Settings" gibt es entweder userspezifisch oder beim "Default User" ein Verzeichnis "SendTo" hier kann man dann beliebige Verknüpfungen, Applikationen, Skripte... reinhängen, die im Kontextmenü unter "Senden an" bzw. "Send to" verfügbar sein sollen.


----------



## Andi_CH (8. Mrz 2011)

Nur nützt ein Eintrag hier nichts - bin ziemlich ratlos, aber ich hab mich soeben in einem Windowsforum angemeldet.


----------



## slawaweis (8. Mrz 2011)

ich habe so was schon mal gemacht. Mit dem folgenden Script (in "open-notepad.reg" speichern):


```
REGEDIT4

[HKEY_CLASSES_ROOT\*\shell]

[HKEY_CLASSES_ROOT\*\shell\Open Notepad]

[HKEY_CLASSES_ROOT\*\shell\Open Notepad\command]
@="notepad.exe \"%1\""
```

kann man z.B. erreichen, dass jede Datei über das Kontextmenu in Notepad geöffnet wird. Sehr nützlich übrigens. Man muss das Script natürlich vorher installieren.

Nun kann man mit einem ähnlichen Script sein eigenes Programm aufrufen, entweder über eine neue JVM oder über eine eigene EXE. Dieses Unterprogramm übergibt dann die Parameter an das Hauptprogramm und beendet sich. Falls das Hauptprogramm nicht läuft, wird es gestartet. Für eine reine Java Lösung gibt es JUnique:

JUnique - Prevent multiple instances of a Java application

Slawa


----------



## Andi_CH (8. Mrz 2011)

Bei was für einem Windows war das? Vermutlich XP - Ab Vista lese ich eben nichts mehr von Registry Einträgen...

(Dein Ziel erreicht man übrigens einfacher über das KontextMenu "öffnen mit ..." und sich dort zur Applikation durchklicken )


----------



## Michael... (8. Mrz 2011)

Eine Verknüpfung auf ein jar wird hier vermutlich nicht viel nutzen. Man könnte hier eine Verknüpfung auf ein batch File machen, welches die Java Applikation startet und dieser die selektierte Datei als Parameter übergibt.


----------



## Andi_CH (8. Mrz 2011)

Genau den Stand habe ich vor einer Minute auch erreicht - wenn ich ein exe angebe geht es, bei einem jar wird der Menupunkt nicht angezeigt - das soll einer verstehen, denn ich kann die Verknüpfung doppelklicken und es geht.

Die Lösung ist folgende:

Die Verknüpfung muss lauten:

```
C:\Programme\Java\jre6\bin\java.exe -jar C:\dvlp\temp\Test.jar
```

(Ja logisch läuft das so nur auf meiner Maschine  aber es ist ja wohl klar was angepasst werden muss)

Für den Fall dass man innerhalb der Software unterscheiden muss ob sie per "send to" oder direkt aufgerufen wurde wird empfohlen den Link z.B. mit /sendto oder etwas ähnlich eindeutigem zu ergänzen.

Mein Programm gibt nur die Parameterliste aus - was noch unangenehm ist, ist die Tatsache dass sich ein Cmd-Fenster (im Hintergrund sichtbar) öffnet und nicht von selbst schliesst.

Der Link hier lautet

```
C:\Programme\Java\jre6\bin\java.exe -jar C:\dvlp\temp\Test.jar /sendto
```


----------



## Michael... (8. Mrz 2011)

Im batch gibt's z.B. das Kommando start, damit wird die Anwendung ausserhalb des Konsolenfensters gestartet und das Konsolenfenster kann sich schließen.

```
start java -jar xxx.jar
```


----------



## Andi_CH (8. Mrz 2011)

Die Batchlösung sehe höhstens ich als unschönen Murks(work)-around  -- es ist ja wirklich nicht sehr elegant erst ein Batch zu starten, das java startet, das dann mein Programm startet - die Parameterübergabe vom Batch zum Javaprogramm ist auch noch spannend - wieviel Parameter soll man da übergeben - eigentlich weiss man ja nicht wieviele es sind - hm so auf Verdacht hin mal 20?

Es zeigt sich einmal mehr dass sich Java halt eben nicht so gut an Betriebssyteme ankoppeln lässt.

Doof finde ich natürlich das Verhalten von Windows - was auf Doppelklick geht sollte definitiv auch aus einem anderen Kontext gehen :-(

EDIT:

Was ncoh viel schlimmer ist, es nützt nicht einmal etwas:

Test.bat:

```
start java -jar c:\dvlp\temp\Test.jar %1 %2 %3
```

und das schwarze Fenster kommt und bleibt trotzdem ... Wenn ich noch genügend Haare hätte würde ich die mir jetzt wohl ausreissen :-(


----------



## slawaweis (8. Mrz 2011)

dann nimmt man noch zusätzlich launch4j:

Launch4j - Cross-platform Java executable wrapper

oder ein anderes Framework, welches eine Start-EXE erstellen kann. Oder man schreibt gleich in C/C++/C# ein eigenes Programm, welches sich selber registriert und die Parameter über ein Socket an die Java-Applikation übergibt. Hätte auch den Vorteil, dass keine JVM dafür gestartet werden muss.

Slawa


----------



## Michael... (8. Mrz 2011)

Andi_CH hat gesagt.:


> Was ncoh viel schlimmer ist, es nützt nicht einmal etwas:
> 
> Test.bat:
> 
> ...


benutze javaw statt java


----------



## RedFox (8. Mrz 2011)

So, ersteinmal Vielen Dank für euren ganzen Antworten.

Mit der Info auf JUnique von slawaweis ist es mir gelungen mein vorhaben zu erfüllen.

Für alle die es gerne wissen wollen, stelle ich ein beispielcode rein (Grundwissen muss vorhanden sein^^):

Zu erst müsst ihr JUnique Runterladen und in euer classpath setzen.

Die Main.java

```
package euer.package;

import it.sauronsoftware.junique.AlreadyLockedException;
import it.sauronsoftware.junique.JUnique;
import it.sauronsoftware.junique.MessageHandler;

public class Main {

    private static MainFrame mainFrame = null;
    private static final String APPID = "java.appid_00";
    private static boolean alreadyRunning;

    public static void main(String[] args) {
        try {
            JUnique.acquireLock(APPID, new MessageHandler() {
                public String handle(String message) {
                    mainFrame.handleMessage(message);
                    return null;
                }
            });
            alreadyRunning = false;
        } catch(AlreadyLockedException ex) {
            alreadyRunning = true;
        }

        if(!alreadyRunning) {
            mainFrame = new MainFrame();
        } else {
            for(int i=0; i<args.length; i++) {
                JUnique.sendMessage(APPID, args[i]);
            }
        }
    }

}
```

Die MainFrame.java (Dieser hier is als Vorschau angepasst der macht also nicht wirglich viel)

```
package OOSA;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;

public class MainFrame extends JFrame {

    DefaultListModel listModel = new DefaultListModel();
    JList list = new JList(listModel);

    public MainFrame() {
        initComponents();
        scrollPane_list.setViewportView(list);
        setVisible(true);
    }

    private void initComponents() {
        //AUTOMATISCH ERSTELLTER CODE VON NETBEANS
    }

    // Das muss in der MainFrame unbedingt drinn stehen damit ihr was mit dem Text anfangen könnt wenn er übergeben wird.
    public void handleMessage(String message) {
        listModel.addElement(message); // Wegen Vorschau werden hier alle args nur in eine JList eingefügt, ich werde da meine Datei Operationen machen.
    }

    // Variables declaration - do not modify
    private javax.swing.JScrollPane scrollPane_list;
    // End of variables declaration

}
```

Hier die .reg die ihr benutzen müsst damit ihr jede Datei mit dem Programm dann öffnen könnt (Bitte anpassen, und als name.reg Speichern und ausführen, oder gleich in die Registry Schreiben.):

```
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\*\shell\[B]NAMEHIER[/B]\Command]
@="javaw -jar [B]PFAD_ZUR_JAR.jar[/B] \"%1\""
```

Wenn ihr jetzt Rechtsklick auf einer Datei macht, könnt ihr auf *NAMEHIER* klicken, somit wird dann, wenn das Programm geöffnet ist, der Pfad zur JList hinzugefügt. Oder halt nur das Programm gestartet, ohne den Dateipfad mit drann zu hängen... Das würde man auch noch hinbekommen, das habe ich jetzt aber nicht nicht getestet.

MFG RedFox


----------



## slawaweis (8. Mrz 2011)

RedFox hat gesagt.:


> ```
> @="javaw -jar [B]PFAD_ZUR_JAR.jar[/B] %1"
> ```


man sollte das %1 in Anführungszeichen setzen, also *\"%1\"*. Sonst hat man Probleme bei Pfaden mit einem Leerzeichen, wie z.B. "C:\Dokumente und Einstellungen\..."

Slawa


----------



## Andi_CH (9. Mrz 2011)

Danke für den Hinweis mit javaw.

Bei Windows Vista und Windows 7 muss die Registry nicht editiert werden. Da muss der Eintrag als Link in 
	
	
	
	





```
C:\Users\<username>\AppData\Roaming\Microsoft\Windows\SendTo
```
 eingetragen sein.


----------

