Ajouter une commande de menu contextuel explorateur de fichiers à une application de bureau empaquetée

Windows 11 applications étendent le menu contextuel de l’Explorateur de fichiers moderne en implémentant IExplorerCommand et en inscrivant la commande avec l’identité de l’application. Cela s’applique aux applications de bureau empaquetées et aux applications Win32 non empaquetées qui utilisent un package partiellement alloué.

Une association de type de fichier peut rendre une application disponible dans Open avec ou ajouter un verbe d’édition pour un type de fichier géré par l’application. Il ne fournit pas l’extension de menu contextuel à usage général décrite dans cet article. Pour ajouter une commande pour les fichiers, dossiers ou arrière-plans de dossiers arbitraires, utilisez IExplorerCommand.

Pour plus d’informations sur la conception du menu contextuel de Windows 11 et sur les cas dans lesquels ajouter une commande, consultez Extension du menu contextuel et de la boîte de dialogue de partage dans Windows 11.

Fonctionnement des extensions de menu contextuel

Une extension de menu contextuel comporte les éléments suivants :

  1. Une DLL native implémente une ou plusieurs classes COM qui exposent IExplorerCommand.
  2. Le manifeste de package inscrit chaque classe COM en tant qu’extension windows.comServer .
  3. Le manifeste du package enregistre la commande comme extension windows.fileExplorerContextMenus et associe un type d’élément de shell au CLSID de la classe COM.

L’Explorateur de fichiers active la classe COM lorsqu’elle génère le menu contextuel. Votre IExplorerCommand implémentation fournit le titre, l’icône, l’état et l’action. Les commandes de la même application peuvent être regroupées dans un menu volant attribué à l’application ; implémentez EnumSubCommands pour fournir les commandes enfants.

Important

L’Explorateur de fichiers charge le code d’extension du shell dans le cadre de l’expérience du shell. Gardez GetTitle, GetIcon, GetState et les autres méthodes de création de menus rapides. N’effectuez pas de travail coûteux sur le chemin d’interface utilisateur de l’Explorateur de fichiers. Exécutez des opérations plus longues après l’appel de Invoke.

Implémenter IExplorerCommand

Implémentez IExplorerCommand dans une DLL COM native. C++ est le choix habituel, car la commande s’exécute dans le chemin d’intégration shell. L’implémentation abrégée suivante fournit un titre de commande, active la commande et reçoit les éléments sélectionnés lorsque l’utilisateur l’appelle.

class EditCommand final : public IExplorerCommand
{
public:
    IFACEMETHODIMP GetTitle(IShellItemArray*, PWSTR* title)
    {
        return SHStrDup(L"Edit with Contoso", title);
    }

    IFACEMETHODIMP GetState(
        IShellItemArray*, BOOL, EXPCMDSTATE* state)
    {
        *state = ECS_ENABLED;
        return S_OK;
    }

    IFACEMETHODIMP Invoke(IShellItemArray* items, IBindCtx*)
    {
        // Obtain selected items from items and start the app or operation.
        return S_OK;
    }

    IFACEMETHODIMP GetIcon(IShellItemArray*, PWSTR* icon)
    {
        return SHStrDup(L"ContosoCommand.dll,-101", icon);
    }

    IFACEMETHODIMP GetToolTip(IShellItemArray*, PWSTR* tooltip)
    {
        *tooltip = nullptr;
        return E_NOTIMPL;
    }

    IFACEMETHODIMP GetCanonicalName(GUID* canonicalName)
    {
        *canonicalName = GUID_NULL;
        return S_OK;
    }

    IFACEMETHODIMP GetFlags(EXPCMDFLAGS* flags)
    {
        *flags = ECF_DEFAULT;
        return S_OK;
    }

    IFACEMETHODIMP EnumSubCommands(IEnumExplorerCommand** commands)
    {
        *commands = nullptr;
        return E_NOTIMPL;
    }
};

Utilisez le IShellItemArray transmis à Invoke pour énumérer la sélection actuelle. GetState peut retourner des états tels que ECS_HIDDEN, ECS_DISABLEDou ECS_ENABLED pour contrôler si la commande apparaît et peut être sélectionnée. Pour le contrat complet, consultez IExplorerCommand.

Affectez à la classe COM un CLSID et vérifiez que le même CLSID est utilisé dans le manifeste du package. Par exemple:

class __declspec(uuid("01234567-89AB-CDEF-0123-456789ABCDEF"))
    EditCommand;

Inscrire la commande dans le manifeste du package

Déclarez les espaces de noms com, desktop4 et desktop5 sur l’élément racine Package et ajoutez-les à IgnorableNamespaces.

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
  xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
  xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
  IgnorableNamespaces="com desktop4 desktop5">
  <!-- ... -->
</Package>

