Frage

Ich verwende launch4j als Wrapper für meine Java-Anwendung unter Windows 7, die mein Verständnis im Wesentlichen Gabel eine Instanz von javaw.exe wiederum, dass der Java-Code interpretiert. Als Ergebnis beim Versuch, meine Anwendung auf die Taskleiste Pin, Pins von Windows statt javaw.exe. Ohne die erforderliche Befehlszeile, wird meine Anwendung dann nicht ausgeführt werden.

Ergebnis einer launch4j Anwendung in der Taskleiste Pinning

Wie Sie sehen können, von Windows auch nicht erkennen, dass Java die Host-Anwendung ist. Die Anwendung selbst als „Java (TM) Platform SE binären“ beschrieben wird

Ich habe versucht, den Registrierungsschlüssel HKEY_CLASSES_ROOT\Applications\javaw.exe Ändern Sie den Wert IsHostApp hinzuzufügen. Dadurch ändert sich das Verhalten von insgesamt Pinning meiner Anwendung zu deaktivieren; eindeutig nicht das, was ich will.

Ergebnis der Angabe javaw.exe als Host-Anwendung

Nach der Lektüre über , wie Windows interpretiert Instanzen eines einzelne Anwendung (und ein Phänomen, in dieser Frage diskutiert ), wurde ich daran interessiert, eine Anwendung Benutzermodell ID (AppUserModelID) in meine Java-Anwendung eingebettet werden.

Ich glaube, dass ich dieses Problem lösen kann eine einzigartige AppUserModelID auf Windows, indem. Es gibt eine shell32 Methode hierfür SetCurrentProcessExplicitAppUserModelID . Nach Gregory Pakosz Vorschlag, ich habe es in einem Versuch implementiert meine Anwendung als separate Instanz von javaw.exe erkannt haben:

NativeLibrary lib;
try {
    lib = NativeLibrary.getInstance("shell32");
} catch (Error e) {
    Logger.out.error("Could not load Shell32 library.");
    return;
}
Object[] args = { "Vendor.MyJavaApplication" };
String functionName = "SetCurrentProcessExplicitAppUserModelID";
try {
    Function function = lib.getFunction(functionName);
    int ret = function.invokeInt(args);
    if (ret != 0) {
        Logger.out.error(function.getName() + " returned error code "
                + ret + ".");
    }
} catch (UnsatisfiedLinkError e) {
    Logger.out.error(functionName + " was not found in "
            + lib.getFile().getName() + ".");
    // Function not supported
}

Dies scheint keine Wirkung zu haben, aber die Funktion zurück, ohne Fehler. warum Diagnostizieren ist so etwas wie ein Rätsel für mich. Irgendwelche Vorschläge?

Arbeits Umsetzung

Die endgültige Implementierung, die gearbeitet ist die Antwort auf meine Folgefrage darüber, wie die AppID mit JNA zu übergeben.

ich die Prämie zu Gregory Pakosz‘brillanter Antwort für JNI verliehen hatte, die mich auf dem richtigen Weg gesetzt.

Als Referenz ich diese Technik glauben mit eröffnet die Möglichkeit diskutiert jede der APIs verwenden in diesem Artikel in einer Java-Anwendung.

War es hilfreich?

Lösung

Ich habe nicht Windows 7, aber hier ist etwas, das Sie begonnen haben könnte bekommen:

Auf der Java-Seite:

package com.stackoverflow.homework;

public class MyApplication
{
  static native boolean setAppUserModelID();

  static
  {
    System.loadLibrary("MyApplicationJNI");
    setAppUserModelID();
  }
}

