Pinning a Java application to the Windows 7 taskbar

Posted by Paul Lammertsma on Stack Overflow See other posts from Stack Overflow or by Paul Lammertsma
Published on 2009-12-02T17:44:01Z Indexed on 2010/03/14 22:35 UTC
Read the original article Hit count: 827

Filed under:
|
|
|
|

Original question

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.

Result of pinning a Launch4j application to the taskbar

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".

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.

Result of specifying javaw.exe as a host application

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.

I believe that I can resolve this by passing a unique AppUserModelID to Windows. There is a shell32 method for this, SetAppID(). (Or SetCurrentProcessExplicitAppUserModelID?) Is it possible to call it via JNI? If so, would this even resolve the issue?

On a side note, I was curious if any of the APIs discussed in this article could be implemented for a Java application.

Edit after implementing JNA, as Gregory Pakosz suggested

I've now implemented the following 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?

Working implementation

The final implementation that worked is the answer to my follow-up question concerning how to pass the AppID using JNA.

I had awarded the bounty to Gregory Pakosz' brilliant answer for JNI that set me on the right track.

© Stack Overflow or respective owner

Related posts about java

Related posts about jni