21

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から変換してみました。PWSTR正直なところ、(a) a のサイズがわからず、(b)GetCurrentProcessExplicitAppUserModelIDが実際にバイト配列または文字列を返すかどうかわからないため、ここでの私のアプローチが正しいかどうかはわかりません。

JSmooth は、こ​​の効果をシミュレートするラッパーで GUI プロセスを実行することを認識しています。Launch4j は同じことを行うと主張していますが、機能していないようです。Javaラッパーに関係なくAppUserModelID、セットを探しています。

ここで何がうまくいかないのですか?

4

3 に答える 3

19

以前にあなたの質問を見たことがありませんでした。

これが私が思いついたものです。コード自体に記載されているように、関数 (から)を使用して適切なメモリ クリーンアップを実装していないことに注意してください。したがって、実装のみを使用することをお勧めしますCoTaskMemFreeOle32.dllSetCurrentProcessExplicitAppUserModelID()

package com.stackoverflow.AppIdTest;

import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.ptr.PointerByReference;

public class AppIdTest
{

  public static void main(String[] args) throws Exception
  {
    setCurrentProcessExplicitAppUserModelID(AppIdTest.class.getName());

    System.out.println(getCurrentProcessExplicitAppUserModelID());
  }

  // DO NOT DO THIS, IT'S JUST FOR TESTING PURPOSE AS I'M NOT FREEING THE MEMORY
  // AS REQUESTED BY THE DOCUMENTATION:
  //
  // http://msdn.microsoft.com/en-us/library/dd378419%28VS.85%29.aspx
  //
  // "The caller is responsible for freeing this string with CoTaskMemFree when
  // it is no longer needed"
  public static String getCurrentProcessExplicitAppUserModelID()
  {
    final PointerByReference r = new PointerByReference();

    if (GetCurrentProcessExplicitAppUserModelID(r).longValue() == 0)
    {
      final Pointer p = r.getValue();


      return p.getString(0, true); // here we leak native memory by lazyness
    }      
    return "N/A";
  }

  public static void setCurrentProcessExplicitAppUserModelID(final String appID)
  {
    if (SetCurrentProcessExplicitAppUserModelID(new WString(appID)).longValue() != 0)
      throw new RuntimeException("unable to set current process explicit AppUserModelID to: " + appID);
  }

  private static native NativeLong GetCurrentProcessExplicitAppUserModelID(PointerByReference appID);
  private static native NativeLong SetCurrentProcessExplicitAppUserModelID(WString appID);


  static
  {
    Native.register("shell32");
  }
}

それはあなたのために働きますか?

少なくともここでは正しく出力されます:

com.stackoverflow.AppIdTest.AppIdTest

于 2009-12-18T15:21:23.553 に答える
3

AppUserModelId を設定するだけであれば、上記の JNA コードで十分です。ただし、Java アプリケーションで Windows 7 の新機能を利用したい場合は、Windows 7 のタスクバー拡張機能を提供する Java ライブラリであるJ7Goodiesをチェックしてください。


EDITJ7Goodies Programmer's Guideからの詳細情報

4.2. AppUserModelID の設定

Windows 7 のいずれかの機能を使用するには、アプリケーションでプロセス識別子 (アプリケーション ユーザー モデル ID ( AppUserModelID)) を明示的に設定する必要があります。128 文字以内で、スペースを含めることはできません。各セクションはキャメルケースにする必要があります。次に例を示します。

 CompanyName.ProductName.SubProduct.VersionInformation

この識別子は、GUI (ウィンドウ) が表示される前に設定する必要があります。次のように呼び出して設定します。

// Remember to set AppUserModelID before creating any UI
AppUserModelId.setCurrentProcessId("StrixCode.J7Goodies.Appname");

4.3. ウィンドウ プロパティの設定

ウィンドウのプロパティが定義されていない限り、Java アプリケーションを Windows 7 のタスクバーにピン留めすることはできません。プロパティは次の 4 つのフィールドで構成されます。

  • AppUserModelID – に渡されるものと同じAppUserModelId.setCurrentProcessId(String)
  • RelaunchDisplayName – アプリケーションの名前
  • RelaunchCommand – アプリケーションの起動に使用される完全なコマンド。Java プログラムの場合は、次のようになります。<path to javaw.exe> -jar <path to application jar>
  • RelaunchIcon – アプリケーションのアイコンへのパス

重要: RelaunchCommandandRelaunchDisplayNameは常に一緒に設定する必要があります。これらのプロパティを設定するには、単純な WindowProperties クラスを使用します。

WindowProperties props = new WindowProperties(myFrame);
props.setRelaunchCommand("<full path to javaw.exe –arguments>");
props.setRelaunchDisplayName("My Java Application");
props.setRelaunchIcon("<full path to an .ico or .exe file>");
props.setAppUserModelID("StrixCode.J7Goodies.Appname");
props.save();
于 2010-12-02T14:57:29.173 に答える