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

标签 java windows-7 java-native-interface launch4j taskbar

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

Result of pinning a Launch4j application to the taskbar

如您所见,Windows 也没有意识到 Java 是宿主应用程序:应用程序本身被描述为“Java(TM) Platform SE 二进制文件”。

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

Result of specifying javaw.exe as a host application

在阅读了 how Windows interprets instances of a single application 之后(和 a phenomenon discussed in this question ),我开始有兴趣将应用程序用户模型 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
}

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

工作实现

最终的实现是the answer to my follow-up question关于如何使用 JNA 传递 AppID

我已将赏金授予 Gregory Pakosz 对 JNI 的出色回答,这让我走上了正轨。

作为引用,我相信使用这种技术可以使用所讨论的任何 API in this article在 Java 应用程序中。

最佳答案

我没有 Windows 7,但这里有一些可以帮助您入门的东西:

在 Java 方面:

package com.stackoverflow.homework;

public class MyApplication
{
  static native boolean setAppUserModelID();

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

而在 native 端,在`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;
}

您的问题明确要求 JNI 解决方案。但是,由于您的应用程序不需要任何其他 native 方法,jna是另一种解决方案,它可以让您不必为了转发到 windows api 而编写 native 代码。如果您决定使用 jna,请注意 SetCurrentProcessExplicitAppUserModelID() 需要一个 UTF-16 字符串。

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

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

编辑:JNA Solution .

引用资料:

关于java - 将 Java 应用程序固定到 Windows 7 任务栏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1834599/

相关文章:

java - 如何在JNI代码中包含cspi/spi.h头文件?

java - 用户 '' @'localhost' 的访问被拒绝(使用密码 : NO) in Eclipse, 而不是 'root' @'localhost' ,类路径已损坏

c++ - 从 SoundTouch 音频库转换 short[] 以进行播放

java - 将 WebRTC 与 XMPP 服务器集成

windows-7 - 在 WM_COPYDATA 命令中获取 64 位数据而不是预期的 32 位 DWORD

windows-7 - SWT Table.setLinesVisible(false) 似乎不适用于 Windows 7

命名管道的 WCF 安全问题

java - Win32 文件属性对话框未通过 JNI 在 Java Swing 应用程序中显示

java - 有没有办法告诉 servlet 容器一次生成一个资源实例?

java - TIntProcedure 无法解析