Pregunta

Yo uso Launch4j como envoltura para mi aplicación Java en Windows 7, que, a mi entender, en esencia horquillas una instancia de javaw.exe que a su vez interpreta el código Java. Como resultado, cuando se trata de fijar mi solicitud a la barra de tareas, en lugar de Windows pines javaw.exe. Sin la línea de comandos es necesario, mi solicitud será entonces no se ejecutan.

Resultado de fijar una aplicación Launch4j a la barra de tareas

Como se puede ver, Windows también no se da cuenta de que Java es la aplicación host:. La propia aplicación se describe como "Java (TM) SE binaria"

He intentado alterar el HKEY_CLASSES_ROOT\Applications\javaw.exe clave de registro para añadir el valor IsHostApp. Esto altera el comportamiento mediante la desactivación de la fijación de mi solicitud por completo; claramente no es lo que quiero.

resultado de especificar javaw.exe como una aplicación host

Después de leer sobre cómo Windows interpreta instancias de una sola aplicación (y un fenómeno discutido en esta pregunta ), me interesé en la incorporación de un identificador de solicitud de modelo de usuario (AppUserModelID) en mi aplicación Java.

Creo que puedo resolver esto pasando un AppUserModelID único para Windows. Hay un método shell32 para esto, SetCurrentProcessExplicitAppUserModelID . Después de Gregory Pakosz sugerencia, he implementado en un intento para que mi aplicación reconocida como una instancia independiente 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
}

Esto parece tener ningún efecto, pero la función devuelve sin error. El diagnóstico de por qué es un misterio para mí. ¿Alguna sugerencia?

implementación funcional

La aplicación final que trabajó es la respuesta a mi pregunta de seguimiento relación con la forma de pasar el AppID usando JNA.

Me había adjudicado a la generosidad brillante respuesta Gregory Pakosz' para la JNI que me puso en el camino correcto.

A modo de referencia, creo que el uso de esta técnica abre la posibilidad de utilizar cualquiera de las API discutidos en este artículo en una aplicación Java.

¿Fue útil?

Solución

No tengo Windows 7, pero aquí es algo que podría empezar:

En el lado de Java:

package com.stackoverflow.homework;

public class MyApplication
{
  static native boolean setAppUserModelID();

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

Y en el lado nativo, en el código fuente de la biblioteca `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;
}

Su pregunta pidió explícitamente una solución JNI. Sin embargo, dado que su aplicación no necesita ningún otro método nativo, JNA es otra solución que permitirá ahorrar que desde escribir código nativo por el simple hecho de remitir a la API de windows. Si usted decide ir JNA, prestar atención al hecho de que SetCurrentProcessExplicitAppUserModelID() espera una cadena UTF-16.

Cuando se trabaja en su caja de arena, el siguiente paso es añadir la detección de sistema operativo en su aplicación como SetCurrentProcessExplicitAppUserModelID() es, obviamente, sólo está disponible en Windows 7:

  • Puede hacerlo desde el lado de Java mediante la comprobación de que System.getProperty("os.name"); devuelve "Windows 7".
  • si se construye desde el pequeño fragmento de código JNI di, puede mejorarlo mediante la carga dinámicamente la biblioteca shell32.dll usando LoadLibrary luego volver al puntero de función SetCurrentProcessExplicitAppUserModelID usando GetProcAddress . Si GetProcAddress vuelve NULL, significa que el símbolo no está presente en shell32 por lo tanto, no es de Windows 7.

EDIT:. Solución JNA

Referencias:

Otros consejos

Hay una biblioteca de Java que proporciona las nuevas características de Windows 7 para Java. Se llama Código Strix . Las aplicaciones que utilizan que se pueden fijar correctamente a la barra de tareas de Windows 7. También puede crear sus propias listas de salto, etc.

Trate de usar JSmooth . Yo siempre uso de éste. En JSmooth hay una opción en Skeleton por Windowed Wrapper llamado

  

aplicación java Lauch en proceso exe

Ver sobre esta imagen.

JSmooth

También comando argumentos de línea se pueden pasar.
Creo que esto puede ser una solución para usted.

Martijn

He implementado el acceso al método SetCurrentProcessExplicitAppUserModelID usando JNA y funciona bastante bien cuando se utiliza según la documentación de MSDN sugiere. Nunca he utilizado la API JNA en la forma que tiene en su fragmento de código. Mi aplicación sigue la uso JNA típica lugar.

En primer lugar la definición de interfaz Shell32:

interface Shell32 extends StdCallLibrary {

    int SetCurrentProcessExplicitAppUserModelID( WString appID );

}

Luego, utilizando JNA para cargar Shell32 y llamar a la función:

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

Muchas de las API en el último artículo que usted ha mencionado hacer uso de COM de Windows que es bastante difícil de usar directamente con JNA. He tenido cierto éxito la creación de un archivo DLL personalizado para llamar a éstos del API (por ejemplo. Mediante el SHGetPropertyStoreForWindow para establecer un ID de aplicación diferente para una ventana submódulo) que luego utilizo JNA para acceder en tiempo de ejecución.

SetCurrentProcessExplicitAppUserModelID (o SetAppID ()) sería, de hecho, hacer lo que estamos tratando de hacer. Sin embargo, podría ser más fácil de modificar su instalador para establecer la propiedad AppUserModel.ID en su acceso directo - citando el documento usuario de la aplicación Modelo ID mencionado anteriormente:

  

En el System.AppUserModel.ID propiedad del archivo de acceso directo de la aplicación. Un acceso directo (como IShellLink, CLSID_ShellLink, o un archivo .lnk) soporta propiedades a través IPropertyStore y otros mecanismos de propiedad de fijación utilizados en el Shell. Esto permite que la barra de tareas para identificar el acceso directo a la clavija adecuada y asegura que las ventanas que pertenecen al proceso están asociados apropiadamente con ese botón de la barra de tareas.   Nota: La propiedad System.AppUserModel.ID se debe aplicar a un acceso directo cuando se crea ese acceso directo. Cuando se utiliza el Microsoft Windows Installer (MSI) para instalar la aplicación, la mesa de MsiShortcutProperty permite al AppUserModelID que se aplicará al acceso directo cuando se crea durante la instalación.

La última biblioteca jna-platform ahora incluye fijaciones JNA para SetCurrentProcessExplicitAppUserModelID:

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

Me fijo mina sin ningún ajuste de ID. Hay una opción en Launch4J si lo está utilizando y que diga lo hace entonces ...

Puede cambiar la cabecera para JNI Gui y luego se envuelve alrededor de la jarra con el JRE. Lo bueno es que se ejecuta .exe en el proceso ahora en lugar de correr javaw.exe junto con su contenedor. Probablemente lo hace bajo el capó (no estoy seguro). También me he dado cuenta de que también se tarda alrededor de un 40-50% menos de recursos de CPU que es aún mejor!

Y la colocación de clavos funciona bien y todos los que las características de las ventanas están habilitadas.

espero que ayude a alguien como yo pasé casi 2 días tratando de resolver ese problema con mi aplicación javafx sin decorar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top