跟进 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/