java - 使用 JNA 获取/设置应用程序标识符

标签 java windows-7 jna utf-16

跟进 my previous question concerning the Windows 7 taskbar ,我想诊断一下为什么 Windows 不承认我的应用程序独立于 javaw.exe。我目前有以下 JNA 代码来获取 AppUserModelID :

public class AppIdTest {

    public static void main(String[] args) {
        NativeLibrary lib;
        try {
            lib = NativeLibrary.getInstance("shell32");
        } catch (Error e) {
            System.err.println("Could not load Shell32 library.");
            return;
        }
        Object[] functionArgs = new Object[1];
        String functionName = null;
        Function function;
        try {
            functionArgs[0] = new String("Vendor.MyJavaApplication")
                    .getBytes("UTF-16");
            functionName = "GetCurrentProcessExplicitAppUserModelID";
            function = lib.getFunction(functionName);
            // Output the current AppId
            System.out.println("1: " + function.getString(0));
            functionName = "SetCurrentProcessExplicitAppUserModelID";
            function = lib.getFunction(functionName);
            // Set the new AppId
            int ret = function.invokeInt(functionArgs);
            if (ret != 0) {
                Logger.out.error(function.getName() + " returned error code "
                        + ret + ".");
            }
            functionName = "GetCurrentProcessExplicitAppUserModelID";
            function = lib.getFunction(functionName);
            // Output the current AppId
            System.out.println("2: " + function.getString(0));
            // Output the current AppID, converted from UTF-16
            System.out.println("3: "
                    + new String(function.getByteArray(0, 255), "UTF-16"));
        } catch (UnsupportedEncodingException e) {
            System.err.println("System does not support UTF-16 encoding.");
        } catch (UnsatisfiedLinkError e) {
            System.err.println(functionName + " was not found in "
                    + lib.getFile().getName() + ".");
        }
    }
}

应用程序的输出看似乱码:

1: ‹ÿU‹ìƒìL¡¬Ÿv3ʼnEüSV‹uƒ&
2: ‹ÿU‹ìƒìL¡¬Ÿv3ʼnEüSV‹uƒ&
3: ????????????????P???????????

意识到输出可能是 UTF-16,在 (3) 中我尝试从 UTF-16 转换字节数组。老实说,我不知道我的方法是否正确,因为 (a) 我不知道 PWSTR 的大小和 (b) 我不知道 GetCurrentProcessExplicitAppUserModelID确实是返回一个字节数组或字符串。

我知道 JSmooth 将在模拟这种效果的包装器中运行 GUI 进程。 Launch4j 声称可以这样做,但似乎不起作用。我希望 AppUserModelID 设置 无论 Java 包装器如何

这里出了什么问题?

最佳答案

我之前没有看到你的问题,否则即使没有赏金我也会尝试一下。

这是我想出的。 请注意,正如代码本身所述,我没有使用 CoTaskMemFree 函数(来自 Ole32.dll)实现正确的内存清理。所以我建议你只采用 SetCurrentProcessExplicitAppUserModelID()

的实现
package com.stackoverflow.AppIdTest;

import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.ptr.PointerByReference;

public class AppIdTest
{

  public static void main(String[] args) throws Exception
  {
    setCurrentProcessExplicitAppUserModelID(AppIdTest.class.getName());

    System.out.println(getCurrentProcessExplicitAppUserModelID());
  }

  // DO NOT DO THIS, IT'S JUST FOR TESTING PURPOSE AS I'M NOT FREEING THE MEMORY
  // AS REQUESTED BY THE DOCUMENTATION:
  //
  // http://msdn.microsoft.com/en-us/library/dd378419%28VS.85%29.aspx
  //
  // "The caller is responsible for freeing this string with CoTaskMemFree when
  // it is no longer needed"
  public static String getCurrentProcessExplicitAppUserModelID()
  {
    final PointerByReference r = new PointerByReference();

    if (GetCurrentProcessExplicitAppUserModelID(r).longValue() == 0)
    {
      final Pointer p = r.getValue();


      return p.getString(0, true); // here we leak native memory by lazyness
    }      
    return "N/A";
  }

  public static void setCurrentProcessExplicitAppUserModelID(final String appID)
  {
    if (SetCurrentProcessExplicitAppUserModelID(new WString(appID)).longValue() != 0)
      throw new RuntimeException("unable to set current process explicit AppUserModelID to: " + appID);
  }

  private static native NativeLong GetCurrentProcessExplicitAppUserModelID(PointerByReference appID);
  private static native NativeLong SetCurrentProcessExplicitAppUserModelID(WString appID);


  static
  {
    Native.register("shell32");
  }
}

它对你有用吗?

至少在这里它正确打印回来:

com.stackoverflow.AppIdTest.AppIdTest

关于java - 使用 JNA 获取/设置应用程序标识符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1907735/

相关文章:

java - JNA 标记联合映射

Java - 使用 JNA 的 Windows 任务栏 - 如何将窗口图标 (HICON) 转换为 Java 图像?

java - 注释方法的任何工具,以便该方法不产生日志

Java数组-(并行数组)

java - 如何在 OS X 中检查管理员权限?

c++ - LNK2019:函数 ___tmainCRTStartup 中引用的未解析外部符号 _main

Java JNA 根据操作系统不同的实现

java - ACR122U - 传输 APDU 时出现 InvalidDeviceStateException

delphi - 开发 Delphi Windows 7 应用程序的规则

c# - 在 Windows 7 上获取有用的错误消息