将Java应用程序固定到Windows 7任务栏 [英] Pinning a Java application to the Windows 7 taskbar

查看:183
本文介绍了将Java应用程序固定到Windows 7任务栏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Windows 7下使用Launch4j作为我的Java应用程序的包装器,根据我的理解,实质上是分析了一个 javaw.exe 的实例,它反过来解释了Java代码。因此,在尝试将我的应用程序固定到任务栏时,Windows会将 javaw.exe 固定。如果没有所需的命令行,我的应用程序将无法运行。

I use Launch4j as a wrapper for my Java application under Windows 7, which, to my understanding, in essence forks an instance of javaw.exe that in turn interprets the Java code. As a result, when attempting to pin my application to the task bar, Windows instead pins javaw.exe. Without the required command line, my application will then not run.

正如您所看到的,Windows也没有意识到Java是主机应用程序:应用程序本身被描述作为Java(TM)平台SE二进制文件。

As you can see, Windows also does not realize that Java is the host application: the application itself is described as "Java(TM) Platform SE binary".

我已经尝试更改注册表项 HKEY_CLASSES_ROOT\Applications\javaw.exe 添加值 IsHostApp 。这通过完全禁用我的应用程序的固定来改变行为;显然不是我想要的。

I have tried altering the registry key HKEY_CLASSES_ROOT\Applications\javaw.exe to add the value IsHostApp. This alters the behavior by disabling pinning of my application altogether; clearly not what I want.

阅读 Windows如何解释单个应用程序的实例(以及这个问题中讨论的一种现象),我开始对将应用程序用户模型ID(AppUserModelID)嵌入到我的Java应用程序中感兴趣。

After reading about how Windows interprets instances of a single application (and a phenomenon discussed in this question), I became interested in embedding a Application User Model ID (AppUserModelID) into my Java application.

我相信我可以通过将唯一的 AppUserModelID 传递给Windows来解决这个问题。有一个 shell32 方法, SetCurrentProcessExplicitAppUserModelID 。根据Gregory Pakosz的建议,我实现了它,试图将我的应用程序识别为 javaw.exe的单独实例

I believe that I can resolve this by passing a unique AppUserModelID to Windows. There is a shell32 method for this, SetCurrentProcessExplicitAppUserModelID. Following Gregory Pakosz suggestion, I implemented it in an attempt to have my application recognized as a separate instance of 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
}

这似乎没有效果,但函数返回没有错误。诊断为什么对我来说是一个谜。有什么建议吗?

This appears to have no effect, but the function returns without error. Diagnosing why is something of a mystery to me. Any suggestions?

最终的实现是我的后续问题的答案,关于如何传递 AppID 使用JNA。

The final implementation that worked is the answer to my follow-up question concerning how to pass the AppID using JNA.

我已经将此奖励给了Gregory Pakosz对JNI的精彩回答,让我走上正轨。

I had awarded the bounty to Gregory Pakosz' brilliant answer for JNI that set me on the right track.

作为参考,我相信使用这种技术可以使用任何讨论的API

For reference, I believe using this technique opens the possibility of using any of the APIs discussed in this article in a Java application.

推荐答案

我没有Windows 7但是这里可以帮助你入门:

I don't have Windows 7 but here is something that might get you started:

在Java方面:

package com.stackoverflow.homework;

public class MyApplication
{
  static native boolean setAppUserModelID();

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

在原生方面,在源代码中`MyApplicationJNI.dll库:

And on the native side, in the source code of the `MyApplicationJNI.dll library:

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

您的问题明确要求提供JNI解决方案。但是,由于您的应用程序不需要任何其他本机方法, jna 是另一种可以节省的解决方案你只是为了转发到windows api而编写本机代码。如果你决定去jna,请注意 SetCurrentProcessExplicitAppUserModelID()期待一个UTF-16字符串的事实。

Your question explicitly asked for a JNI solution. However, since your application doesn't need any other native method, jna is another solution which will save you from writing native code just for the sake of forwarding to the windows api. If you decide to go jna, pay attention to the fact that SetCurrentProcessExplicitAppUserModelID() is expecting a UTF-16 string.

当它在沙盒中工作时,下一步是在应用程序中添加操作系统检测,因为 SetCurrentProcessExplicitAppUserModelID()显然仅在Windows 7中可用:

When it works in your sandbox, the next step is to add operating system detection in your application as SetCurrentProcessExplicitAppUserModelID() is obviously only available in Windows 7:

  • you may do that from the Java side by checking that System.getProperty("os.name"); returns "Windows 7".
  • if you build from the little JNI snippet I gave, you can enhance it by dynamically loading the shell32.dll library using LoadLibrary then getting back the SetCurrentProcessExplicitAppUserModelID function pointer using GetProcAddress. If GetProcAddress returns NULL, it means the symbol is not present in shell32 hence it's not Windows 7.

编辑: JNA解决方案

参考文献:

  • The JNI book for more JNI examples
  • Java Native Access (JNA)

这篇关于将Java应用程序固定到Windows 7任务栏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