質問

Windows 7 で Java アプリケーションのラッパーとして Launch4j を使用しています。私の理解では、これは本質的に次のインスタンスをフォークします。 javaw.exe 次に、Java コードを解釈します。その結果、アプリケーションをタスク バーに固定しようとすると、代わりに Windows が固定してしまいます。 javaw.exe. 。必要なコマンド ラインがなければ、アプリケーションは実行できません。

Result of pinning a Launch4j application to the taskbar

ご覧のとおり、Windows は Java がホスト アプリケーションであることを認識しません。アプリケーション自体は「Java(TM) Platform SE バイナリ」と記述されます。

レジストリキーを変更してみました HKEY_CLASSES_ROOT\Applications\javaw.exe 値を追加する IsHostApp. 。これにより、アプリケーションの固定が完全に無効になり、動作が変わります。明らかに私が望んでいることではありません。

Result of specifying javaw.exe as a host application

について読んだ後、 Windows が単一アプリケーションのインスタンスをどのように解釈するか (そして この質問で議論されている現象)、私はアプリケーション ユーザー モデル ID (AppUserModelID) を Java アプリケーションに埋め込むことに興味を持ちました。

ユニークなパラメータを渡すことでこれを解決できると思います AppUserModelID Windowsに。があります shell32 このための方法、 SetCurrentProcessExplicitAppUserModelID. 。Gregory Pakosz の提案に従い、アプリケーションを別のインスタンスとして認識させるためにこれを実装しました。 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
}

これには効果がないように見えますが、関数はエラーなしで戻ります。その理由を診断することは私にとって謎のようなものです。助言がありますか?

実用的な実装

機能した最終的な実装は次のとおりです 私のフォローアップの質問に対する答え 渡し方については AppID JNAを使用します。

私は、正しい軌道に乗せてくれた JNI に対する Gregory Pakosz の素晴らしい回答に報奨金を授与しました。

参考までに、この手法を使用すると、説明した API のいずれかを使用できる可能性が開かれると思います。 記事上で Java アプリケーションで。

役に立ちましたか?

解決

私は Windows 7 を持っていませんが、始めるきっかけとなるかもしれないものは次のとおりです。

Java 側:

package com.stackoverflow.homework;

public class MyApplication
{
  static native boolean setAppUserModelID();

  static
  {
    System.loadLibrary("MyApplicationJNI");
    setAppUserModelID();
  }
}

