L'intégration au shell Windows aujourd'hui ── menus contextuels, associations de fichiers et ce qui a changé sous Windows 11
· Go Komura · Windows, Extensions du shell, Menu contextuel, Association de fichiers, COM, Windows 11, Explorateur de fichiers, MSIX, Développement Windows
On m’a consulté avec « nous avons remplacé les PC par Windows 11, et le menu contextuel de l’application que vous nous avez construite il y a des années a disparu ». En écoutant plus attentivement, il n’avait pas disparu. Clic droit sur un fichier, choisir « Afficher plus d’options » en bas du menu, et le menu familier apparaît comme toujours. Autrement dit, les éléments de menu de l’application interne avaient été cachés d’un clic plus loin. Du terrain on entend « c’est un clic de plus » et « les demandes de ceux qui ne trouvent pas l’élément ont augmenté ».
Ce n’est ni une panne ni une mauvaise configuration ; c’est un changement de conception de Windows 11. Le menu contextuel de l’Explorateur de fichiers est devenu une structure à deux couches, ancienne et nouvelle, et les conditions pour placer un élément dans le nouveau menu sont devenues tout autre chose qu’auparavant.
Cependant, le mécanisme d’association de fichiers et d’extensions de shell en dessous reste l’ancien monde de COM et du registre. Une clé d’extension pointe vers un ProgID, le verb du ProgID contient une ligne de commande, et une extension plus élaborée s’exécute comme serveur COM in-process (DLL) chargé dans l’Explorateur — cette structure n’a pas changé depuis plus de vingt ans. Si vous ne connaissez pas à la fois le fondement inchangé et le menu que Windows 11 a scindé en deux, vous ne pouvez pas isoler « le menu n’apparaît pas », « il est caché » ou « il apparaît deux fois ».
Cet article s’adresse aux informaticiens des PME et aux développeurs Windows qui entretiennent des applications métier. Il relie, en un seul tableau, la structure à trois couches de l’association de fichiers, les précautions des extensions de shell classiques, la façon de viser le nouveau menu contextuel de Windows 11, ainsi que l’enregistrement, le nettoyage et le dépannage côté installateur.
1. La conclusion d’abord
- Le fondement du menu contextuel et de l’association de fichiers est la structure de registre à trois couches « clé d’extension → ProgID → verb ». La clé d’extension est un pointeur vers un ProgID, le ProgID est la substance, et
shell\<verb>\commanden dessous contient la ligne de commande.1 - HKEY_CLASSES_ROOT (HKCR) n’est pas une ruche indépendante ; c’est une vue fusionnée de HKLM\Software\Classes et HKCU\Software\Classes. Écrivez l’enregistrement tous utilisateurs dans HKLM et l’enregistrement par utilisateur dans HKCU, et traitez HKCR en lecture seule.2
- L’application par défaut (celle qui s’ouvre au double-clic) est conçue pour être choisie par l’utilisateur, et un programme ne peut pas la voler. Le système d’exploitation protège le choix de l’utilisateur ; ce qu’un installateur peut faire, c’est s’enregistrer comme candidat.3
- Une extension de shell classique est une DLL COM in-process chargée dans l’Explorateur. Un plantage ou un retard de l’extension se propage à l’Explorateur tout entier (et aux autres applications qui utilisent le shell) ; un environnement 64 bits exige une DLL 64 bits ; et une implémentation en code managé n’est pas prise en charge.45
- Sous Windows 11 le menu contextuel s’est scindé en deux. Les seules commandes qui apparaissent dans le nouveau menu sont celles enregistrées avec IExplorerCommand plus une identité de paquet ; les extensions IContextMenu classiques sont déplacées vers l’ancien menu sous « Afficher plus d’options » (Maj+F10).67
- La voie officielle pour placer une commande personnalisée dans le nouveau menu est d’enregistrer une DLL native implémentant IExplorerCommand dans un manifeste MSIX (desktop4:FileExplorerContextMenus). Une application qui ne peut pas devenir MSIX peut recevoir l’identité seule avec un sparse package (MSIX avec emplacement externe).78
- Si tout ce que vous voulez est « ouvrir avec cette application », une association et un verb statique suffisent encore. Vous n’avez pas besoin d’une DLL d’extension de shell, et Microsoft elle-même dit clairement « choisir la méthode la plus simple qui satisfait les exigences (un verb statique) ».9
- Après un enregistrement ou un changement, notifiez avec SHChangeNotify(SHCNE_ASSOCCHANGED) ; à la désinstallation, supprimez le ProgID mais ne supprimez pas la valeur par défaut de la clé d’extension — c’est le guide officiel. L’intégration au shell inclut la conception du nettoyage.110
En une phrase : le monde des associations et des verbs est inchangé ; seule la façon dont le menu est montré s’est scindée en deux sous Windows 11. Nous parcourons cela depuis le fondement.
2. Comment fonctionne l’association de fichiers — la structure à trois couches clé d’extension → ProgID → verb
2.1. Lire la structure à trois couches à partir d’un exemple
Ce qui se passe lorsque vous double-cliquez un fichier d’une extension donnée est décidé par trois couches de clés de registre.1
HKEY_CLASSES_ROOT
.kmrpt ← (1) Clé d'extension
(Default) = KomuraSoft.Report.1 ← Un pointeur qui ne nomme que le ProgID
OpenWithProgids
KomuraSoft.Report.1 ← Un candidat sous « Ouvrir avec »
KomuraSoft.Report.1 ← (2) ProgID (la substance de l'association)
(Default) = Komura Report document
DefaultIcon
(Default) = "C:\Program Files\KomuraSoft\Report.exe",0
shell ← (3) Liste des verbs
open
command
(Default) = "C:\Program Files\KomuraSoft\Report.exe" "%1"
- (1) La clé d’extension (
.kmrpt) ne pointe que vers un nom de ProgID comme valeur par défaut. Y écrire une commande directement est une erreur. - (2) Le ProgID (
KomuraSoft.Report.1) est la substance de l’association ; il contient le nom d’affichage, l’icône et la liste des verbs. - (3) Un verb est une action telle que « ouvrir » ou « imprimer », et la valeur par défaut de
shell\open\commandest la ligne de commande réellement lancée.
Cette séparation permet de pointer plusieurs extensions (.kmrpt et .kmrpt-file, par exemple) vers le même ProgID, ou de changer le ProgID lors d’une mise à niveau de l’application.
flowchart TB
accTitle: La structure à trois couches de l'association de fichiers
accDescr: La clé d'extension est un pointeur dont la valeur par défaut nomme un ProgID ; le ProgID est la substance qui contient le nom d'affichage, l'icône et la liste des verbs ; et la valeur par défaut de command sous le verb est la ligne de commande réellement lancée
ext["Clé d'extension .kmrpt"] -->|nomme le ProgID comme défaut| pid["ProgID KomuraSoft.Report.1"]
pid --> vb["verb(open et autres sous shell)"]
vb --> cmd["valeur par défaut de command"]
cmd --> exe["Report.exe est lancé"]
pid -.-> attr["Contient aussi le nom d'affichage et DefaultIcon"]
Figure 1 : La clé d’extension est un pointeur, le ProgID est la substance, et le command du verb est la ligne de commande réellement lancée.
2.2. HKCR est une « vue fusionnée » — où vous écrivez change le sens
L’exemple ci-dessus est montré sous HKEY_CLASSES_ROOT (HKCR), mais HKCR n’est pas un emplacement de stockage physique ; c’est une vue fusionnée de HKLM\Software\Classes et HKCU\Software\Classes. Si la même clé existe des deux côtés, le côté HKCU l’emporte.2
flowchart TB
accTitle: HKCR est une vue fusionnée
accDescr: HKCR est HKLM et HKCU Classes superposés ; si la même clé existe des deux côtés, HKCU l'emporte ; écrivez l'enregistrement dans HKLM ou HKCU explicitement et traitez HKCR en lecture seule
hklm["HKLM\\Software\\Classes(tous les utilisateurs)"] --> hkcr["HKCR(vue fusionnée)"]
hkcu["HKCU\\Software\\Classes(par utilisateur)"] --> hkcr
hkcu -.-> win["Si la même clé existe, HKCU l'emporte"]
hkcr -.-> ro["Traitez-le en lecture seule(pour confirmation)"]
Figure 2 : HKCR est l’aspect de HKLM et HKCU Classes superposés ; nommez toujours l’un ou l’autre comme destination d’écriture.
| Destination d’écriture | Signification | Droits requis |
|---|---|---|
HKLM\Software\Classes |
Enregistrement commun à tous les utilisateurs | Administrateur |
HKCU\Software\Classes |
Enregistrement pour cet utilisateur seulement | Aucun |
Écrire directement dans HKCR |
Aiguillé selon l’endroit où la clé existante vit déjà | Selon le cas |
En pratique, la scission sûre est de toujours écrire l’enregistrement dans HKLM ou HKCU explicitement, et de traiter HKCR en lecture seule (pour confirmation). La relation avec la redirection de registre WOW64 mérite aussi d’être triée. Les données d’association directement sous HKLM\Software\Classes telles que les clés d’extension et les ProgID sont partagées entre les vues de registre 32 bits et 64 bits depuis Windows 7, donc un installateur 32 bits qui les écrit ne s’échappe pas du côté Wow6432Node. Certaines sous-clés d’enregistrement COM telles que Classes\CLSID, en revanche, sont redirigées, et lorsque vous enregistrez une extension de shell (COM in-process) la scission d’écriture 32 bits / 64 bits compte. Les détails sont dans « Redirection et virtualisation du registre 32 bits/64 bits — Wow6432Node et le problème de la « valeur écrite qui n’existe pas » ».
2.3. L’enregistrement côté application — App Paths, Applications, RegisteredApplications
Il existe aussi trois sortes d’enregistrement côté application, en paire avec le côté fichier (extension et ProgID).11
- App Paths (
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths) : enregistrement qui permet àShellExecuteExde lancer par le seul nom de fichier exécutable. Microsoft le recommande parce que vous n’avez pas à polluer la variable d’environnement PATH. - Applications (
HKCR\Applications\<app.exe>) : définit la façon par défaut d’ouvrir lorsqu’un fichier arbitraire est remis sous « Ouvrir avec », et le nom d’affichage de l’application (FriendlyAppName). - RegisteredApplications + Capabilities : déclare les extensions et types MIME que l’application peut traiter, et c’est l’enregistrement qui la fait apparaître comme candidat sur la page Paramètres des applications par défaut de Windows.
La plupart des consultations « notre application n’apparaît pas dans la liste des applications par défaut » sont des cas où le ProgID a été enregistré et cet enregistrement Capabilities a été omis.
flowchart TB
accTitle: Les trois sortes d'enregistrement côté application
accDescr: L'enregistrement côté application a trois sortes — App Paths, Applications et RegisteredApplications — responsables respectivement du lancement par le seul nom de fichier, de la façon par défaut d'ouvrir sous Ouvrir avec, et de l'apparition sur la page des applications par défaut
app["Enregistrement côté application"] --> ap["App Paths"]
app --> apps["Applications"]
app --> ra["RegisteredApplications"]
ap --> r1["Lancement par le seul nom de fichier"]
apps --> r2["Défaut sous Ouvrir avec"]
ra --> r3["Apparaît sur la page des applications par défaut"]
r3 -.-> cap["Une déclaration Capabilities est requise"]
Figure 3 : Il y a trois sortes d’enregistrement côté application, et apparaître comme candidat des applications par défaut exige un enregistrement Capabilities.
2.4. L’application par défaut appartient à l’utilisateur — protection UserChoice
Écrire un ProgID comme valeur par défaut de la clé d’extension ne suffit pas à en faire l’application par défaut. Le résultat du choix explicite de l’utilisateur sous « Ouvrir avec » et assimilés est conservé dans HKCU\...\Explorer\FileExts\<extension>\UserChoice, et la résolution d’association préfère ce côté.
Et le point important est que Windows ne prend pas en charge le changement programmatique de l’application par défaut. Les paramètres d’application par défaut sont conçus pour être faits par l’utilisateur via l’interface Paramètres du système ; les données UserChoice sont obscurcies, et un pilote-filtre (UCPD.sys) bloque les écritures depuis les applications. Dans un environnement géré, la stratégie de groupe / MDM est le moyen officiel.3
Que des outils tels que SetUserFTA, qui « imitent le hachage et le réécrivent », aient été utilisés est l’autre face de cette protection. Ce que vous devez mettre dans l’installateur d’une application interne n’est pas de voler la valeur par défaut, mais les trois (a) enregistrement correct du ProgID et des verbs, (b) s’ajouter à OpenWithProgIds, et (c) si besoin, orienter vers la page Paramètres.
flowchart TB
accTitle: Résolution de l'application par défaut et protection UserChoice
accDescr: Le résultat d'un choix explicite de l'utilisateur est conservé dans UserChoice et préféré dans la résolution d'association ; UCPD.sys bloque les réécritures depuis les applications, donc ce qu'un installateur peut faire est de s'enregistrer comme candidat et d'orienter vers la page Paramètres
uc["UserChoice(le choix de l'utilisateur)"] -->|préféré| res["Résolution d'association"]
ext["Valeur par défaut de la clé d'extension"] --> res
wr["Réécriture depuis une application"] -.->|UCPD.sys le bloque| uc
res ~~~ inst["Le travail de l'installateur"]
inst --> a1["Enregistrer le ProgID et les verbs"]
inst --> a2["Ajouter à OpenWithProgIds"]
inst --> a3["Orienter vers la page Paramètres"]
Figure 4 : La résolution d’association préfère le choix de l’utilisateur (UserChoice), et le système d’exploitation le protège des réécritures par les applications.
3. Les verbs autres que « Ouvrir » — print, edit, runas, verbs personnalisés
Un verb n’est pas seulement open. Les verbs standard dont le système d’exploitation connaît le sens incluent edit, print, play et preview ainsi que open, et un verb standard reçoit automatiquement un nom d’affichage qui suit les paramètres régionaux du système. Le verb par défaut utilisé au double-clic est décidé dans l’ordre : valeur par défaut de la clé shell → premier verb dans le registre → open → openwith.12
flowchart TB
accTitle: Ordre dans lequel le verb par défaut est décidé
accDescr: Le verb par défaut utilisé au double-clic est le premier trouvé dans l'ordre valeur par défaut de la clé shell, premier verb dans le registre, open, openwith
s1["valeur par défaut de la clé shell"] -->|si aucune| s2["Premier verb dans le registre"]
s2 -->|si aucun| s3["open"]
s3 -->|si aucun| s4["openwith"]
Figure 5 : Le verb par défaut au double-clic est le premier trouvé dans cet ordre.
Lorsque vous voulez ajouter votre propre action, enregistrez un verb personnalisé.
KomuraSoft.Report.1
shell
open
command
(Default) = "C:\Program Files\KomuraSoft\Report.exe" "%1"
print
command
(Default) = "C:\Program Files\KomuraSoft\Report.exe" /print "%1"
verify ← verb personnalisé
(Default) = Verify report (&V) ← nom d'affichage du menu
command
(Default) = "C:\Program Files\KomuraSoft\Report.exe" /verify "%1"
Trois petits faits utiles à connaître.
- Enregistrez un verb nommé runas et vous définissez un lancement en élévation équivalent à « Exécuter en tant qu’administrateur », également utilisé lorsqu’une API de la famille
ShellExecutespécifierunas. - Placez une valeur vide nommée
Extendedsur la clé du verb et il devient un verb étendu affiché seulement lorsque vous Maj+clic droit. Pratique pour cacher une opération dangereuse rarement utilisée.12 - Certaines associations d’applications plus anciennes ont encore une configuration qui envoie un document dans un processus existant avec DDE (la clé
ddeexec), mais lancer un verb via DDE est déjà un héritage Deprecated. Il n’y a aucune raison de l’écrire à neuf.12
Un autre accident fréquent est les guillemets sur la ligne de commande. Si un élément de la chaîne de commande peut contenir un espace, vous devez l’envelopper de guillemets. Cela s’applique bien sûr à un chemin EXE tel que C:\Program Files\..., et %1 (le chemin du fichier sélectionné) doit toujours s’écrire "%1". Vous ne pouvez pas garantir qu’un chemin de fichier utilisateur ne contient pas d’espace. Un My Program.exe non quoté est interprété comme « lancer My avec l’argument Program.exe ».13
flowchart TB
accTitle: L'accident des guillemets sur la ligne de commande
accDescr: Une commande non quotée est coupée à l'espace et mal interprétée comme lançant My avec l'argument Program.exe, donc un chemin EXE qui peut contenir un espace et %1, qui représente le chemin du fichier sélectionné, doivent toujours être enveloppés de guillemets
c1["Commande non quotée"] -->|coupée à l'espace| bad["Mal interprétée comme lançant un autre EXE"]
c2["Commande quotée"] --> good["Lance comme prévu"]
c2 -.-> q1["Enveloppez le chemin EXE de guillemets"]
q1 -.-> q2["Enveloppez toujours %1 de guillemets aussi"]
Figure 6 : Une commande non quotée est mal coupée à un espace, donc enveloppez toujours le chemin EXE et %1 de guillemets.
Le mécanisme registre-seul jusqu’ici (un verb statique) peut se réaliser sans écrire une seule DLL, et il ne risque pas de rendre l’Explorateur instable. Microsoft elle-même répète « avant d’écrire une extension de shell, demandez-vous si le verb statique le plus simple qui satisfait les exigences suffira ».9
4. Extensions de shell classiques — une DLL qui s’exécute dans l’Explorateur
4.1. Types d’extension de shell
Les exigences qu’un verb statique ne peut pas satisfaire — « changer le menu dynamiquement selon la sélection », « remplacer l’icône ou la feuille de propriétés » — utilisent un gestionnaire d’extension de shell. Les types représentatifs sont les suivants.4
| Gestionnaire | Interface principale | Ce qu’il peut faire |
|---|---|---|
| Gestionnaire de menu contextuel | IContextMenu + IShellExtInit | Ajouter et contrôler dynamiquement des éléments de menu |
| Gestionnaire d’icône / superposition d’icône | IExtractIcon / IShellIconOverlayIdentifier | Icône par fichier et superposition |
| Gestionnaire de feuille de propriétés | IShellPropSheetExt | Ajouter un onglet à la feuille de propriétés |
| Miniature / infobulle | IThumbnailProvider / IQueryInfo | Vue miniature et description au survol |
| Gestionnaire glisser-déposer / copy-hook | IDropTarget / ICopyHook | Intervenir au dépôt ou à la copie/déplacement |
Tous sont implémentés comme classes COM et enregistrés dans le registre par CLSID. L’idée de COM elle-même est couverte dans « Qu’est-ce que COM / ActiveX / OCX ? - Différences et relations expliquées ensemble ».
4.2. Ce que signifie être un serveur COM in-process
L’essence d’une extension de shell classique est qu’elle est un serveur COM in-process (DLL) chargé dans l’Explorateur (ou dans toute application qui a ouvert une boîte de dialogue de fichiers commune). Toutes les précautions en découlent.4
- Si l’extension plante, l’Explorateur est emporté avec elle. Si elle se fige, un clic droit se fige pendant plusieurs secondes. Les dégâts ne se limitent pas à l’Explorateur ; ils atteignent toute application qui a affiché une boîte de dialogue d’ouverture de fichier.
- La construction du menu se fait sur le thread d’interface, donc vous ne devez pas faire de travail lent tel qu’un accès réseau ou des E/S de fichiers au moment de l’affichage du menu.
- Enregistrez le modèle de threading comme
Apartmenten règle.
flowchart TB
accTitle: Structure des dommages collatéraux d'une extension in-process
accDescr: Une DLL d'extension de shell est chargée non seulement dans l'Explorateur mais aussi dans le processus de toute application qui a ouvert une boîte de dialogue de fichiers, donc un plantage ou un gel de l'extension se propage à tout le processus hôte
dll["DLL d'extension de shell"] -->|chargée in-process| exp["Explorateur"]
dll -->|chargée in-process| any["Toute application qui ouvre une boîte de dialogue"]
exp --> dmg["Un plantage ou un gel se propage"]
any --> dmg
dmg -.-> rule["Ne pas faire de travail lent à l'affichage"]
Figure 7 : La DLL d’extension s’exécute dans le processus hôte, donc un plantage ou un gel se propage à l’hôte tout entier.
Enquêter une consultation telle que « l’Explorateur se fige lorsque j’ouvre un dossier particulier » ou « un clic droit prend cinq secondes » et il n’est pas rare que la cause soit une extension de shell tierce plutôt que l’application interne. Les méthodes d’isolation sont au chapitre 8.
4.3. Aligner la bitsité — un environnement 64 bits exige une DLL 64 bits
Une DLL in-process doit correspondre à la bitsité du processus qui la charge. L’Explorateur sous Windows 64 bits est un processus 64 bits, donc une DLL d’extension de shell compilée seulement en 32 bits n’est jamais chargée et n’apparaît jamais du tout dans le menu. Il n’y a pas non plus d’erreur, donc c’est une cause classique de « je l’ai enregistrée mais elle n’apparaît pas ». Combiner un corps d’application 32 bits avec une DLL d’extension de shell 64 bits est une configuration légitime, mais il faut surveiller le fait que l’enregistrement COM se scinde par bitsité (Wow6432Node). Lancer depuis le command d’un verb est un EXE en processus séparé, donc il n’est pas soumis à cette contrainte (le laisser en EXE 32 bits convient).
flowchart TB
accTitle: Aligner la bitsité d'une DLL d'extension de shell
accDescr: La seule DLL d'extension de shell qu'un Explorateur 64 bits peut charger est une DLL 64 bits ; une DLL seulement 32 bits n'apparaît jamais dans le menu et ne produit aucune erreur ; un EXE lancé depuis un command de verb est un processus séparé et n'est pas soumis à la contrainte
exp["Explorateur 64 bits"] -->|peut charger| d64["DLL d'extension de shell 64 bits"]
exp -.->|ne peut pas charger| d32["DLL seulement 32 bits"]
d32 -.-> sym["N'apparaît pas dans le menu, sans erreur"]
exe["EXE lancé depuis un verb"] -->|processus séparé| ok32["Convient laissé en 32 bits"]
Figure 8 : La seule DLL chargée dans l’Explorateur 64 bits est une DLL 64 bits ; un EXE lancé depuis un verb n’est pas soumis à cette contrainte.
4.4. Pourquoi il ne faut pas l’écrire en code managé
On me pose souvent la question « puis-je écrire une extension de shell en C# », mais Microsoft a dit clairement que rédiger une extension de shell in-process en code managé (.NET) n’est pas recommandé et est hors support.5
La raison est la nature de l’extension chargée dans un processus arbitraire. Les collisions de version du CLR (surtout en dessous de .NET Framework 4), le problème du CLR qui réentre dans la boucle de messages en attendant un verrou, et la durée de vie d’objet non déterministe du ramasse-miettes qui heurte le contrat de comptage de références de COM sont des raisons structurelles pour lesquelles l’application hôte devient instable. Certains points ont été atténués sur .NET Framework 4 et ultérieur et sur le .NET moderne, mais la position officielle n’a pas changé.
Le guide pratique est simple. Écrivez une extension in-process en C++ natif. Si vous voulez utiliser du code managé, faites-en un EXE ordinaire lancé depuis le command d’un verb, ou une extension hors processus qui s’exécute dans un processus séparé (un gestionnaire d’aperçu et assimilés).5
flowchart TB
accTitle: Juger si le code managé est autorisé
accDescr: Une extension in-process qui s'exécute dans l'Explorateur s'écrit en C++ natif en règle ; si vous voulez du code managé, faites-en un EXE ordinaire lancé depuis un command de verb ou une extension hors processus qui s'exécute dans un processus séparé
q1{"S'exécute in-process ?"} -->|oui| cpp["Écrivez-la en C++ natif"]
q1 -->|non| mg["Le code managé convient"]
cpp -.-> why["Risque CLR / réentrance rend l'hôte instable"]
mg --> e1["EXE lancé par un verb"]
mg --> e2["Aperçu hors processus"]
Figure 9 : Une extension in-process est du C++ natif en règle ; le code managé se limite à une configuration qui s’exécute dans un processus séparé.
5. Le nouveau menu contextuel de Windows 11 — le menu scindé en deux
5.1. Ce qui s’est passé
Windows 11 a rafraîchi le menu contextuel de l’Explorateur de fichiers. Couper, copier et assimilés sont devenus une rangée d’icônes en haut ; « Ouvrir » et « Ouvrir avec » ont été groupés en haut ; et les commandes qu’une application ajoute sont groupées sous les commandes standard du shell. Lorsqu’une application ajoute plusieurs commandes, elles sont rassemblées dans un menu volant (sous-menu) portant le nom de l’application.6
Et le point crucial est celui-ci. Les extensions de shell classiques fondées sur IContextMenu n’ont pas été supprimées ; elles ont été déplacées vers le côté ancien menu qui s’ouvre avec « Afficher plus d’options » (Maj+F10) et charge le menu de Windows 10 tel quel.6 L’identité de la consultation d’ouverture « le menu a été caché » est cette scission.
flowchart TB
accTitle: Le menu contextuel que Windows 11 a scindé en deux
accDescr: Ce qui s'ouvre d'abord au clic droit est le nouveau menu ; les seules commandes qui y apparaissent sont celles enregistrées avec IExplorerCommand et une identité de paquet ; les extensions IContextMenu classiques sont déplacées vers l'ancien menu ouvert par Afficher plus d'options
rc["Clic droit sur un fichier"] --> newm["Nouveau menu(Windows 11)"]
newm --> newi["Commandes IExplorerCommand + identité"]
newm -->|Afficher plus d'options Maj+F10| oldm["Ancien menu(le menu Windows 10)"]
oldm --> oldi["Extensions IContextMenu classiques"]
newi -.-> fly["Plusieurs commandes sont rassemblées dans un menu volant"]
Figure 10 : Les seules commandes qui apparaissent dans le nouveau menu sont les commandes IExplorerCommand + identité ; les extensions classiques sont déplacées vers le côté ancien menu.
5.2. La voie officielle vers le nouveau menu — IExplorerCommand + enregistrement dans le manifeste
Il y a une façon de placer une commande personnalisée dans le nouveau menu. Préparez une DLL native qui implémente l’interface IExplorerCommand, et déclarez le serveur COM et l’extension de menu contextuel dans un manifeste de paquet MSIX.7
<!-- Manifeste de paquet (extrait) -->
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:SurrogateServer DisplayName="Komura commands">
<com:Class Id="01234567-89AB-CDEF-0123-456789ABCDEF"
Path="KomuraCommand.dll" ThreadingModel="STA" />
</com:SurrogateServer>
</com:ComServer>
</com:Extension>
<desktop4:Extension Category="windows.fileExplorerContextMenus">
<desktop4:FileExplorerContextMenus>
<desktop5:ItemType Type=".kmrpt">
<desktop5:Verb Id="VerifyReport"
Clsid="01234567-89AB-CDEF-0123-456789ABCDEF" />
</desktop5:ItemType>
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>
Le Type de ItemType peut spécifier une extension particulière, ou * (tous les fichiers), Directory (dossiers), ou Directory\Background (un arrière-plan de dossier). Alignez la DLL sur l’architecture de l’Explorateur (64 bits / ARM64).7
IExplorerCommand elle-même est une interface qui existe depuis l’ère Windows 7 ; vous implémentez le titre (GetTitle), l’icône (GetIcon), l’état activé / désactivé / masqué (GetState), et l’exécution (Invoke). Les méthodes sont appelées depuis le thread d’interface, donc l’accès aux ressources réseau est interdit, et les méthodes de construction du menu doivent revenir rapidement. Faites le travail lourd après Invoke.147
flowchart TB
accTitle: Structure de manifeste d'un enregistrement dans le nouveau menu
accDescr: La déclaration de serveur COM du manifeste MSIX mappe un CLSID vers une DLL, et la déclaration d'extension de menu contextuel lie la cible et l'implémentation avec ItemType et Verb, de sorte qu'une commande personnalisée apparaît dans le nouveau menu
man["Manifeste MSIX"] --> com["Déclaration de serveur COM"]
man --> ctx["Déclaration d'extension de menu"]
com -->|mappe le CLSID vers la DLL| impl["DLL d'implémentation IExplorerCommand"]
ctx -->|spécifie avec ItemType et Verb| impl
impl --> shown["La commande apparaît dans le nouveau menu"]
ctx -.-> tgt["La cible est une extension, tous les fichiers, et assimilés"]
Figure 11 : Deux déclarations dans le manifeste lient la DLL d’implémentation à la cible, et la commande apparaît dans le nouveau menu.
5.3. L’option pour une application non empaquetée — obtenir l’identité seule avec un sparse package
La trappe de sortie lorsque « notre application ne peut être distribuée que comme MSI ; MSIX est impossible » est un sparse package (MSIX avec emplacement externe). Vous signez un petit MSIX qui n’est qu’un manifeste, sans corps d’application, et vous l’enregistrez à la fin de l’installateur existant. L’application acquiert alors une identité de paquet, et l’enregistrement de manifeste ci-dessus (= apparition dans le nouveau menu) devient possible. Disponible à partir de Windows 10 version 2004, le paquet a besoin d’une signature avec un certificat de confiance sur la machine cible.8
flowchart TB
accTitle: Le flux d'obtention de l'identité avec un sparse package
accDescr: Après que l'installateur existant a placé le corps de l'application, enregistrer un sparse package de manifeste seul avec un emplacement externe donne à l'application une identité de paquet et rend possible l'enregistrement de manifeste du nouveau menu
inst["Installateur existant"] --> files["Placer le corps de l'application"]
sp["Sparse package"] -.-> only["Manifeste seulement, pas de corps"]
files --> reg["Enregistrer avec un emplacement externe"]
sp --> reg
reg --> id["Acquérir l'identité de paquet"]
id --> ok["L'enregistrement du nouveau menu devient possible"]
sp -.-> sign["Une signature de confiance est requise"]
Figure 12 : Enregistrez un sparse package qui ne contient pas de corps, avec un emplacement externe, et l’application acquiert une identité de paquet.
Le plus grand avantage est que vous n’avez pas à remplacer l’installateur ; c’est la réponse réaliste pour une application qui a déjà un actif d’installateur MSI/EXE. Pour une comparaison avec un passage complet à MSIX, voir aussi « Choisir une méthode de distribution d’application Windows - MSI/MSIX/ClickOnce/xcopy/Updater personnalisé ».
5.4. Comment les verbs d’association apparaissent dans le nouveau menu
Un point facile à mal comprendre : les associations des chapitres 2 et 3 (ProgID et verb) sont encore vivantes dans le nouveau menu. Le verb par défaut au double-clic, « Ouvrir », et les candidats « Ouvrir avec » sont résolus depuis l’association et affichés en haut du nouveau menu. Donc si tout ce que vous voulez est « pouvoir ouvrir avec cette application », Windows 11 n’a besoin d’aucun travail supplémentaire. En revanche, une association n’est pas une extension de menu à usage général, donc si vous voulez une commande personnalisée arbitraire à la première couche du nouveau menu, vous avez besoin d’IExplorerCommand plus l’identité — c’est la répartition des rôles.7
flowchart TB
accTitle: La répartition des rôles entre associations et nouveau menu
accDescr: Une association ProgID-et-verb est encore utilisée dans le nouveau menu pour résoudre le verb par défaut, Ouvrir et Ouvrir avec, et est affichée en haut ; placer une commande personnalisée arbitraire à la première couche du nouveau menu exige IExplorerCommand et l'identité
assoc["Assoc.(ProgID + verb)"] --> sol["Résoudre défaut / Ouvrir"]
sol --> top["Haut du nouveau menu"]
assoc -.-> keep["Pas de travail extra sous Win11"]
cmd["Une commande personnalisée"] --> need["IExplorerCommand+identité"]
need --> first["Première couche du nouveau menu"]
Figure 13 : Les associations gèrent encore la résolution de la famille « Ouvrir » dans le nouveau menu ; seule une commande personnalisée exige IExplorerCommand plus l’identité.
6. Un tableau de décision pratique — laquelle des trois options prendre
Nous organisons ce que nous avons jusqu’ici en un choix pratique à trois voies.
| Ce que vous voulez accomplir | Moyen recommandé | Aspect sous Windows 11 | Travail et coût requis |
|---|---|---|---|
| (a) Lancer l’application interne au double-clic ou « Ouvrir » | Association + verb statique (enregistrement de registre seulement) | Intégré à « Ouvrir » et « Ouvrir avec » dans le nouveau menu | Enregistrement de registre de l’installateur seulement. Pas de DLL, pas d’exigence de signature extra |
| (b) Placer une commande personnalisée pour le fichier/dossier sélectionné dans le nouveau menu | Implémentation IExplorerCommand + enregistrement de manifeste MSIX. Une application non empaquetée reçoit l’identité avec un sparse package | Première couche du nouveau menu (plusieurs commandes rassemblées dans un menu volant au nom de l’application) | DLL C++ native + identité de paquet + signature de code |
| (c) Continuer à utiliser une extension IContextMenu classique existante | La garder telle quelle pour l’instant (ne pas la choisir pour un nouveau développement) | Côté ancien menu seulement, sous « Afficher plus d’options » (Maj+F10) | Maintenir une compilation 64 bits et l’enregistrement COM. Planifier un passage ultérieur à (b) |
Il y a deux points de jugement. Premier, n’amenez pas (b) ou (c) pour une exigence que (a) satisfera. Dès que vous écrivez une extension de shell vous prenez la responsabilité de la stabilité de l’Explorateur. Second, (c) n’est que « pas cassé » ; comme expérience utilisateur elle reste un cran plus mauvaise. Plus une commande est utilisée fréquemment dans l’exploitation quotidienne, plus le retour d’un passage à (b) est grand.
flowchart TB
accTitle: Comment choisir parmi les trois options
accDescr: Si tout ce que vous voulez est le lancement au double-clic ou Ouvrir, une association et un verb statique suffisent ; pour placer une commande personnalisée dans le nouveau menu utilisez IExplorerCommand et l'enregistrement de manifeste MSIX ; si vous ne pouvez pas devenir MSIX, accordez l'identité avec un sparse package ; gardez une extension IContextMenu classique existante du côté ancien menu pour l'instant
q1{"Ouvrir suffit ?"} -->|oui| pa["Assoc. + verb statique"]
q1 -->|non| q2{"Personnalisé dans le nouveau menu ?"}
q2 -->|oui| q3{"Pouvez-vous devenir MSIX ?"}
q3 -->|oui| pb1["IExplorerCommand+MSIX"]
q3 -->|non| pb2["Identité sparse-pkg"]
q2 -->|non| pc["Garder le classique pour l'instant"]
pc -.-> old["Côté ancien menu seulement"]
pa -.-> dllfree["Pas de DLL, petit risque"]
Figure 14 : Choisissez parmi un verb statique, IExplorerCommand plus l’identité, et garder le classique, selon l’exigence.
7. Déploiement et enregistrement en pratique — installateur, sparse package, nettoyage
7.1. HKLM ou HKCU
Alignez-le sur la forme de l’installateur. Tous utilisateurs (placé sous Program Files, droits d’administrateur) est HKLM\Software\Classes ; installation par utilisateur (sans élévation) est HKCU\Software\Classes. Mélangez-les et vous produisez le genre de demande « A peut l’ouvrir mais B ne le peut pas ». Pour une extension de shell qui implique un enregistrement CLSID, Reg-Free COM — qui supprime le besoin d’enregistrement de registre lui-même — est une option valable pour l’usage COM dans l’application, mais elle ne peut pas s’appliquer à une extension de shell que l’Explorateur charge, donc vous avez besoin de l’enregistrement frontal (« Qu’est-ce que Reg-Free COM - Utiliser COM sans enregistrement »).
7.2. Après un changement, notifiez — SHChangeNotify
Après avoir enregistré, changé ou supprimé une association, notifiez l’événement SHCNE_ASSOCCHANGED avec SHChangeNotify. Sautez cela et l’Explorateur peut ne pas remarquer le changement jusqu’à un redémarrage.110
// Appeler une fois après avoir changé les associations, p. ex. depuis une action personnalisée d'installateur
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);
7.3. Enregistrer et retirer un sparse package
Enregistrer et retirer un sparse package est le travail de l’installateur. Enregistrez après avoir placé les fichiers ; retirez avant de supprimer les fichiers.8
# À l'installation : après avoir placé les fichiers, enregistrer le dossier d'installation comme emplacement externe
Add-AppxPackage -Path "C:\Program Files\KomuraSoft\KomuraReport.identity.msix" `
-ExternalLocation "C:\Program Files\KomuraSoft"
# À la désinstallation : retirer l'enregistrement du paquet avant de supprimer les fichiers
Remove-AppxPackage <package full name>
Un point à surveiller : Add-AppxPackage enregistre pour l’utilisateur qui l’a exécuté. Si vous l’appelez depuis une action personnalisée d’un MSI par machine, s’exécuter sous LocalSystem n’accorde pas l’identité à l’utilisateur qui a installé, donc vous le configurez pour s’exécuter sous usurpation d’utilisateur. Même alors, l’enregistrement sous usurpation est seulement pour l’utilisateur qui a exécuté cette installation. Sur un PC utilisé par plusieurs utilisateurs, les autres utilisateurs et les utilisateurs créés plus tard n’ont pas d’identité de paquet, et la commande n’apparaît pas dans le nouveau menu. Pour que chaque utilisateur l’utilise, fournissez un mécanisme tel que vérifier votre propre enregistrement de paquet au premier lancement et enregistrer s’il manque (enregistrement par utilisateur), et incluez le retrait de chaque utilisateur qui a un enregistrement dans le plan de désinstallation. Refléter un enregistrement de manifeste peut aussi exiger un redémarrage de l’Explorateur (ou une déconnexion).7
flowchart TB
accTitle: Ordre d'enregistrement et de retrait d'un sparse package
accDescr: À l'installation enregistrez le sparse package après avoir placé les fichiers ; à la désinstallation retirez l'enregistrement avant de supprimer les fichiers ; surveillez le fait que l'enregistrement n'est effectif que pour l'utilisateur qui l'a exécuté
i1["Installation"] --> i2["Placer les fichiers"]
i2 --> i3["Enregistrer le sparse package"]
u1["Désinstallation"] --> u2["Retirer l'enregistrement du paquet"]
u2 --> u3["Supprimer les fichiers"]
i3 -.-> pu["L'enregistrement n'est effectif que pour l'utilisateur en cours"]
Figure 15 : Enregistrez après avoir placé les fichiers, retirez avant de les supprimer, et surveillez le fait que l’enregistrement est par utilisateur en cours.
7.4. Nettoyage à la désinstallation — quoi supprimer et quoi laisser
Le nettoyage à la désinstallation a une ligne de guide officiel claire.1
- Supprimer : toute la clé ProgID interne, l’enregistrement Capabilities/RegisteredApplications, l’enregistrement CLSID de l’extension de shell, le sparse package (Remove-AppxPackage).
- Laisser : la valeur par défaut de la clé d’extension (
.kmrpt). La recommandation officielle est de ne pas la supprimer même si elle pointe encore vers le ProgID interne. Juger après installation si une autre application a pris la valeur par défaut est difficile, et Windows ignore simplement un ProgID de valeur par défaut qui n’est pas enregistré, donc le laisser ne fait pas de mal réel. - Appelez aussi SHChangeNotify(SHCNE_ASSOCCHANGED) à la fin du nettoyage.
La plupart des problèmes « nous avons désinstallé et des restes apparaissent encore dans le menu » sont une fuite dans cette conception de nettoyage.
flowchart TB
accTitle: Conception du nettoyage à la désinstallation
accDescr: À la désinstallation vous supprimez la clé ProgID interne, l'enregistrement CLSID et le sparse package ; laissez la valeur par défaut de la clé d'extension parce qu'un ProgID non enregistré est ignoré ; notifiez le changement avec SHChangeNotify à la fin du nettoyage
un["Désinstallation"] --> del["Supprimer"]
un --> keep["Laisser"]
del --> d1["Enregistrement ProgID et CLSID"]
del --> d2["Sparse package"]
keep --> k1["Valeur par défaut de la clé d'extension"]
k1 -.-> why["Un ProgID non enregistré est ignoré"]
d1 --> fin["Notifier avec SHChangeNotify à la fin"]
k1 --> fin
Figure 16 : Supprimez l’enregistrement interne, laissez la valeur par défaut de la clé d’extension, et notifiez le changement à la fin du nettoyage.
8. Dépannage — manquant, en double, lourd
8.1. Il n’apparaît pas dans le menu
Isolez dans cet ordre.
- Quel menu vous regardez : un enregistrement de style classique n’apparaît que du côté ancien menu sous Maj+F10. Vérifiez les deux d’abord.
- Bitsité : une DLL d’extension de shell seulement 32 bits n’est pas chargée dans l’Explorateur 64 bits (section 4.3).
- Destination d’enregistrement : HKLM/HKCU, une confusion Wow6432Node. Confirmez la clé réelle avec
reg query. - Enregistrement de paquet : pour le nouveau menu, confirmez la présence avec
Get-AppxPackage, la confiance du certificat de signature, et le chemin-ExternalLocation, puis redémarrez l’Explorateur.7 - Notification oubliée : si SHChangeNotify a été oublié, vous pouvez le dire selon qu’un redémarrage de l’Explorateur le fait prendre effet.
flowchart TB
accTitle: Ordre d'isolation lorsqu'il n'apparaît pas dans le menu
accDescr: Commencez par confirmer quel menu vous regardez, puis isolez la bitsité de la DLL, la destination d'enregistrement de registre, l'enregistrement de paquet et la signature, et une notification SHChangeNotify oubliée, dans cet ordre
c1["Confirmer quel menu, ancien ou nouveau"] --> c2["Confirmer la bitsité de la DLL"]
c2 --> c3["Confirmer la destination d'enregistrement HKLM et HKCU"]
c3 --> c4["Confirmer l'enregistrement de paquet et la signature"]
c4 --> c5["Dire une notification oubliée en redémarrant"]
Figure 17 : Lorsqu’il « n’apparaît pas », isolez dans l’ordre menu que vous regardez, bitsité, destination d’enregistrement, enregistrement de paquet, notification oubliée.
8.2. Il apparaît deux fois, ou ne disparaît pas
Les causes typiques sont la coexistence d’un enregistrement de registre classique et d’un enregistrement de manifeste, une fuite dans le nettoyage de désinstallation (section 7.4), ou des restes d’un ProgID d’ancienne version. S’il apparaît deux fois seulement dans l’ancien menu, pensez restes ; s’il apparaît sur l’ancien et le nouveau, pensez coexistence.
flowchart TB
accTitle: Isoler un double affichage
accDescr: Deux fois seulement dans l'ancien menu pointe vers des restes tels qu'une fuite de nettoyage ou un ancien ProgID ; deux fois sur l'ancien et le nouveau pointe vers la coexistence d'un enregistrement de registre classique et d'un enregistrement de manifeste
q{"Sur lequel apparaît-il deux fois ?"} -->|ancien menu seulement| zan["Restes"]
q -->|ancien et nouveau| hei["Coexistence"]
zan -.-> z1["Fuite de nettoyage ou un ancien ProgID laissé"]
hei -.-> h1["Enregistrement de registre classique coexistant avec le nouvel enregistrement"]
Figure 18 : Deux fois seulement dans l’ancien menu pointe vers des restes ; deux fois sur l’ancien et le nouveau pointe vers la coexistence.
8.3. L’Explorateur est lourd ou plante
Lorsqu’un clic droit est lent, ou qu’un dossier particulier plante, dressez d’abord l’inventaire des extensions de shell installées. Listez les extensions non Microsoft avec un outil tel que ShellExView de NirSoft, désactivez temporairement les suspectes, et identifiez la DLL fautive par recherche dichotomique. Sur un plantage, le « Faulting module » de l’Observateur d’événements est aussi un indice. Si l’extension interne était la cause, suspectez des E/S synchrones ou un accès réseau sur le chemin de construction du menu (sections 4.2 et 5.2).
flowchart TB
accTitle: Identifier la DLL fautive lorsqu'il est lourd ou plante
accDescr: Listez les extensions de shell non Microsoft dans ShellExView, désactivez temporairement les suspectes et identifiez la DLL fautive par recherche dichotomique ; sur un plantage, le faulting module de l'Observateur d'événements est aussi un indice
s1["Inventorier les extensions de shell"] --> s2["Lister les non Microsoft"]
s2 --> s3["Désactiver temporairement et recherche dichotomique"]
s3 --> s4["Identifier la DLL fautive"]
crash["Sur un plantage"] -.-> ev["Vérifier le faulting module"]
ev -.-> s4
Figure 19 : Désactivez temporairement les extensions non Microsoft et faites une recherche dichotomique ; sur un plantage, utilisez aussi l’Observateur d’événements.
8.4. Windows Sandbox est commode pour la vérification
La vérification de l’intégration au shell repose sur confirmer « installer sur un environnement propre → opérer → désinstaller → restes zéro ». Pratique ici est Windows Sandbox (Pro/Enterprise/Education) : chaque lancement fait apparaître un Windows jetable tout neuf en quelques secondes, donc vous pouvez exécuter les tests d’enregistrement et de nettoyage de l’installateur autant de fois que vous voulez. Fermez-le et tout disparaît, donc il convient aussi à l’enquête de registre restant.15
9. Résumé
- L’association de fichiers est la structure à trois couches « clé d’extension → ProgID → verb », et HKCR est une vue fusionnée de HKLM/HKCU Classes. Nommez la destination d’écriture explicitement, et enveloppez toujours
%1de guillemets. - L’application par défaut est conçue pour être choisie par l’utilisateur et ne peut pas être changée depuis un programme. Le travail de l’installateur est de s’enregistrer correctement comme candidat.
- Une extension de shell classique est une DLL COM in-process chargée dans l’Explorateur. Un plantage ou un retard se propage à l’ensemble ; le 64 bits est requis ; le code managé n’est pas pris en charge ; l’implémentation en C++ natif est la règle.
- Sous Windows 11 le menu contextuel s’est scindé en deux. Placer une commande personnalisée dans le nouveau menu exige IExplorerCommand plus un manifeste MSIX ; IContextMenu classique est déplacé vers le côté « Afficher plus d’options ».
- Pour une application qui ne peut pas devenir MSIX, obtenir l’identité avec un sparse package (MSIX avec emplacement externe) est la réponse réaliste.
- Si tout ce que vous voulez est « ouvrir avec cette application », une association et un verb statique suffisent encore. Commencer par le moyen le plus simple est aussi le guide officiel.
- Après un enregistrement, un changement ou une suppression, notifiez avec SHChangeNotify ; à la désinstallation, supprimez le ProgID mais laissez la valeur par défaut de la clé d’extension. Windows Sandbox est commode pour la vérification.
Si un remplacement de PC Windows 11 vous a fait remarquer que « le menu a été caché », confirmez d’abord lequel de (a), (b) et (c) du tableau de décision du chapitre 6 c’est. Vous devriez pouvoir estimer l’échelle du travail sur place.
Articles connexes
- Qu’est-ce que COM / ActiveX / OCX ? - Différences et relations expliquées ensemble
- Qu’est-ce que Reg-Free COM - Utiliser COM sans enregistrement
- Redirection et virtualisation du registre 32 bits/64 bits — Wow6432Node et le problème de la « valeur écrite qui n’existe pas »
- Choisir une méthode de distribution d’application Windows - MSI/MSIX/ClickOnce/xcopy/Updater personnalisé
- Compatibilité descendante des interfaces DLL et COM — Tableau de décision : quels changements cassent les appelants
- Comment fonctionne la compatibilité des applications Windows — garder les anciennes applications en vie avec le mode de compatibilité, les shims et Compatibility Administrator
Domaines de conseil associés
KomuraSoft LLC traite la conception et l’implémentation de l’association de fichiers, des menus contextuels et des extensions de shell pour les applications métier ; le ciblage du nouveau menu contextuel de Windows 11 (passage à IExplorerCommand, introduction d’un sparse package) ; la revue de l’enregistrement et du nettoyage d’un installateur existant ; et l’investigation de la cause d’un Explorateur lourd ou qui plante. Il convient de commencer par décider quoi faire du « menu qui a été caché sous Afficher plus d’options ».
- Développement d’applications Windows
- Réutilisation et migration d’actifs existants
- Conseil technique et revue de conception
- Contact
Références
-
Microsoft Learn, File Types. Sur la structure d’une clé d’extension pointant vers un ProgID ; OpenWithProgIds ; la scission d’enregistrement entre HKLM/HKCU\Software\Classes ; l’appel de SHChangeNotify(SHCNE_ASSOCCHANGED) après un changement d’association ; et la suppression du ProgID à la désinstallation tout en laissant la valeur par défaut de la clé d’extension. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, HKEY_CLASSES_ROOT Key. Sur le fait que HKEY_CLASSES_ROOT est une vue fusionnée de HKLM\Software\Classes et HKCU\Software\Classes ; les définitions côté utilisateur ayant priorité sur celles côté machine ; et les règles d’aiguillage à l’écriture. ↩ ↩2
-
Microsoft Learn, Windows app defaults platform. Sur le fait que changer l’application par défaut est conçu pour n’être fait que via l’interface Paramètres du système ; les données de paramètres utilisateur étant obscurcies et protégées en écriture par un pilote-filtre (UCPD.sys) ; le changement fondé sur le registre n’étant pas pris en charge ; et l’usage de la stratégie de groupe / MDM dans un environnement géré. ↩ ↩2
-
Microsoft Learn, Working with Shell Extensions. Sur les types de gestionnaire d’extension de shell ; une extension étant une DLL COM in-process chargée dans l’Explorateur (et dans les processus qui hébergent le shell), de sorte qu’un plantage ou un gel se propage à l’Explorateur tout entier ; l’enregistrement avec ThreadingModel=Apartment ; et le fait de considérer une alternative plus simple avant une extension de shell. ↩ ↩2 ↩3
-
Microsoft Learn, Guidance for Implementing In-Process Extensions. Sur le fait que Microsoft ne recommande pas et ne prend pas en charge une implémentation d’extension de shell in-process en code managé ; les raisons incluant les collisions de version du CLR, la réentrance et la durée de vie d’objet non déterministe ; et le code managé étant acceptable pour une extension hors processus (un gestionnaire d’aperçu, ou un lancement depuis shell\verb\command). ↩ ↩2 ↩3
-
Windows Developer Blog, Extending the Context Menu and Share Dialog in Windows 11. Sur la conception du nouveau menu contextuel de Windows 11 ; l’extension via IExplorerCommand plus l’identité d’application ; le placement de « Ouvrir » et « Ouvrir avec » en haut ; le rassemblement de plusieurs commandes dans un menu volant au nom de l’application ; et les extensions IContextMenu classiques étant chargées comme le menu Windows 10 sous « Afficher plus d’options » (Maj+F10). ↩ ↩2 ↩3
-
Microsoft Learn, Add a File Explorer context menu command to a packaged desktop app. Sur le fait que l’enregistrement dans le nouveau menu contextuel de Windows 11 se fait avec une implémentation IExplorerCommand plus windows.comServer plus une déclaration de manifeste desktop4:FileExplorerContextMenus ; ItemType pouvant spécifier *, Directory ou Directory\Background ; l’alignement de l’architecture de la DLL ; le maintien de méthodes de construction de menu rapides ; la couverture d’une application non empaquetée avec un sparse package ; un redémarrage de l’Explorateur étant parfois requis pour que l’enregistrement prenne effet ; et une association de fichiers n’étant pas une extension de menu à usage général. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Microsoft Learn, Grant package identity by packaging with external location. Sur l’obtention d’une identité de paquet en enregistrant un paquet à emplacement externe (sparse package) sans changer l’installateur existant ; la disponibilité à partir de Windows 10 version 2004 ; et les fonctions Windows qui exigent l’identité (enregistrement de menu contextuel, notifications, et assimilés) devenant utilisables. ↩ ↩2 ↩3
-
Microsoft Learn, Choosing a Static or Dynamic Shortcut Menu Method. Sur le choix de la méthode de verb statique la plus simple qui satisfait les exigences ; IContextMenu étant le plus puissant mais aussi le plus complexe et classé du côté non recommandé ; et IExplorerCommand/IExplorerCommandState étant la méthode recommandée. ↩ ↩2
-
Microsoft Learn, SHChangeNotify function. Sur la façon de lever l’événement SHCNE_ASSOCCHANGED qui notifie le système d’un changement d’association de fichiers, et sur son usage pour que le shell remarque le changement. ↩ ↩2
-
Microsoft Learn, Application Registration. Sur le fait que l’enregistrement d’un exécutable via la sous-clé App Paths est recommandé ; le rôle de la sous-clé Applications ; l’enregistrement de verbs via SystemFileAssociations ; et la priorité du ProgID et des informations associées lorsque l’application par défaut change. ↩
-
Microsoft Learn, Verbs and File Associations. Sur le fait qu’un verb est une action aussi utilisée par ShellExecuteEx ; les éléments d’une chaîne de commande qui peuvent contenir un espace devant être enveloppés de guillemets, et “%1” s’écrivant toujours quoté ; et l’enregistrement d’une procédure par défaut sous HKCR\Applications. ↩
-
Microsoft Learn, IExplorerCommand interface. Sur la composition de méthodes de GetTitle, GetIcon, GetState, Invoke, EnumSubCommands, et assimilés ; les méthodes étant appelées sur le thread d’interface donc elles ne doivent pas communiquer avec des ressources réseau ; et la disponibilité à partir de Windows Vista. ↩
-
Microsoft Learn, Windows Sandbox. Sur le fait de pouvoir lancer un environnement Windows isolé et jetable en quelques secondes, tous les changements étant abandonnés lorsque vous le fermez, sa convenance pour les tests logiciels et la vérification d’installateur, et sa disponibilité sur Pro/Enterprise/Education. ↩
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
Comment fonctionnent le presse-papiers et le glisser-déposer — traiter correctement le transfert de données OLE dans les applications métier
Coller un tableau Excel et la mise en forme se défait ; fermer l'application source et vous ne pouvez plus coller — les deux viennent du ...
Externalisation et développement sur mesure d'une application Windows : ce qu'il faut clarifier avant de se lancer
Avant de confier l'externalisation ou le développement sur mesure d'une application Windows, voici les points à clarifier : révision d'un...
L'étrange amour d'un développeur, ou : comment j'ai appris à ne plus m'en faire et à aimer Windows
Windows est contraignant. Mais cette contrainte est aussi celle d'un système d'exploitation qui porte depuis des décennies le poids d'act...
Pourquoi Windows affiche « Windows a protégé votre PC »
Pourquoi le message SmartScreen apparaît lors de la distribution d'une application Windows : signature de code, certificats EV/OV, Azure ...
L'API du pool de threads Win32 — de la concurrence sans créer de threads, via CreateThreadpoolWork
Vous semez des appels CreateThread partout dans votre code natif ? Cet article explique l'API du pool de threads Win32 refondue sous Vist...
Sujets associés
Ces pages replacent le sujet dans un contexte plus large de services et de décisions.
Thèmes techniques Windows
Portail des sujets sur le développement Windows, l'analyse des incidents et la valorisation des actifs existants.
Migration ActiveX
Choisir de conserver, encapsuler ou remplacer des composants COM / ActiveX / OCX.
Services liés à ce sujet
Cet article est directement lié aux services suivants.
Développement d'applications Windows
Applications métier, intégration d'équipements et outils de communication, des besoins au développement.
Maintenance et modernisation de logiciels Windows
Ajouts de fonctions, maintenance et modernisation progressive de logiciels Windows existants.
Questions fréquentes
Questions souvent posées lors d’une consultation sur le sujet de cet article.
- Pourquoi l'élément de menu contextuel de notre application n'apparaît-il sous Windows 11 que dans « Afficher plus d'options » ?
- Parce que sous Windows 11 le menu contextuel de l'Explorateur s'est scindé en deux couches, ancienne et nouvelle. Seules les commandes qui implémentent l'interface IExplorerCommand et sont enregistrées dans le manifeste d'un paquet MSIX (= qui ont une identité de paquet) peuvent apparaître dans le nouveau menu. Les extensions de shell classiques fondées sur IContextMenu ont été déplacées vers l'ancien menu ouvert par « Afficher plus d'options » (Maj+F10). L'extension elle-même n'est pas cassée, elle continue donc de fonctionner pour l'instant, mais pour la voir dans le nouveau menu il faut migrer vers IExplorerCommand et soit empaqueter en MSIX, soit accorder l'identité avec un sparse package.
- L'installateur peut-il définir notre application comme application par défaut d'un fichier (celle qui s'ouvre au double-clic) ?
- Non. Le choix de l'application par défaut est conçu pour être fait par l'utilisateur, et Windows ne prend pas en charge le changement d'application par défaut ailleurs que depuis l'interface Paramètres du système. Les informations UserChoice qui conservent le choix de chaque utilisateur sont obscurcies, et un pilote-filtre (UCPD.sys) protège aussi l'écriture contre les applications. Ce qu'un installateur peut faire, c'est enregistrer un ProgID et des verbs, s'ajouter à OpenWithProgIds pour figurer comme candidat sous « Ouvrir avec », et orienter l'utilisateur vers la page des applications par défaut. La bonne implémentation n'est pas de voler la valeur par défaut, mais de se préparer à être choisi.
- Puis-je écrire une extension de shell en code managé, par exemple en C# ?
- Microsoft a dit clairement que rédiger une extension de shell in-process (gestionnaire de menu contextuel, gestionnaire d'icône, et assimilés) en code managé n'est pas recommandé et n'est pas pris en charge. L'extension est chargée dans l'Explorateur et dans le processus de toute application qui ouvre une boîte de dialogue de fichiers commune, de sorte que les collisions de version du CLR, la réentrance et la durée de vie non déterministe des objets rendent l'application hôte instable. La règle est une implémentation en C++ natif. Un EXE ordinaire lancé depuis le command d'un verb, ou une extension hors processus comme un gestionnaire d'aperçu qui s'exécute dans un processus séparé, convient en code managé.
- Qu'est-ce qu'un sparse package (MSIX avec emplacement externe) ?
- Un petit paquet MSIX qui ne contient aucun fichier d'application, seulement un manifeste (informations d'identité). Pour une application installée de façon ordinaire avec un installateur existant (MSI, Inno Setup, et assimilés), on l'enregistre avec Add-AppxPackage -ExternalLocation pointant vers le dossier d'installation : l'application acquiert une identité de paquet et peut utiliser les fonctions qui l'exigent, comme l'enregistrement dans le nouveau menu contextuel de Windows 11 et les notifications toast. Disponible à partir de Windows 10 version 2004, le paquet a besoin d'une signature de code de confiance sur la machine cible. C'est l'option réaliste quand on veut le nouveau menu sans déplacer toute la distribution vers MSIX.
- Que faire lorsqu'un élément de menu contextuel apparaît deux fois, ou ne disparaît pas ?
- Isolez d'abord la cause en vérifiant sur quel menu il apparaît : le nouveau ou l'ancien (Afficher plus d'options). Le double affichage typique vient de la coexistence d'un enregistrement classique dans le registre et d'un enregistrement dans le manifeste MSIX, ou d'un ProgID ou d'un CLSID d'extension laissé après désinstallation. Après un changement d'association, suspectez aussi un SHChangeNotify(SHCNE_ASSOCCHANGED) oublié ; juste après l'enregistrement du paquet, un redémarrage de l'Explorateur oublié. Si cela ne résout pas, désactivez temporairement les extensions non Microsoft dans ShellExView et identifiez la DLL fautive par recherche dichotomique.
Profil de l’auteur
Page de présentation de l’auteur de l’article.
Go Komura
Représentant de KomuraSoft LLC
Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.