问题描述
我在Windows 7下使用Launch4j作为我的Java应用程序的包装器,根据我的理解,实质上是分析了一个 javaw.exe
的实例,它反过来解释了Java代码。因此,在尝试将我的应用程序固定到任务栏时,Windows会将 javaw.exe
固定。如果没有所需的命令行,我的应用程序将无法运行。
I use Launch4j as a wrapper for my Java application under Windows 7, which, to my understanding, in essence forks an instance of javaw.exe
that in turn interprets the Java code. As a result, when attempting to pin my application to the task bar, Windows instead pins javaw.exe
. Without the required command line, my application will then not run.
正如您所看到的,Windows也没有意识到Java是主机应用程序:应用程序本身被描述作为Java(TM)平台SE二进制文件。
As you can see, Windows also does not realize that Java is the host application: the application itself is described as "Java(TM) Platform SE binary".
我已经尝试更改注册表项 HKEY_CLASSES_ROOT\Applications\javaw.exe
添加值 IsHostApp
。这通过完全禁用我的应用程序的固定来改变行为;显然不是我想要的。
I have tried altering the registry key HKEY_CLASSES_ROOT\Applications\javaw.exe
to add the value IsHostApp
. This alters the behavior by disabling pinning of my application altogether; clearly not what I want.
阅读(以及),我开始对将应用程序用户模型ID(AppUserModelID)嵌入到我的Java应用程序中感兴趣。
After reading about how Windows interprets instances of a single application (and a phenomenon discussed in this question), I became interested in embedding a Application User Model ID (AppUserModelID) into my Java application.
我相信我可以通过将唯一的 AppUserModelID
传递给Windows来解决这个问题。有一个 shell32
方法,。根据Gregory Pakosz的建议,我实现了它,试图将我的应用程序识别为 javaw.exe的单独实例
:
I believe that I can resolve this by passing a unique AppUserModelID
to Windows. There is a shell32
method for this, SetCurrentProcessExplicitAppUserModelID
. Following Gregory Pakosz suggestion, I implemented it in an attempt to have my application recognized as a separate instance of 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
}
这似乎没有效果,但函数返回没有错误。诊断为什么对我来说是一个谜。有什么建议吗?
This appears to have no effect, but the function returns without error. Diagnosing why is something of a mystery to me. Any suggestions?
最终的实现是,关于如何传递 AppID
使用JNA。
The final implementation that worked is the answer to my follow-up question concerning how to pass the AppID
using JNA.
我已经将此奖励给了Gregory Pakosz对JNI的精彩回答,让我走上正轨。
I had awarded the bounty to Gregory Pakosz' brilliant answer for JNI that set me on the right track.
作为参考,我相信使用这种技术可以使用任何讨论的API 是另一种可以节省的解决方案你只是为了转发到windows api而编写本机代码。如果你决定去jna,请注意 SetCurrentProcessExplicitAppUserModelID()
期待一个UTF-16字符串的事实。
Your question explicitly asked for a JNI solution. However, since your application doesn't need any other native method, jna is another solution which will save you from writing native code just for the sake of forwarding to the windows api. If you decide to go jna, pay attention to the fact that SetCurrentProcessExplicitAppUserModelID()
is expecting a UTF-16 string.
当它在沙盒中工作时,下一步是在应用程序中添加操作系统检测,因为 SetCurrentProcessExplicitAppUserModelID()
显然仅在Windows 7中可用:
When it works in your sandbox, the next step is to add operating system detection in your application as SetCurrentProcessExplicitAppUserModelID()
is obviously only available in Windows 7:
- 您可以通过检查
System.getProperty(os.name); 返回
Windows 7
。 - 如果您使用我提供的小JNI片段构建,您可以动态增强它使用然后使用。如果
GetProcAddress
返回NULL
,则表示该符号不存在于shell32 因此它不是Windows 7。
you may do that from the Java side by checking that
System.getProperty("os.name");
returns"Windows 7"
.if you build from the little JNI snippet I gave, you can enhance it by dynamically loading the
shell32.dll
library usingLoadLibrary
then getting back theSetCurrentProcessExplicitAppUserModelID
function pointer usingGetProcAddress
. IfGetProcAddress
returnsNULL
, it means the symbol is not present inshell32
hence it's not Windows 7.
编辑:。
参考文献:
The JNI book for more JNI examples
Java Native Access (JNA)
这篇关于将Java应用程序固定到Windows 7任务栏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!