Domanda

Io uso Launch4J come wrapper per la mia applicazione Java sotto Windows 7, che, alla mia comprensione, in forche essenza un'istanza di javaw.exe che a sua volta interpreta il codice Java. Di conseguenza, quando si tenta di appuntare la mia domanda alla barra delle applicazioni, Windows appunta invece javaw.exe. Senza la linea di comando necessaria, la mia domanda, allora, non eseguito.

Risultato di pinning un'applicazione Launch4J alla barra delle applicazioni

Come si può vedere, Windows anche non si rende conto che Java è l'applicazione host:. L'applicazione stessa è descritto come "Java (TM) Platform SE binario"

Ho provato alterare il HKEY_CLASSES_ROOT\Applications\javaw.exe chiave di registro per aggiungere il valore di IsHostApp. Questo altera il comportamento disabilitando pinning della mia applicazione del tutto; chiaramente non quello che voglio.

Risultato di specificare javaw.exe come applicazione host

Dopo aver letto su modo in cui Windows interpreta le istanze di un singola applicazione (e un fenomeno discusso in questa domanda ), mi sono interessato ad inserire un ID applicazione del modello utente (AppUserModelID) nella mia applicazione Java.

Credo che posso risolvere questo passando un AppUserModelID unico a Windows. C'è un metodo shell32 per questo, SetCurrentProcessExplicitAppUserModelID . A seguito di Gregory Pakosz suggerimento, ho implementato in un tentativo di avere la mia applicazione riconosciuto come un'istanza separata di 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
}

Questo sembra non avere alcun effetto, ma la funzione restituisce senza errori. Diagnosi perché è qualcosa di un mistero per me. Qualche suggerimento?

implementazione funzionante

La realizzazione finale che ha funzionato è la risposta alla mia domanda di follow-up riguardo a come passare il AppID utilizzando JNA.

avevo assegnato il premio alla risposta brillante Gregory Pakosz' per JNI che mi mise sulla strada giusta.

Per riferimento, Credo che usando questa tecnica apre la possibilità di utilizzare le API discussi in questo articolo in un'applicazione Java.

È stato utile?

Soluzione

Non ho Windows 7 ma qui è qualcosa che potrebbe iniziare:

Sul lato Java:

package com.stackoverflow.homework;

public class MyApplication
{
  static native boolean setAppUserModelID();

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

E sul lato nativo, nel codice sorgente della libreria `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;
}

La tua domanda esplicitamente chiesto una soluzione JNI. Tuttavia, dal momento che l'applicazione non ha bisogno di alcun altro metodo nativo, JNA è un'altra soluzione che farà risparmiare si da scrivere codice nativo solo per il gusto di inoltro al API di Windows. Se si decide di andare JNA, prestare attenzione al fatto che SetCurrentProcessExplicitAppUserModelID() si aspetta una stringa UTF-16.

Quando funziona nel vostro sandbox, il passo successivo è quello di aggiungere il rilevamento del sistema operativo nella vostra applicazione, come SetCurrentProcessExplicitAppUserModelID() è ovviamente disponibile solo in Windows 7:

  • è possibile farlo dal lato Java controllando che System.getProperty("os.name"); restituisce "Windows 7".
  • se si crea dal piccolo frammento JNI ho dato, è possibile migliorare lo caricando dinamicamente la libreria shell32.dll utilizzando LoadLibrary poi tornare il puntatore a funzione SetCurrentProcessExplicitAppUserModelID utilizzando GetProcAddress . Se GetProcAddress ritorna NULL, significa che il simbolo non è presente in shell32 non Quindi è Windows 7.

EDIT:. JNA Soluzione

References:

Altri suggerimenti

C'è una libreria Java che fornisce le nuove funzionalità di Windows 7 per Java. Si chiama di Codice Strix . Le applicazioni che utilizzano può essere adeguatamente riposte a Windows 7 barra delle applicazioni. È inoltre possibile creare i propri elenchi di salto, ecc.

Prova ad utilizzare JSmooth . Io uso sempre questo. In JSmooth c'è un'opzione in Skeleton da Windowed Wrapper chiamato

  

Lauch java applicazione nel processo exe

Vedere su questa immagine.

JSmooth

Anche argomenti della riga di comando possono essere passati.
Penso che questo può essere una soluzione per voi.

Martijn

Ho implementato l'accesso al metodo SetCurrentProcessExplicitAppUserModelID utilizzando JNA e funziona abbastanza bene quando viene utilizzato come suggerisce la documentazione MSDN. Non ho mai usato l'API JNA nel modo che avete nel vostro frammento di codice. La mia applicazione segue la tipico utilizzo JNA .

In primo luogo la definizione di interfaccia Shell32:

interface Shell32 extends StdCallLibrary {

    int SetCurrentProcessExplicitAppUserModelID( WString appID );

}

Quindi, utilizzando JNA per caricare Shell32 e chiamare la funzione:

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

Molte delle API nell'ultimo articolo lei ha citato fare uso di COM di Windows che è abbastanza difficile da usare direttamente con JNA. Ho avuto un certo successo la creazione di una DLL personalizzata per chiamare questi API (ad es. Utilizzando lo SHGetPropertyStoreForWindow per impostare un diverso ID app per una finestra di modulo), che Ho quindi utilizzare JNA per accedere in fase di esecuzione.

SetCurrentProcessExplicitAppUserModelID (o SetAppID ()) sarebbe in effetti fare quello che stai cercando di fare. Tuttavia, potrebbe essere più facile da modificare all'installatore di impostare la proprietà AppUserModel.ID sul collegamento - citando il Applicazione utente ID Modello documento di cui sopra:

  

System.AppUserModel.ID proprietà del file di collegamento dell'applicazione. Una scorciatoia (come IShellLink, CLSID_ShellLink, o un file .lnk) supporta le proprietà attraverso IPropertyStore e altri meccanismi di proprietà di impostazione utilizzati in tutta la Shell. Questo permette la barra per identificare il collegamento corretto al pin e assicura che le finestre appartenenti al processo sono opportunamente associati a tale pulsante di barra.   Nota: La proprietà System.AppUserModel.ID dovrebbe essere applicata a una scorciatoia quando si crea quel collegamento. Quando si utilizza il Microsoft Windows Installer (MSI) per installare l'applicazione, il tavolo MsiShortcutProperty permette al AppUserModelID da applicare al collegamento quando viene creato durante l'installazione.

L'ultima libreria jna-platform ora include attacchi JNA per SetCurrentProcessExplicitAppUserModelID:

https://github.com/java-native-access/jna/ tirare / 680

ho fissato il mio, senza alcuna impostazione ID. C'è un'opzione in Launch4J se lo si utilizza e tu dici che fai allora ...

È possibile modificare l'intestazione di JNI Gui e poi avvolgerla intorno il vaso con la JRE. La cosa buona è che funziona exe nel processo ora invece a correre javaw.exe con il vostro vaso. Probabilmente lo fa sotto il cofano (non sono sicuro). Inoltre ho notato anche che ci vuole circa il 40-50% in meno di risorse della CPU che è ancora meglio!

E il pinning funziona bene e tutto ciò che le caratteristiche delle finestre sono abilitati.

Spero che aiuta a qualcuno come ho trascorso quasi 2 giorni a cercare di risolvere il problema con il mio non decorato JavaFX app.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top