Sous l’élément d’application Extensions , inscrivez d’abord la DLL en tant que serveur COM. com:Class/@Id est le CLSID de la commande et Path est le chemin relatif du package de la DLL.

<com:Extension Category="windows.comServer">
  <com:ComServer>
    <com:SurrogateServer DisplayName="Contoso commands">
      <com:Class
        Id="01234567-89AB-CDEF-0123-456789ABCDEF"
        Path="ContosoCommand.dll"
        ThreadingModel="STA" />
    </com:SurrogateServer>
  </com:ComServer>
</com:Extension>

Associez ensuite le CLSID au contexte dans lequel la commande doit apparaître.

<desktop4:Extension Category="windows.fileExplorerContextMenus">
  <desktop4:FileExplorerContextMenus>
    <desktop5:ItemType Type="*">
      <desktop5:Verb
        Id="EditWithContoso"
        Clsid="01234567-89AB-CDEF-0123-456789ABCDEF" />
    </desktop5:ItemType>
  </desktop4:FileExplorerContextMenus>
</desktop4:Extension>

desktop5:ItemType/@Type identifie les éléments du shell cible. Utiliser * pour les fichiers, Directory pour les dossiers sélectionnés ou Directory\Background pour l’arrière-plan d’un dossier. Vous pouvez inscrire plusieurs ItemType entrées pour le même CLSID lorsqu’une commande prend en charge plusieurs contextes.

desktop5:Verb/@Id identifie l’enregistrement du manifeste. desktop5:Verb/@Clsid doit correspondre à la com:Class/@Id valeur et au CLSID sur la classe COM.

Pour obtenir le schéma de manifeste complet, consultez desktop4 :FileExplorerContextMenus et com :Class.

Empaqueter la DLL

Incluez la DLL de commande et toutes les ressources dont elle a besoin dans le package au niveau du chemin d’accès spécifié par com:Class/@Path. Si vous utilisez un Project d’empaquetage d’applications Windows, ajoutez la DLL au project et configurez-la pour la copier dans la sortie du package. Configurez une dépendance de build ou une copie post-build pour que le package contienne la DLL actuelle.

L’architecture DLL doit correspondre à l’architecture de l’Explorateur de fichiers qui la charge. Générez et empaquetez l’architecture appropriée pour l’appareil cible.

Utiliser un package partiel pour une application non packagée

Une application Win32 non empaquetée peut utiliser les mêmes IExplorerCommand et les mêmes déclarations de manifeste en installant un package fragmenté qui confère à l’application une identité de package. Un package sparse ne contient pas les binaires de l’application ; il fait référence à l’application installée séparément à la place.

Outre les extensions COM et de menus contextuels présentées précédemment, un manifeste de package sparse déclare uap10:AllowExternalContent et configure l’application comme une application Win32. L’exemple suivant montre les déclarations de package sparse pertinentes.

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  IgnorableNamespaces="uap10 rescap">

  <Properties>
    <uap10:AllowExternalContent>true</uap10:AllowExternalContent>
  </Properties>

  <Applications>
    <Application
      Id="ContosoApp"
      Executable="ContosoApp.exe"
      uap10:TrustLevel="mediumIL"
      uap10:RuntimeBehavior="win32App">
      <!-- VisualElements and the COM/context-menu Extensions go here. -->
    </Application>
  </Applications>

  <Capabilities>
    <rescap:Capability Name="runFullTrust" />
    <rescap:Capability Name="unvirtualizedResources" />
  </Capabilities>
</Package>

Consultez les packages partiels pour connaître les conditions de création de package et d’inscription des applications non empaquetées.

Tester l’extension

Installez ou inscrivez le package, puis ouvrez l’Explorateur de fichiers et cliquez avec le bouton droit sur un élément correspondant à l’un des types d’éléments inscrits. Si la commande n’apparaît pas après l’installation ou la mise à jour d’un package, redémarrez l’Explorateur de fichiers ou reconnectez-vous afin que l’interpréteur de commandes recharge l’inscription de l’extension.

Utilisez Afficher plus d’options uniquement pour inspecter les extensions de menu contextuel héritées. Une commande enregistrée via windows.fileExplorerContextMenus et implémentée avec IExplorerCommand apparaît dans le menu contextuel de Windows 11.

Associations de types de fichiers

Inscrivez une association de type de fichier lorsque l’application ouvre ou modifie ce type de fichier. Il peut rendre l’application disponible via Open with et ajouter un verbe de modification pour les types de fichiers associés. Utilisez le mécanisme de menu contextuel de cet article pour les commandes qui s’appliquent aux fichiers, dossiers ou arrière-plans génériques, ou pour les commandes qui effectuent des opérations sans ouvrir l’expérience normale d’ouverture de fichier de l’application.