應用程式使用者模型識別碼 (AppUserModelIDs)

應用程式使用者模型識別碼 (AppUserModelIDs) 是由 Windows 7 和更新版本中的工作列廣泛使用,以將進程、檔案和視窗與特定應用程式產生關聯。 在某些情況下,就足以依賴系統指派給進程的內部 AppUserModelID。 不過,擁有多個進程的應用程式或主進程中執行的應用程式可能需要明確識別本身,使其可以在單一工作列按鈕下將其其他不同的視窗分組,並控制該應用程式的跳躍清單內容。

Application-Defined和System-Defined AppUserModelIDs

某些應用程式不會宣告明確的 AppUserModelID。 它們是選擇性的。 在此情況下,系統會使用一系列啟發學習法來指派內部 AppUserModelID。 不過,避免這些計算有效能優勢,而明確的 AppUserModelID 是保證確切使用者體驗的唯一方式。 因此,強烈建議您設定明確的識別碼。 應用程式無法擷取系統指派的 AppUserModelID。

如果應用程式使用明確的 AppUserModelID,它也必須將相同的 AppUserModelID 指派給所有執行中的視窗或進程、快捷方式和檔案關聯。 它也必須在透過 ICustomDestinationList自訂其跳躍清單時使用該 AppUserModelID,以及任何 對 SHAddToRecentDocs的呼叫。

注意

如果應用程式沒有明確的 AppUserModelID,則必須從應用程式內呼叫 IApplicationDestinationsIApplicationDocumentListsICustomDestinationList 方法,以及 SHAddToRecentDocs 。 如果從另一個進程呼叫這些方法,例如安裝程式或卸載程式,系統就無法產生正確的 AppUserModelID,而且這些呼叫不會有任何作用。

 

下列專案描述需要明確 AppUserModelID 的常見案例。 它們也會指出應該使用多個明確的 AppUserModelID 的情況。

  • 具有多個模式且使用者顯示為個別應用程式的 UI 的單一可執行檔,應該將不同的 AppUserModelID 指派給每個模式。 例如,使用者看到的應用程式部分是獨立體驗,他們可以釘選並從工作列個別啟動,而應用程式其餘部分應該有自己的 AppUserModelID,與主要體驗不同。

  • 具有不同引數的多個快捷方式,全都會導致使用者看到相同的應用程式,應該對所有快捷方式使用一個 AppUserModelID。 例如,Windows Internet Explorer 針對不同的模式有不同的快捷方式 (,例如在沒有附加元件的情況下啟動) ,但全都應該以單一 Internet Explorer 實例的形式向使用者顯示。

  • 做為主機進程的可執行檔,並以應用程式身分執行目標內容必須 註冊為主應用程式,之後就可以將不同的 AppUserModelID 指派給所裝載的每個感知體驗。 或者,主機進程可以允許裝載的程式設定其 AppUserModelID。 不論是哪一種情況,主機進程都必須保留 AppUserModelID 來源的記錄,不論是本身還是裝載的應用程式。 在此情況下,沒有目標內容,主機進程沒有主要使用者體驗。 範例包括 Windows 遠端應用程式整合在本機 (RAIL) 應用程式、JAVA 執行時間、RunDLL32.exe或DLLHost.exe。

    在現有的託管應用程式案例中,系統會嘗試識別個別體驗,但新的應用程式應該使用明確的 AppUserModelID 來保證預期的使用者體驗。

  • 與使用者合作或鏈結的程式屬於相同應用程式的一部分,應該將相同的 AppUserModelID 套用至每個進程。 範例包括具有啟動器進程的遊戲 (鏈結) 和 Microsoft Windows 媒體播放機,其具有在第一個進程中執行的初次執行/設定體驗,以及在另一個進程中執行的主要應用程式, (合作式) 。

  • Shell 命名空間延伸模組,做為個別的應用程式,在 Windows 檔案總管中流覽和管理內容時,應該在其資料夾屬性中指派 AppUserModelID。 例如,主控台。

  • 在部署架構之類的虛擬化環境中,虛擬化環境應該將不同的 AppUserModelID 指派給其管理的每個應用程式。 在這些情況下,應用程式啟動器會使用中繼程式來設定環境,然後將作業交出給不同的進程來執行應用程式。 請注意,這會導致系統無法讓執行中的目標進程回到快捷方式,因為快捷方式指向中繼進程。

    如果有任何應用程式有多個視窗、快捷方式或進程,該應用程式指派的 AppUserModelID 也應該套用至虛擬化環境的每個部分。

    這種情況的範例是 ClickOnce 架構,可代表其管理的應用程式正確指派 AppUserModelID。 如同所有這類環境,由 ClickOnce 部署及管理的應用程式不應該自行指派明確的 AppUserModelID,因為這麼做會與 ClickOnce 指派的 AppUserModelID 發生衝突,並導致非預期的結果。

