将Java应用程序固定到Windows 7任务栏

Pau*_*sma 35 java java-native-interface taskbar launch4j windows-7

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

将Launch4j应用程序固定到任务栏的结果

如您所见,Windows也没有意识到Java是主机应用程序:应用程序本身被描述为"Java(TM)Platform SE binary".

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

将javaw.exe指定为宿主应用程序的结果

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

我相信我可以通过传递一个独特AppUserModelID的Windows 来解决这个问题.有一种shell32方法,SetCurrentProcessExplicitAppUserModelID.根据Gregory Pakosz的建议,我实现了它,试图将我的应用程序识别为以下单独的实例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
}
Run Code Online (Sandbox Code Playgroud)

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

工作实施

有效的最终实现是关于如何通过使用JNA的后续问题的答案AppID.

我把这笔赏金给了格雷戈里·帕科斯(Gregory Pakosz)对JNI的精彩回答,让我走上正轨.

作为参考,我相信使用这种技术可以在Java应用程序中使用本文中讨论的任何API .

Gre*_*osz 21

我没有Windows 7,但这里可能会让你开始:

在Java方面:

package com.stackoverflow.homework;

public class MyApplication
{
  static native boolean setAppUserModelID();

  static
  {
    System.loadLibrary("MyApplicationJNI");
    setAppUserModelID();
  }
}
Run Code Online (Sandbox Code Playgroud)

在本机方面,在`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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 您可以通过检查System.getProperty("os.name");返回来从Java端执行此操作"Windows 7".
  • 如果你从我给的小JNI片段构建,你可以通过动态加载shell32.dllLoadLibrary然后使用返回SetCurrentProcessExplicitAppUserModelID函数指针来增强它GetProcAddress.如果GetProcAddress返回NULL,则表示该符号不存在,shell32因此它不是Windows 7.

编辑:JNA解决方案.

参考文献:


小智 5

有一个Java库为Java提供了新的Windows 7功能.它被Strix Code称为J7Goodies.使用它的应用程序可以正确固定到Windows 7任务栏.您还可以创建自己的跳转列表等.