Pergunta

Eu uso Launch4j como um wrapper para a minha aplicação Java no Windows 7, que, no meu entender, em essência bifurca uma instância de javaw.exe que no interpreta sua vez, o código Java. Como resultado, quando se tenta fixar a minha aplicação na barra de tarefas, o Windows em vez pinos javaw.exe. Sem a linha de comando necessário, o meu pedido, então não será executado.

Resultado da fixando uma aplicação Launch4j à barra de tarefas

Como você pode ver, o Windows também não percebe que Java é a aplicação host: a aplicação em si é descrito como "Java (TM) Platform SE binário"

.

Eu tentei alterar o HKEY_CLASSES_ROOT\Applications\javaw.exe chave de registo para adicionar o valor IsHostApp. Isso altera o comportamento, desativando fixando da minha candidatura por completo; claramente não o que eu quero.

Resultado de especificar javaw.exe como um aplicativo host

Depois de ler sobre como as instâncias de um Windows interpreta única aplicação (e um fenómeno discutido nesta questão ), fiquei interessado na incorporação de um usuário aplicação Modelo ID (AppUserModelID) em minha aplicação Java.

Eu acredito que eu posso resolver isso passando um AppUserModelID exclusivo para o Windows. Existe um método shell32 para isso, SetCurrentProcessExplicitAppUserModelID . Seguindo a sugestão Gregory Pakosz, eu implementou em uma tentativa de ter o meu pedido reconhecida como uma instância separada do 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
}

Este parece não ter efeito, mas a função retorna sem erro. Diagnosticar porque é algo de um mistério para mim. Alguma sugestão?

implementação de Trabalho

A implementação final que trabalhou é a resposta à minha pergunta de follow-up sobre como passar o AppID usando JNA.

Eu tinha concedido a graça a brilhante resposta Gregory Pakosz' para JNI que me colocou no caminho certo.

Para referência, eu acredito que usando esta técnica abre a possibilidade de utilizar qualquer uma das APIs discutido neste artigo em uma aplicação Java.

Foi útil?

Solução

Eu não tenho o Windows 7, mas aqui é algo que pode você começar:

No lado do Java:

package com.stackoverflow.homework;

public class MyApplication
{
  static native boolean setAppUserModelID();

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

E do lado nativo, no código fonte do `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;
}

Sua pergunta feita explicitamente por uma solução JNI. No entanto, uma vez que a sua aplicação não precisa de qualquer outro método nativo, jna é outra solução que irá poupar -lo de escrever código nativo apenas por uma questão de encaminhamento para a API do Windows. Se você decidir ir jna, prestar atenção ao fato de que SetCurrentProcessExplicitAppUserModelID() está esperando uma string UTF-16.

Quando se trabalha em sua área local, o próximo passo é adicionar a detecção de sistema operacional em seu aplicativo como SetCurrentProcessExplicitAppUserModelID() é, obviamente, disponível apenas no Windows 7:

  • Você pode fazer isso do lado de Java, verificando que System.getProperty("os.name"); retornos "Windows 7".
  • Se você construir a partir do pouco JNI trecho que eu dei, você pode melhorá-lo por carregar dinamicamente a biblioteca shell32.dll usando LoadLibrary depois voltar o ponteiro de função SetCurrentProcessExplicitAppUserModelID usando GetProcAddress . Se GetProcAddress retornos NULL, isso significa que o símbolo não está presente em shell32 não, portanto, é o Windows 7.

EDIT: JNA Solution

Referências:

Outras dicas

Há uma biblioteca Java fornecer os novos recursos do Windows 7 para Java. É chamado por Código Strix . Aplicações usando ele pode ser devidamente fixado à barra de tarefas do Windows 7. Você também pode criar suas próprias listas de salto, etc.

Tente usar JSmooth . Eu uso sempre um presente. Em JSmooth existe uma opção em Skeleton por Windowed Wrapper chamado

Lauch java aplicativo em processo de exe

Veja na imagem.

JSmooth

Além disso argumentos de linha de comando podem ser passados.
Acho que isso pode ser uma solução para você.

Martijn

Eu tenho implementado acesso ao método SetCurrentProcessExplicitAppUserModelID usando JNA e ele funciona muito bem quando usado como a documentação MSDN sugere. Eu nunca usei a API JNA na maneira que você tem em seu trecho de código. Minha implementação segue a típico JNA uso .

Primeiro, a definição de interface Shell32:

interface Shell32 extends StdCallLibrary {

    int SetCurrentProcessExplicitAppUserModelID( WString appID );

}

Em seguida, usando JNA para carregar Shell32 e chamar a função:

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

Muitos dos da API no último artigo que você mencionou fazer uso do Windows COM que é bastante difícil de usar diretamente com ANJ. Eu tive algum sucesso criando uma DLL personalizada para chamar estes de API (ex. Utilizando o SHGetPropertyStoreForWindow para definir um ID de aplicativo diferente para uma janela submodule) que eu, em seguida, usar JNA para acesso em tempo de execução.

SetCurrentProcessExplicitAppUserModelID (ou SetAppID ()) seria, de facto, fazer o que você está tentando fazer. No entanto, pode ser mais fácil de modificar o seu instalador para definir a propriedade AppUserModel.ID em seu atalho - citando o Aplicativo de Usuário Modelo ID documento mencionado acima:

Na System.AppUserModel.ID propriedade de arquivo de atalho do aplicativo. Um atalho (como um IShellLink, CLSID_ShellLink, ou um arquivo .lnk) oferece suporte a propriedades através IPropertyStore e outros mecanismos de fixação dos imóveis usados ??em todo o Shell. Isto permite que a barra de ferramentas para identificar o atalho adequada para o pino e garante que o Windows pertencentes ao processo são apropriadamente associados com esse botão barra de tarefas. Nota: A propriedade System.AppUserModel.ID deve ser aplicada a um atalho quando esse atalho é criado. Ao usar o Microsoft Windows Installer (MSI) para instalar o aplicativo, o MsiShortcutProperty tabela permite o AppUserModelID a ser aplicado o atalho quando é criado durante a instalação.

O mais recente biblioteca jna-platform agora inclui ligações JNA para SetCurrentProcessExplicitAppUserModelID:

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

Eu fixo mina sem quaisquer definições de identificação. Existe uma opção no Launch4J se você estiver usando-lo e você dizer que sim, então ...

Você pode alterar o cabeçalho para JNI Gui e, em seguida, envolvê-la em torno do frasco com o JRE. A coisa boa é que ele roda .exe no processo agora, em vez de correr javaw.exe com o seu jar. Provavelmente não é sob o capô (não tenho certeza). Também tenho notado também que leva em torno de 40-50% menos recursos de CPU que é ainda melhor!

E a pinagem funciona bem e tudo o que características de janela são habilitado.

Espero que ajude a alguém como eu passei quase 2 dias tentando resolver esse problema com meu aplicativo JavaFX undecorated.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top