如何形成 Application-Defined AppUserModelID

應用程式必須以下列形式提供其 AppUserModelID。 不能超過 128 個字元,而且不能包含空格。 每個區段都應該是 pascal 大小寫。

CompanyName.ProductName.SubProduct.VersionInformation

CompanyNameProductName 應該一律使用,而 SubProductVersionInformation 部分是選擇性的,而且取決於應用程式的需求。 SubProduct 允許包含數個子應用程式的主要應用程式,為每個子應用程式及其相關聯的視窗提供個別的工作列按鈕。 VersionInformation 允許兩個版本的應用程式共存,同時被視為離散實體。 如果應用程式不是以這種方式使用,則應該省略 , VersionInformation 讓升級的版本可以使用與其取代的版本相同的 AppUserModelID。

指派 AppUserModelID 的位置

當應用程式使用一或多個明確的 AppUserModelID 時,應該在下列位置和情況下套用這些 AppUserModelID:

  • 在應用程式的快捷方式檔案的 System.AppUserModel.ID 屬性中。 快捷方式 (做為 IShellLink、CLSID_ShellLink或 .lnk 檔案) 透過 IPropertyStore 和其他在整個 Shell 中使用的屬性設定機制支援屬性。 這可讓工作列識別釘選的適當快捷方式,並確保屬於進程的視窗與該工作列按鈕適當相關聯。

    注意

    建立該快捷方式時,應該將 System.AppUserModel.ID 屬性套用至快捷方式。 使用 Microsoft Windows Installer (MSI) 安裝應用程式時, MsiShortcutProperty 資料表可讓 AppUserModelID 在安裝期間套用至快捷方式。

     

  • 做為任何應用程式執行視窗的屬性。 這可以透過下列兩種方式之一來設定:

    1. 如果某個進程擁有的不同視窗需要不同的 AppUserModelID 來控制工作列群組,請使用 SHGetPropertyStoreForWindow) 來擷取視窗的屬性存放區,並將 AppUserModelID 設定為視窗屬性。
    2. 如果進程中的所有視窗都使用相同的 AppUserModelID,請透過 SetCurrentProcessExplicitAppUserModelID 在進程上設定 AppUserModelID。 應用程式必須在應用程式的初始啟動常式期間呼叫 SetCurrentProcessExplicitAppUserModelID 來設定其 AppUserModelID,然後應用程式才會呈現任何 UI、進行任何跳躍清單操作,或進行 (或讓系統對 SHAddToRecentDocs進行任何呼叫) 。

    視窗層級 AppUserModelID 會覆寫進程層級的 AppUserModelID。

    當應用程式在視窗層級設定明確的 AppUserModelID 時,應用程式可以為其工作列按鈕提供其重新開機命令的詳細資料。 若要提供該資訊,會使用下列屬性:

    注意

    如果啟動應用程式的快捷方式存在,應用程式應該將 AppUserModelID 套用為快捷方式的屬性,而不是使用重新開機屬性。 在此情況下,快捷方式的命令列、圖示和文字會用來提供與重新開機屬性相同的資訊。

     

    視窗層級明確的 AppUserModelID 也可以使用 System.AppUserModel.PreventPinning 屬性來指定它不應該用於釘選或重新開機。

  • 在自訂或更新 ICustomDestinationList () 的呼叫中,擷取 (IApplicationDocumentLists) ,或清除 (IApplicationDestinations) 應用程式的跳躍清單。

  • 如果應用程式使用系統自動產生的最近或頻繁目的地清單,則檔案關聯註冊 (透過ProgID) 。 SHAddToRecentDocs會參考此關聯資訊。 將 IShellItem 目的地新增至透過 ICustomDestinationList::AppendCategory自訂跳躍清單時,也會使用這項資訊。

  • 在任何呼叫中,應用程式都直接對 SHAddToRecentDocs進行。 如果應用程式相依于一般檔案對話方塊來代表 其呼叫 SHAddToRecentDocs ,則這些呼叫只有在針對整個進程設定 AppUserModelID 時,才會推斷明確的 AppUserModelID。 如果應用程式在其視窗上設定 AppUserModelID,而不是在進程中設定 AppUserModelID,則應用程式必須透過其明確的 AppUserModelID,以及防止一般檔案對話方塊自行呼叫 SHAddToRecentDocs 本身。 每當專案開啟時,都必須完成此動作,以確保應用程式的 [跳躍清單] 的 [ 最近 ] 或 [ 頻繁] 區段正確無誤。

