使用 JNA 获取/设置应用程序标识符
跟进我之前有关 Windows 7 任务栏的问题,我想诊断为什么 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 包装器如何。
这里出了什么问题?
Following up on my previous question concerning the Windows 7 taskbar, I would like to diagnose why Windows isn't acknowledging that my application is independent of javaw.exe
. I presently have the following JNA code to obtain the 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() + ".");
}
}
}
The output of the application is seemingly gibberish:
1: ‹ÿU‹ìƒìL¡¬Ÿv3ʼnEüSV‹uƒ&
2: ‹ÿU‹ìƒìL¡¬Ÿv3ʼnEüSV‹uƒ&
3: ????????????????P???????????
Being aware of the fact that the output may be UTF-16, in (3) I attempted to convert a byte array from UTF-16. In all honesty I don't know if my approach here is right as (a) I don't know the size of a PWSTR
and (b) I don't know if GetCurrentProcessExplicitAppUserModelID
is indeed returning a byte array or string.
I'm aware that JSmooth will run the GUI process in a wrapper which simulates this effect. Launch4j claims to do the same, but doesn't appear to work. I am looking to have the AppUserModelID
set regardless of the Java wrapper.
What is going wrong here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
以下是有关如何通过
JNA
调用SetCurrentProcessExplicitAppUserModelID
的更简单示例:Here's a more simple example on how to call
SetCurrentProcessExplicitAppUserModelID
viaJNA
:我之前没有看到你的问题,否则即使没有赏金我也会尝试一下。
这是我想出的。 请注意,正如代码本身所述,我没有使用
CoTaskMemFree
函数(来自Ole32.dll
)实现正确的内存清理。因此,我建议您仅采用SetCurrentProcessExplicitAppUserModelID()
的实现,它适合您吗?
至少在这里它正确地打印回来:
I didn't see your question before otherwise I would have given a try even without a bounty.
Here is what I came up with. Please note, as stated in the code itself, I didn't implement proper memory clean up with the
CoTaskMemFree
function (fromOle32.dll
). So I suggest you take only the implementation forSetCurrentProcessExplicitAppUserModelID()
Does it work for you?
At least here it correctly prints back:
如果您只需要设置 AppUserModelId 那么上面的 JNA 代码就足够了。但是,如果您想在 Java 应用程序中利用 Windows 7 的新功能,请查看 J7Goodies 的功能,一个提供 Windows 7 任务栏扩展的 Java 库。
编辑:来自 J7Goodies 程序员指南的更多信息
If you just need to set the AppUserModelId then the above JNA code is enough. However if you want to take advantage of the new Windows 7 features in you Java application then check out J7Goodies a Java library providing Windows 7 taskbar extensions.
EDIT: more info from J7Goodies Programmer's Guide