Question

J'utilise Launch4j comme emballage pour mon application Java sous Windows 7, qui, à ma connaissance, dans les fourches d'essence une instance de javaw.exe qui, à son tour interprète le code Java. En conséquence, lorsque l'on tente d'épingler mon application à la barre des tâches, Windows pins au lieu javaw.exe. Sans la ligne de commande nécessaire, mon application alors ne fonctionnera pas.

Résultat de l'épinglage d'une application Launch4j à la barre des tâches

Comme vous pouvez le voir, Windows ne se rend pas compte également que Java est l'application hôte. L'application elle-même est décrit comme « Java (TM) SE binaire »

J'ai essayé de modifier le registre HKEY_CLASSES_ROOT\Applications\javaw.exe clé pour ajouter la valeur IsHostApp. Cela modifie le comportement en désactivant l'épinglage de ma demande tout à fait; de toute évidence pas ce que je veux.

Résultat de la spécification javaw.exe comme une application hôte

Après avoir lu comment Windows interprète les instances d'un unique application (et un phénomène discuté dans cette question ), je me suis intéressé à l'intégration d'un ID de modèle utilisateur application (AppUserModelID) dans mon application Java.

Je crois que je peux résoudre ce problème en passant une AppUserModelID unique de Windows. Il existe une méthode de shell32 pour cela, SetCurrentProcessExplicitAppUserModelID . À la suite de la suggestion Gregory Pakosz, je mis en œuvre dans une tentative de ma demande d'inscription reconnu comme une instance distincte de javaw.exe:

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
}

Cela semble avoir aucun effet, mais la fonction retourne sans erreur. Pourquoi est quelque chose le diagnostic d'un mystère pour moi. Toutes les suggestions?

Mise en oeuvre de travail

La mise en œuvre finale qui a travaillé est la réponse à ma question de suivi sur la façon de passer le AppID en utilisant la JNA.

J'avais reçu la prime à Gregory Pakosz » réponse brillante pour JNI qui m'a mis sur la bonne voie.

Pour référence, je crois à l'aide de cette technique ouvre la possibilité d'utiliser l'une des API discutées dans cet article dans une application Java.

Était-ce utile?

La solution

Je n'ai pas Windows 7, mais voici quelque chose qui pourrait vous aider à démarrer:

Du côté Java:

package com.stackoverflow.homework;

public class MyApplication
{
  static native boolean setAppUserModelID();

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

Et du côté natif, dans le code source de la bibliothèque `MyApplicationJNI.dll:

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;
}

Votre question a demandé explicitement une solution JNI. Toutefois, étant donné que l'application n'a pas besoin d'une autre méthode native, est une autre jna solution qui permettra d'économiser vous d'écrire du code natif juste pour le plaisir de transmettre aux fenêtres api. Si vous décidez d'aller jna, attention au fait que SetCurrentProcessExplicitAppUserModelID() attend une chaîne UTF-16.

Quand il fonctionne dans votre bac à sable, l'étape suivante consiste à ajouter la détection du système d'exploitation dans votre application comme SetCurrentProcessExplicitAppUserModelID() est évidemment disponible que dans Windows 7:

  • vous pouvez le faire à partir du côté Java en vérifiant que System.getProperty("os.name"); retourne "Windows 7".
  • si vous construisez à partir du petit extrait JNI j'ai donné, vous pouvez l'améliorer en chargeant dynamiquement la bibliothèque shell32.dll en utilisant LoadLibrary puis revenir le pointeur de fonction à l'aide SetCurrentProcessExplicitAppUserModelID GetProcAddress . Si GetProcAddress retourne NULL, cela signifie que le symbole est pas présent dans shell32 donc ce n'est pas Windows 7.

EDIT:. Solution JNA

Références:

Autres conseils

Il y a une bibliothèque Java fournissant les nouvelles fonctionnalités de Windows 7 pour Java. Il est appelé par Strix code . Les applications qui l'utilisent peuvent être correctement épinglés à la barre des tâches de Windows 7. Vous pouvez également créer vos propres listes de saut, etc.

Essayez d'utiliser JSmooth . Je l'utilise toujours un. En JSmooth est là une option sous Skeleton par Windowed Wrapper appelé

  

Lauch application java dans le processus de exe

Voir sur cette image.

JSmooth

commande également les arguments de ligne peuvent être transmis.
Je pense que cela peut être une solution pour vous.

Martijn

Je l'ai mis en place l'accès à la méthode SetCurrentProcessExplicitAppUserModelID à l'aide de la JNA et il fonctionne très bien lorsqu'il est utilisé comme la documentation MSDN suggère. Je ne l'ai jamais utilisé la JNA api de la manière que vous avez dans votre extrait de code. Ma mise en œuvre suit le utilisation typique de la JNA à la place.

D'abord la définition d'interface Shell32:

interface Shell32 extends StdCallLibrary {

    int SetCurrentProcessExplicitAppUserModelID( WString appID );

}

Ensuite, en utilisant la JNA pour charger Shell32 et appeler la fonction:

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 );

La plupart des API de dans le dernier article que vous avez mentionné faire usage de COM de Windows qui est assez difficile à utiliser directement avec la JNA. J'ai eu un certain succès la création d'une DLL personnalisée pour appeler son (par exemple. À l'aide du SHGetPropertyStoreForWindow pour définir un autre ID d'application pour une fenêtre de sous-module) ces API que je puis utiliser la JNA pour accéder à l'exécution.

SetCurrentProcessExplicitAppUserModelID (ou SetAppID ()) serait en fait faire ce que vous essayez de faire. Toutefois, il pourrait être plus facile de modifier votre installateur pour définir la propriété AppUserModel.ID sur votre raccourci - citant document de l'application ID modèle utilisateur mentionné ci-dessus:

  

Dans le System.AppUserModel.ID propriété du fichier de raccourci de l'application. Un raccourci (comme IShellLink, CLSID_ShellLink, ou un fichier .lnk) prend en charge les propriétés par le IPropertyStore et d'autres mécanismes de fixation des biens utilisés dans le Shell. Cela permet à la barre des tâches pour identifier le raccourci approprié à la broche et assure que les fenêtres appartenant au processus sont associés à ce appropriée bouton de la barre des tâches.   Remarque: La propriété System.AppUserModel.ID doit être appliqué à un raccourci lorsque ce raccourci est créé. Lorsque vous utilisez le Microsoft Windows Installer (MSI) pour installer l'application, le

Je le mien fixe sans aucun paramètre d'identification. Il y a une option dans Launch4j si vous utilisez et vous dites que vous faites alors ...

Vous pouvez changer l'en-tête de JNI puis envelopper Gui autour du pot avec le JRE. La bonne chose est qu'il .exe exécute dans le processus maintenant, au lieu de courir javaw.exe avec votre pot. Il le fait sans doute sous le capot (pas sûr). De plus, je l'ai remarqué aussi qu'il faut environ 40-50% moins de ressources CPU qui est encore mieux!

Et l'épinglage fonctionne très bien et tout ce que les caractéristiques de la fenêtre sont activées.

J'espère que cela aide à quelqu'un que j'ai passé près de 2 jours à essayer de résoudre ce problème avec mon application undecorated de JavaFX.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top