下列專案描述常見案例,以及在這些案例中套用明確 AppUserModelID 的位置。

  • 當單一進程包含多個應用程式時,請使用 SHGetPropertyStoreForWindow 來擷取視窗的屬性存放區,並將 AppUserModelID 設定為視窗屬性。
  • 當應用程式使用多個進程時,請將 AppUserModelID 套用至每個進程。 無論您在每個進程上使用相同的 AppUserModelID,取決於您是否要讓每個進程顯示為主要應用程式或個別實體的一部分。
  • 若要將特定視窗與相同進程中的集合分開,請使用視窗的屬性存放區,將單一 AppUserModelID 套用至您想要分隔的視窗,然後將不同的 AppUserModelID 套用至進程。 該進程中未以視窗層級 AppUserModelID 明確標示的任何視窗都會繼承進程的 AppUserModelID。
  • 如果檔案類型與應用程式相關聯,請在檔案類型的 ProgID 註冊中指派 AppUserModelID。 如果以不同的模式啟動單一可執行檔,而使用者顯示為不同的應用程式,則每個模式都需要個別的 AppUserModelID。 在此情況下,檔案類型必須有多個 ProgID 註冊,每個類型都有不同的 AppUserModelID。
  • 當使用者可以從中啟動應用程式 (多個快捷方式位置時,在 [ 開始 ] 功能表、桌面或其他地方) 擷取快捷方式的屬性存放區,以將單一 AppUserModelID 套用至所有快捷方式做為快捷方式屬性。
  • 當應用程式對 SHAddToRecentDocs 進行明確呼叫時,請在呼叫中使用 AppUserModelID。 當通用檔案對話方塊用來開啟或儲存檔案時,對話方塊會代表應用程式呼叫 SHAddToRecentDocs 。 該呼叫可以從進程推斷明確的 AppUserModelID。 不過,如果明確套用 AppUserModelID 作為視窗屬性,則通用檔案對話方塊無法判斷正確的 AppUserModelID。 在此情況下,應用程式本身必須明確呼叫 SHAddToRecentDocs ,並提供正確的 AppUserModelID。 此外,應用程式必須在IFileOpenDialogIFileSaveDialogGetOptions方法中設定 FOS_DONTADDTORECENT 旗標,以防止常見的檔案對話方塊代表其呼叫 SHAddToRecentDocs

將應用程式註冊為主機進程

應用程式可以設定 IsHostApp 登錄專案,使可執行檔的進程被工作列視為主機進程。 這會影響其群組和預設的跳躍清單專案。

下列範例顯示必要的登錄專案。 請注意,專案未指派值;其存在是所有必要的專案。 它是REG_Null值。

HKEY_CLASSES_ROOT
   Applications
      example.exe
         IsHostApp

如果進程本身或用來啟動進程的快捷方式檔案具有明確的 AppUserModelID,則會忽略主機進程清單,而且應用程式會由工作列視為一般應用程式。 應用程式的執行視窗會分組在單一工作列按鈕下,而應用程式可以釘選到工作列。