Und auf der nativen Seite im Quellcode der `MyApplicationJNI.dll Bibliothek:

JNIEXPORT jboolean JNICALL Java_com_stackoverflow_homework_MyApplication_setAppUserModelID(JNIEnv* env)
{
  LPCWSTR id = L"com.stackoverflow.homework.MyApplication";
  HRESULT hr = SetCurrentProcessExplicitAppUserModelID(id);

  return hr == S_OK;
}

Ihre Frage explizit für eine JNI-Lösung gefragt. Da jedoch Ihre Anwendung benötigt keine andere native Methode, jna wird eine andere Lösung, die sparen Sie vom Schreiben nativen Code, nur um auf den Windows-aPI weiterzuleiten. Wenn Sie sich entscheiden jna zu gehen, achten Sie auf die Tatsache, dass SetCurrentProcessExplicitAppUserModelID() ein UTF-16-String erwartet.

Wenn es in Ihrer Sandbox arbeitet, ist der nächste Schritt des Betriebssystem erkennt in Ihrer Anwendung hinzuzufügen als SetCurrentProcessExplicitAppUserModelID() in Windows offensichtlich nur verfügbar ist, 7:

  • Sie können tun, dass aus der Java-Seite an, dass System.getProperty("os.name"); Überprüfung kehrt "Windows 7".
  • , wenn Sie aus dem kleinen bauen JNI Snippet Ich gab, können Sie es durch dynamischen Laden der shell32.dll Bibliothek verbessern können mit LoadLibrary dann die SetCurrentProcessExplicitAppUserModelID Funktionszeiger mit immer wieder GetProcAddress . Wenn GetProcAddress NULL zurückkehrt, bedeutet das Symbol in shell32 nicht vorhanden ist, daher ist es nicht Windows 7.

EDIT:. JNA Lösung

Referenzen:

Andere Tipps

Es ist eine Java-Bibliothek, die neuen Funktionen von Windows 7 für Java bietet. Es heißt J7Goodies von Strix-Code . indem es Anwendungen werden können, um die Windows-7-Taskleiste richtig festgesteckt. Sie können auch Ihre eigenen Sprunglisten erstellen, etc.

Versuchen Sie JSmooth zu verwenden. Ich benutze immer diese. In JSmooth gibt es eine Option unter Skeleton von Windowed Wrapper genannt

  

Lauch Java-Anwendung in exe-Prozess

Sehen Sie auf diesem Bild.

JSmooth

auch Befehl Zeilenargumente können übergeben werden.
Ich denke, dass dies eine Lösung für Sie sein kann.

Martijn

Ich habe Zugriff auf die SetCurrentProcessExplicitAppUserModelID Methode JNA implementiert und es funktioniert sehr gut, wenn sie als die MSDN-Dokumentation schlägt. Ich habe noch nie die JNA api in der Art und Weise verwendet, die Sie in Ihrem Code-Schnipsel haben. Meine Implementierung folgt die typische JNA Nutzung statt.

Zuerst wird die Shell32 Interface-Definition:

interface Shell32 extends StdCallLibrary {

    int SetCurrentProcessExplicitAppUserModelID( WString appID );

}

Dann JNA mit Shell32 und rufen Sie die Funktion laden:

final Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() {
    {
       put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
       put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
    }
};
Shell32 shell32 = (Shell32) Native.loadLibrary("shell32", Shell32.class,
           WIN32API_OPTIONS);
WString wAppId = new WString( "Vendor.MyJavaApplication" );
shell32.SetCurrentProcessExplicitAppUserModelID( wAppId );

Viele der API im letzten Artikel, den Sie nutzen Windows COM genannt, die ziemlich schwierig ist, direkt mit JNA zu verwenden. Ich habe einige Erfolge Erstellen einer benutzerdefinierten DLL hatte diese API aufrufen (z. B. die SHGetPropertyStoreForWindow mit einer anderen App-ID für ein Submodul Fenster setzen), die ich dann JNA verwenden zur Laufzeit zugreifen zu können.

SetCurrentProcessExplicitAppUserModelID (oder SetAppID ()) würde in der Tat tun, was Sie versuchen zu tun. Allerdings könnte es einfacher sein, Ihre Installation zu modifizieren, um die AppUserModel.ID Eigenschaft auf Ihrer Verknüpfung zu setzen - Zitat aus dem Anwendungsbenutzermodell ID Dokument erwähnt oben:

  

In der System.AppUserModel.ID Eigenschaft der Verknüpfungsdatei der Anwendung. Eine Verknüpfung (als IShellLink, CLSID_ShellLink oder eine LNK-Datei) unterstützt Eigenschaften durch IPropertyStore und anderen Eigentum-Einstellung im gesamt Shell verwendet Mechanismen. Dies ermöglicht die Taskleiste die richtige Verknüpfung zu identifizieren und Pin stellt sicher, dass die Fenster zu dem Prozess gehören, sind in geeigneter Weise mit dem Taskleistenschaltfläche zugeordnet.   Hinweis: Die System.AppUserModel.ID Eigenschaft sollte auf eine Verknüpfung angewandt werden, wenn die Verknüpfung erstellt wird. Wenn das Microsoft Windows Installer (MSI) mit der Anwendung zu installieren, die

Ich reparierte Mine ohne ID-Einstellungen. Es gibt eine Option in launch4j, wenn Sie es verwenden, und Sie sagen, Sie tun dann ...

Sie können den Header JNI Gui ändern und es dann mit der JRE um das Glas wickeln. Die gute Sache ist, dass es .exe im Prozess ausgeführt werden nun statt javaw.exe mit Ihrem Glas auf Laufen. Wahrscheinlich tut es unter der Haube (nicht sicher). Auch ich habe auch bemerkt, dass es sich um 40-50% weniger CPU-Ressourcen nimmt die sogar besser ist!

Und das Pinning funktioniert gut und alle, dass Fensterfunktionen aktiviert sind.

Ich hoffe, es hilft jemand, wie ich fast 2 Tage damit verbracht, dieses Problem mit meinem undecorated javafx App zu lösen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top