سؤال

متابعة سؤالي السابق بشأن شريط مهام 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 و (ب) لا أعرف ما إذا كان GetCurrentProcessExplicitAppUserModelID هو بالفعل عودة مجموعة بايت أو سلسلة.

أنا أدرك أن JSMOOTH ستقوم بتشغيل عملية واجهة المستخدم الرسومية في مجمع يحاكي هذا التأثير. Launch4J مطالبات أن تفعل الشيء نفسه، ولكن لا يبدو للعمل. أنا أتطلع للحصول على AppUserModelID تعيين بغض النظر عن غلاف جافا.

ما يحدث الخطأ هنا؟

هل كانت مفيدة؟

المحلول

لم أر سؤالك قبل خلاف ذلك كنت سأقدم محاولة حتى بدون مكافأة.

هنا هو ما توصلت إليه. يرجى ملاحظة، كما هو مذكور في الكود نفسه، لم أقوم بتطبيق الذاكرة المناسبة تنظيف مع CoTaskMemFree وظيفة (من Ole32.dll). لذلك أقترح عليك أن تأخذ فقط التنفيذ ل SetCurrentProcessExplicitAppUserModelID()

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

نصائح أخرى

إذا كنت بحاجة فقط إلى تعيين AppusermodelId، فإن رمز JNA أعلاه يكفي. ومع ذلك، إذا كنت ترغب في الاستفادة من ميزات Windows 7 الجديدة في تطبيق Java الجديد، تحقق من J7goodies. مكتبة Java توفر ملحقات شريط المهام ويندوز 7.


تعديل: مزيد من المعلومات من J7goodies. دليل مبرمج

4.2. وضع Appusermodelid.

من أجل استخدام أي من ميزات Windows 7، يجب أن يضع تطبيق بشكل صريح معرف العملية - معرف نموذج المستخدم (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 ما لم يتم تعريف خصائص النافذة الخاصة به. تتكون الخصائص من أربعة حقول:

  • Appusermodelid - نفس الشيء الذي تم تمريره AppUserModelId.setCurrentProcessId(String)
  • relaunchdisplayname - اسم التطبيق
  • relaunchcommand - الأمر الكامل المستخدم لإطلاق التطبيق. في حالة وجود برنامج Java، سيكون: <path to javaw.exe> -jar <path to application jar>
  • relaunchicon - طريق أيقونة التطبيق

الأهمية: RelaunchCommand و RelaunchDisplayName يجب أن يتم تعيين دائما معا. لتعيين هذه الخصائص استخدم فئة WindowProprePerties.

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();

إليك مثال أكثر بسيطة حول كيفية الاتصال SetCurrentProcessExplicitAppUserModelID عبر JNA:

import com.sun.jna.*;
import com.sun.jna.win32.*;

interface Shell32 extends StdCallLibrary {

    Shell32 INSTANCE = (Shell32) Native.loadLibrary("shell32", Shell32.class, W32APIOptions.DEFAULT_OPTIONS);

    NativeLong SetCurrentProcessExplicitAppUserModelID(WString appID);

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top