如果只有執行中的進程可執行檔名稱已知,但沒有明確的 AppUserModelID,而且該可執行檔位於主機進程清單中,則進程的每個實例都會被視為工作列群組的個別實體。 與進程之任何特定實例相關聯的工作列按鈕不會顯示進程新實例的釘選/取消釘選選項或啟動圖示。 此程式也不適合包含在 [ 開始 ] 功能表的 [最常使用 (MFU) 清單中。 不過,如果進程是透過包含啟動引數的快捷方式啟動, (通常裝載為「應用程式」的目標內容) ,系統就可以判斷身分識別,而且可以釘選並重新啟動應用程式。

工作列釘選和最近/常用清單的排除清單

應用程式、進程和視窗可以選擇將自己釘選到工作列,或包含在 [ 開始 ] 功能表的 最常使用清單中。 有三種機制可以完成此作業:

  1. 將 NoStartPage 專案新增至應用程式的註冊,如下所示:

    HKEY_CLASSES_ROOT
       Applications
          Example.exe
             NoStartPage
    

    系統會忽略與 NoStartPage 專案相關聯的資料。 只需要有專案存在。 因此,NoStartPage 的理想類型是REG_NONE。

    請注意,任何使用明確的 AppUserModelID 會覆寫 NoStartPage 專案。 如果明確 AppUserModelID 套用至快捷方式、進程或視窗,它就會變成可釘選且符合 [ 開始 ] 功能表 最常使用清單的資格。

  2. 在視窗和快捷方式上設定 System.AppUserModel.PreventPinning 屬性。 這個屬性必須在視窗上設定, 才能PKEY_AppUserModel_ID 屬性。

  3. 將明確的 AppUserModelID 新增為下列登錄子機碼下的值,如下所示:

    HKEY_LOCAL_MACHINE
       Software
          Microsoft
             Windows
                CurrentVersion
                   Explorer
                      FileAssociation
                         NoStartPageAppUserModelIDs
                            AppUserModelID1
                            AppUserModelID2
                            AppUserModelID3
    

    每個專案都是具有 AppUserModelID 名稱的REG_Null值。 此清單中找到的任何 AppUserModelID 都無法釘選,而且不符合在 [ 開始 ] 功能表 最常使用清單中包含的資格。

請注意,某些可執行檔及其名稱中包含特定字串的快捷方式會自動排除在 最常使用清單中釘選和包含。

注意

您可以套用明確的 AppUserModelID 來覆寫此自動排除。

 

如果下列任一字串,不論大小寫為何,都會包含在快捷方式名稱中,則程式無法釘選,而且不會顯示在最常用的清單中, (不適用於Windows 10) :

  • 文件
  • 說明
  • 安裝
  • 其他資訊
  • 閱讀我
  • 讀取優先
  • 讀我檔案
  • 移除
  • 安裝程式
  • 支援
  • 新功能

下列程式清單無法釘選,而且會從最常使用的清單中排除。

  • Applaunch.exe
  • Control.exe
  • Dfsvc.exe
  • Dllhost.exe
  • Guestmodemsg.exe
  • Hh.exe
  • Install.exe
  • Isuninst.exe
  • Lnkstub.exe
  • Mmc.exe
  • Mshta.exe
  • Msiexec.exe
  • Msoobe.exe
  • Rundll32.exe
  • Setup.exe
  • St5unst.exe
  • Unwise.exe
  • Unwise32.exe
  • Werfault.exe
  • Winhlp32.exe
  • Wlrmdr.exe
  • Wuapp.exe

上述清單會儲存在下列登錄值中。

注意

應用程式不應修改這些清單。 使用先前列出的其中一個排除清單方法,以取得相同的體驗。

 

HKEY_LOCAL_MACHINE
   Software
      Microsoft
         Windows
            CurrentVersion
               Explorer
                  FileAssociation
                     AddRemoveApps
                     HostApps

SetCurrentProcessExplicitAppUserModelID

GetCurrentProcessExplicitAppUserModelID

工作列延伸模組

ICustomDestinationList::SetAppID

IApplicationDocumentLists::SetAppID

IApplicationDestinations::SetAppID

SHGetPropertyStoreForWindow