ネイティブ側の `MyApplicationJNI.dll ライブラリのソース コードでは次のようになります。

JNIEXPORT jboolean JNICALL Java_com_stackoverflow_homework_MyApplication_setAppUserModelID(JNIEnv* env)
{
  LPCWSTR id = L"com.stackoverflow.homework.MyApplication";
  HRESULT hr = SetCurrentProcessExplicitAppUserModelID(id);

  return hr == S_OK;
}

あなたの質問は明示的に JNI ソリューションを求めています。ただし、アプリケーションには他のネイティブ メソッドが必要ないため、 ジナ これは、Windows API に転送するためだけにネイティブ コードを作成する手間を省く別のソリューションです。jnaに行くことに決めた場合は、次のことに注意してください。 SetCurrentProcessExplicitAppUserModelID() UTF-16 文字列が必要です。

サンドボックスで動作したら、次のステップはアプリケーションにオペレーティング システムの検出を追加することです。 SetCurrentProcessExplicitAppUserModelID() 明らかに Windows 7 でのみ利用可能です。

  • それをチェックすることでJava側からそれを行うことができます System.getProperty("os.name"); 戻り値 "Windows 7".
  • 私が提供した小さな JNI スニペットから構築する場合、動的にロードすることで拡張できます。 shell32.dll ライブラリを使用して LoadLibrary それから戻ってきます SetCurrentProcessExplicitAppUserModelID 関数ポインターを使用する GetProcAddress. 。もし GetProcAddress 戻り値 NULL, 、それはシンボルが存在しないことを意味します shell32 したがって、Windows 7ではありません。

編集: JNAソリューション.

参考文献:

他のヒント

Java用の新しいWindows 7の機能を提供するJavaライブラリがあります。それは<のhref = "HTTPでにJava"> J7Goodiesための7の特徴は、ストリックスコードする。それを使用するアプリケーションが正常にWindows 7のタスクバーにピン留めすることができます。あなたはまた、など、独自のジャンプリストを作成することができます。

JSmooth を使用してみてください。私はいつも、このいずれかを使用します。 JSmoothで呼ばSkeletonによってWindowed Wrapper下のオプションがあります。

  

exeファイルのプロセスで出せのJavaアプリ

この画像で見る。

JSmooth

またライン引数を渡すことができるコマンド。
私は、これはあなたのための解決策になることができると思います。

マルタイン

私はJNAを使用してSetCurrentProcessExplicitAppUserModelIDメソッドへのアクセスを実装しているし、MSDNのドキュメントが示唆するように使用された場合、それはかなりうまく動作します。私はあなたのコードスニペットを持っているように、JNA APIを使用したことがありません。私の実装ではなく、典型的なJNA使い方に従います。

まずShell32はインタフェースの定義:

interface Shell32 extends StdCallLibrary {

    int SetCurrentProcessExplicitAppUserModelID( WString appID );

}

次にShell32はをロードし、関数を呼び出すJNAを使用します:

final Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() {
    {
       put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
       put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
    }
};
Shell32 shell32 = (Shell32) Native.loadLibrary("shell32", Shell32.class,
           WIN32API_OPTIONS);
WString wAppId = new WString( "Vendor.MyJavaApplication" );
shell32.SetCurrentProcessExplicitAppUserModelID( wAppId );

APIのあなたはJNAを直接使用することは非常に困難であり、WindowsのCOMのメイク使用を述べた最後の記事に多くの。私はその後、実行時にアクセスするためにJNAを使用している(サブモジュールウィンドウごとに異なるアプリケーションIDを設定するSHGetPropertyStoreForWindowを使用して。例えば)これらのAPIを呼び出すためにカスタムDLLを作成し、いくつかの成功を収めている。

SetCurrentProcessExplicitAppUserModelID (または SetAppID()) は、実際にやろうとしていることを実行します。ただし、インストーラーを変更してショートカットに AppUserModel.ID プロパティを設定する方が簡単な場合があります。 アプリケーションユーザーモデルID 前述の文書:

の中に System.AppUserModel.ID アプリケーションのショートカット ファイルのプロパティ。ショートカット (IShellLink、CLSID_ShellLink、または .lnk ファイルとして) は、IPropertyStore およびシェル全体で使用されるその他のプロパティ設定メカニズムを通じてプロパティをサポートします。これにより、タスク バーがピン留めする適切なショートカットを識別できるようになり、プロセスに属するウィンドウがそのタスク バー ボタンに適切に関連付けられるようになります。注記:System.AppUserModel.ID プロパティは、ショートカットの作成時にショートカットに適用する必要があります。Microsoft Windows インストーラー (MSI) を使用してアプリケーションをインストールする場合、 MsiShortcutプロパティ 表を使用すると、インストール中に作成されるショートカットに AppUserModelID を適用できます。

最新jna-platformライブラリは現在、SetCurrentProcessExplicitAppUserModelIDためJNAバインディングが含まれます:

https://github.com/java-native-access/jna/プル/ 680

私は、任意のIDを設定せずに鉱山を修正しました。 あなたがそれを使用していて、あなたがしてやると言っている場合Launch4Jでオプションが...あります。

あなたはJNI GUIへのヘッダーを変更して、JREと瓶のまわりでそれをラップすることができます。 良いところは、それはあなたのjarファイルとjavaw.exeのを実行する上で、今の代わりにプロセスで.exeファイルを実行していることです。それはおそらくフード(わからない)の下でそれをしません。 また、私はそれがさらに良いです周りの40から50パーセント少ないCPUリソースを取ることも気づきました!

そしてピニングが正常に動作し、すべてそのウィンドウの機能が有効になっています。

私は装飾のないJavaFXのアプリでその問題を解決しようとしてほぼ2日間を過ごしたとして、それは誰かに役立ちます願っています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top