Launch4jをWindows7でのJavaアプリケーションのラッパーとして使用します。これは、私の理解では、本質的にjavaw.exe
のインスタンスをフォークし、それがJavaコード。その結果、アプリケーションをタスクバーに固定しようとすると、Windowsは代わりにjavaw.exe
を固定します。必要なコマンドラインがないと、アプリケーションは実行されません。
ご覧のとおり、WindowsはJavaがホストアプリケーションであることも認識していません。アプリケーション自体は「Java(TM)プラットフォームSEバイナリ」として記述されています。
レジストリキーHKEY_CLASSES_ROOT\Applications\javaw.exe
を変更して値IsHostApp
を追加しようとしました。これにより、アプリケーションの固定が完全に無効になり、動作が変わります。明らかに私が望むものではありません。
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
}
これは効果がないように見えますが、関数はエラーなしで戻ります。なぜそれを診断するのは私には謎のようなものです。助言がありますか?
うまくいった最終的な実装は 私のフォローアップの質問への答え JNAを使用してAppID
を渡す方法に関するものです。
私は、Gregory PakoszのJNIに対する見事な回答に報奨金を授与し、私を正しい軌道に乗せました。
参考までに、この手法を使用すると、説明したAPIのいずれかを使用できる可能性が広がると思います この記事で Javaアプリケーションで。
私はWindows7を持っていませんが、ここにあなたが始めるかもしれない何かがあります:
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ソリューションを求めていました。ただし、アプリケーションは他のネイティブメソッドを必要としないため、 jna は、WindowsAPIに転送するためだけにネイティブコードを記述しないようにする別のソリューションです。 jnaに移行する場合は、SetCurrentProcessExplicitAppUserModelID()
がUTF-16文字列を予期していることに注意してください。
サンドボックスで機能する場合、次のステップは、アプリケーションにオペレーティングシステムの検出を追加することです。これは、SetCurrentProcessExplicitAppUserModelID()
が明らかにWindows7でのみ使用できるためです。
System.getProperty("os.name");
が_"Windows 7"
_を返すことを確認することにより、Java側からこれを行うことができます。LoadLibrary
を使用して_Shell32.dll
_ライブラリを動的にロードし、SetCurrentProcessExplicitAppUserModelID
関数を取得することで拡張できます。 GetProcAddress
を使用したポインタ。 GetProcAddress
がNULL
を返す場合、シンボルが_Shell32
_に存在しないため、Windows7ではないことを意味します。編集: JNAソリューション 。
参照:
Java Java用の新しいWindows7機能を提供するライブラリがあります。これは J7Goodies by Strix Code と呼ばれます。これを使用するアプリケーションは適切に使用できます。 Windows7タスクバーに固定されています。独自のジャンプリストなどを作成することもできます。
JNAを使用してSetCurrentProcessExplicitAppUserModelIDメソッドへのアクセスを実装しましたが、MSDNドキュメントが示すように使用すると非常にうまく機能します。コードスニペットのようにJNAAPIを使用したことはありません。私の実装は、代わりに 通常のJNAの使用法 に従います。
まず、Shell32インターフェイスの定義:
interface Shell32 extends StdCallLibrary {
int SetCurrentProcessExplicitAppUserModelID( WString appID );
}
次に、JNAを使用してShell32をロードし、関数を呼び出します。
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で直接使用するのが非常に難しいWindowsCOMを使用しています。これらのAPIを呼び出すためのカスタムDLLを作成して(たとえば、SHGetPropertyStoreForWindowを使用してサブモジュールウィンドウに別のアプリIDを設定する)、実行時にJNAを使用してアクセスすることに成功しました。
JSmooth を使用してみてください。私はいつもこれを使います。 JSmoothには、Skeleton
の下にWindowed Wrapper
によって呼び出されるオプションがあります
Lauch Java exeプロセスのアプリ
この画像を参照してください。
コマンドライン引数を渡すこともできます。
これはあなたにとっての解決策になると思います。
マルティン
SetCurrentProcessExplicitAppUserModelID(またはSetAppID())は、実際には、実行しようとしていることを実行します。ただし、インストーラーを変更して、ショートカットにAppUserModel.IDプロパティを設定する方が簡単な場合があります-上記の アプリケーションユーザーモデルID ドキュメントから引用します。
アプリケーションのショートカットファイルの System.AppUserModel.ID プロパティ。ショートカット(IShellLink、CLSID_ShellLink、または.lnkファイルとして)は、IPropertyStoreおよびシェル全体で使用されるその他のプロパティ設定メカニズムを介してプロパティをサポートします。これにより、タスクバーはピン留めするための適切なショートカットを識別し、プロセスに属するウィンドウがそのタスクバーボタンに適切に関連付けられるようになります。注:ショートカットの作成時に、System.AppUserModel.IDプロパティをショートカットに適用する必要があります。 Microsoft Windowsインストーラー(MSI)を使用してアプリケーションをインストールする場合、 MsiShortcutProperty テーブルを使用すると、インストール中に作成されたショートカットにAppUserModelIDを適用できます。
最新の jna-platform
ライブラリにSetCurrentProcessExplicitAppUserModelID
のJNAバインディングが含まれるようになりました。
IDを設定せずに修正しました。 Launch4Jを使用していて、使用すると言う場合は、Launch4Jにオプションがあります...
ヘッダーをJNIGuiに変更してから、JREでjarにラップすることができます。良い点は、jarでjavaw.exeを実行する代わりに、プロセスで.exeを実行することです。それはおそらくボンネットの下でそれを行います(確かではありません)。また、CPUリソースが約40〜50%少なくて済み、さらに優れていることにも気づきました。
また、ピン留めは正常に機能し、すべてのウィンドウ機能が有効になります。
装飾されていないjavafxアプリでその問題を解決するために2日近く費やしたので、誰かに役立つことを願っています。