Windows-Shell-Integration heute ── Kontextmenüs, Dateizuordnungen und was sich unter Windows 11 geändert hat
· Go Komura · Windows, Shell-Erweiterungen, Kontextmenü, Dateizuordnung, COM, Windows 11, Datei-Explorer, MSIX, Windows-Entwicklung
Ich wurde mit „wir haben die PCs durch Windows 11 ersetzt, und das Kontextmenü der App, die Sie uns vor Jahren gebaut haben, ist verschwunden“ konsultiert. Beim genaueren Zuhören war es nicht verschwunden. Rechtsklick auf eine Datei, „Weitere Optionen anzeigen“ am unteren Ende des Menüs wählen, und das vertraute Menü erscheint genau wie immer. Mit anderen Worten: Die Menüeinträge der internen App waren einen Klick weiter nach innen versteckt worden. Vom Feld hören wir „es ist ein Extra-Klick“ und „Anfragen, dass sie den Eintrag nicht finden, haben zugenommen“.
Das ist weder ein Ausfall noch eine Fehlkonfiguration; es ist eine Windows-11-Entwurfsänderung. Das Kontextmenü des Datei-Explorers wurde zu einer Zweischichtstruktur, alt und neu, und die Bedingungen, einen Eintrag ins neue Menü zu setzen, wurden etwas völlig anderes als zuvor.
Zugleich ist die Dateizuordnungs- und Shell-Erweiterungsmaschinerie darunter noch die alte Welt von COM und der Registrierung. Ein Erweiterungsschlüssel zeigt auf eine ProgID, das Verb der ProgID hält eine Befehlszeile, und eine aufwendigere Erweiterung läuft als In-Process-COM-Server (DLL), der in den Explorer geladen wird — diese Struktur hat sich in mehr als zwanzig Jahren nicht geändert. Wenn Sie nicht sowohl das unveränderte Fundament als auch das Menü kennen, das Windows 11 in zwei Teile gespalten hat, können Sie „das Menü erscheint nicht“, „es ist versteckt“ oder „es erscheint doppelt“ nicht isolieren.
Dieser Artikel richtet sich an IT-Personal in kleinen und mittleren Unternehmen und an Windows-Entwickler, die Geschäftsanwendungen betreuen. Er knüpft in einem Bild die Dreischichtstruktur der Dateizuordnung, die Fallstricke klassischer Shell-Erweiterungen, wie man das neue Windows-11-Kontextmenü ansteuert, sowie Installationsprogramm-Registrierung, Aufräumen und Fehlerbehebung zusammen.
1. Zuerst das Fazit
- Das Fundament von Kontextmenü und Dateizuordnung ist die dreischichtige Registrierungsstruktur „Erweiterungsschlüssel → ProgID → Verb“. Der Erweiterungsschlüssel ist ein Zeiger auf eine ProgID, die ProgID ist die Substanz, und
shell\<verb>\commanddarunter hält die Befehlszeile.1 - HKEY_CLASSES_ROOT (HKCR) ist kein unabhängiger Hive; es ist eine zusammengeführte Ansicht von HKLM\Software\Classes und HKCU\Software\Classes. Schreiben Sie die Alle-Benutzer-Registrierung nach HKLM und die Pro-Benutzer-Registrierung nach HKCU, und behandeln Sie HKCR als schreibgeschützt.2
- Die Standard-App (die App, die beim Doppelklick öffnet) ist so entworfen, dass sie der Benutzer wählt, und ein Programm kann sie nicht stehlen. Das Betriebssystem schützt die Wahl des Benutzers; was ein Installationsprogramm tun kann, ist, sich als Kandidat zu registrieren.3
- Eine klassische Shell-Erweiterung ist eine In-Process-COM-DLL, die in den Explorer geladen wird. Ein Absturz oder eine Verzögerung in der Erweiterung greift auf den Explorer als Ganzes über (und auf andere Apps, die die Shell nutzen); eine 64-Bit-Umgebung braucht eine 64-Bit-DLL; und eine Implementierung in verwaltetem Code ist nicht unterstützt.45
- Unter Windows 11 ist das Kontextmenü in zwei Teile zerfallen. Die einzigen Befehle, die im neuen Menü erscheinen, sind solche, die mit IExplorerCommand plus Paketidentität registriert sind; klassische IContextMenu-Erweiterungen werden ins alte Menü unter „Weitere Optionen anzeigen“ (Umschalt+F10) verschoben.67
- Der offizielle Weg, einen eigenen Befehl ins neue Menü zu setzen, ist, eine native DLL, die IExplorerCommand implementiert, in einem MSIX-Manifest zu registrieren (desktop4:FileExplorerContextMenus). Eine App, die nicht MSIX werden kann, kann die Identität allein mit einem Sparse-Paket (MSIX mit externem Speicherort) erhalten.78
- Wenn Sie nur „mit dieser App öffnen“ wollen, reichen eine Zuordnung und ein statisches Verb immer noch. Sie brauchen keine Shell-Erweiterungs-DLL, und Microsoft selbst sagt klar „wählen Sie die einfachste Methode, die die Anforderungen erfüllt (ein statisches Verb)“.9
- Nach Registrierung oder Änderung benachrichtigen Sie mit SHChangeNotify(SHCNE_ASSOCCHANGED); bei der Deinstallation löschen Sie die ProgID, löschen aber nicht den Standardwert des Erweiterungsschlüssels — das ist die offizielle Anleitung. Shell-Integration schließt den Entwurf des Aufräumens ein.110
In einem Satz: die Welt der Zuordnungen und Verben ist unverändert; nur wie das Menü gezeigt wird, ist unter Windows 11 in zwei Teile zerfallen. Unten gehen wir das vom Fundament her durch.
2. Wie Dateizuordnung funktioniert — die Dreischichtstruktur Erweiterungsschlüssel → ProgID → Verb
2.1. Die Dreischichtstruktur an einem Beispiel lesen
Was passiert, wenn Sie eine Datei einer gegebenen Erweiterung doppelklicken, entscheiden drei Schichten von Registrierungsschlüsseln.1
HKEY_CLASSES_ROOT
.kmrpt ← (1) Erweiterungsschlüssel
(Default) = KomuraSoft.Report.1 ← Ein Zeiger, der nur die ProgID nennt
OpenWithProgids
KomuraSoft.Report.1 ← Ein Kandidat unter „Öffnen mit“
KomuraSoft.Report.1 ← (2) ProgID (die Substanz der Zuordnung)
(Default) = Komura Report document
DefaultIcon
(Default) = "C:\Program Files\KomuraSoft\Report.exe",0
shell ← (3) Liste der Verben
open
command
(Default) = "C:\Program Files\KomuraSoft\Report.exe" "%1"
- (1) Der Erweiterungsschlüssel (
.kmrpt) zeigt nur als Standardwert auf einen ProgID-Namen. Hier direkt einen Befehl zu schreiben ist ein Fehler. - (2) Die ProgID (
KomuraSoft.Report.1) ist die Substanz der Zuordnung; sie hält den Anzeigenamen, das Symbol und die Verbliste. - (3) Ein Verb ist eine Aktion wie „öffnen“ oder „drucken“, und der Standardwert von
shell\open\commandist die Befehlszeile, die tatsächlich gestartet wird.
Diese Trennung ist der Grund, warum Sie mehrere Erweiterungen (.kmrpt und .kmrpt-file zum Beispiel) auf dieselbe ProgID zeigen lassen oder die ProgID beim Upgrade der App tauschen können.
flowchart TB
accTitle: Die Dreischichtstruktur der Dateizuordnung
accDescr: Der Erweiterungsschlüssel ist ein Zeiger, dessen Standardwert eine ProgID nennt; die ProgID ist die Substanz, die Anzeigename, Symbol und Verbliste hält; und der Standardwert von command unter dem Verb ist die Befehlszeile, die tatsächlich gestartet wird
ext["Erweiterungsschlüssel .kmrpt"] -->|nennt die ProgID als Standard| pid["ProgID KomuraSoft.Report.1"]
pid --> vb["Verb(open und andere unter shell)"]
vb --> cmd["command-Standardwert"]
cmd --> exe["Report.exe wird gestartet"]
pid -.-> attr["Hält auch den Anzeigenamen und DefaultIcon"]
Abbildung 1: Der Erweiterungsschlüssel ist ein Zeiger, die ProgID ist die Substanz, und das command des Verbs ist die Befehlszeile, die tatsächlich gestartet wird.
2.2. HKCR ist eine „zusammengeführte Ansicht“ — wohin Sie schreiben, ändert die Bedeutung
Das Beispiel oben steht unter HKEY_CLASSES_ROOT (HKCR), aber HKCR ist kein physischer Speicherort; es ist eine zusammengeführte Ansicht von HKLM\Software\Classes und HKCU\Software\Classes. Existiert derselbe Schlüssel auf beiden Seiten, gewinnt die HKCU-Seite.2
flowchart TB
accTitle: HKCR ist eine zusammengeführte Ansicht
accDescr: HKCR ist HKLM- und HKCU-Classes übereinandergelegt; existiert derselbe Schlüssel auf beiden Seiten, gewinnt HKCU; schreiben Sie die Registrierung ausdrücklich nach HKLM oder HKCU und behandeln Sie HKCR als schreibgeschützt
hklm["HKLM\\Software\\Classes(alle Benutzer)"] --> hkcr["HKCR(zusammengeführte Ansicht)"]
hkcu["HKCU\\Software\\Classes(pro Benutzer)"] --> hkcr
hkcu -.-> win["Existiert derselbe Schlüssel, gewinnt HKCU"]
hkcr -.-> ro["Als schreibgeschützt behandeln(zur Bestätigung)"]
Abbildung 2: HKCR ist, wie HKLM- und HKCU-Classes aussehen, wenn sie zusammengelegt sind; nennen Sie immer die eine oder die andere als Schreibziel.
| Schreibziel | Bedeutung | Erforderliche Rechte |
|---|---|---|
HKLM\Software\Classes |
Registrierung gemeinsam für alle Benutzer | Administrator |
HKCU\Software\Classes |
Registrierung nur für diesen Benutzer | Keine |
Direkt nach HKCR schreiben |
Je nachdem, wo der vorhandene Schlüssel schon lebt, verteilt | Abhängig |
In der Praxis ist die sichere Teilung, die Registrierung immer ausdrücklich nach HKLM oder HKCU zu schreiben und HKCR als schreibgeschützt (zur Bestätigung) zu behandeln. Das Verhältnis zur WOW64-Registrierungsumleitung lohnt sich ebenfalls zu sortieren. Zuordnungsdaten direkt unter HKLM\Software\Classes wie Erweiterungsschlüssel und ProgIDs sind seit Windows 7 zwischen der 32-Bit- und der 64-Bit-Registrierungsansicht geteilt, sodass ein 32-Bit-Installationsprogramm, das sie schreibt, nicht auf die Wow6432Node-Seite entkommt. Einige COM-Registrierungsunterschlüssel wie Classes\CLSID dagegen werden umgeleitet, und wenn Sie eine Shell-Erweiterung (In-Process-COM) registrieren, zählt die 32-Bit-/64-Bit-Schreibteilung. Einzelheiten stehen in „Registry-32-Bit/64-Bit-Umleitung und Virtualisierungsfallen — Wow6432Node und das Problem „Der Wert, den ich geschrieben habe, ist nicht da““.
2.3. Registrierung auf der App-Seite — App Paths, Applications, RegisteredApplications
Es gibt auch drei Arten von Registrierung auf der App-Seite, gepaart mit der Dateiseite (Erweiterung und ProgID).11
- App Paths (
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths): Registrierung, dieShellExecuteExerlaubt, allein über den Namen der ausführbaren Datei zu starten. Microsoft empfiehlt das, weil Sie die PATH-Umgebungsvariable nicht verschmutzen müssen. - Applications (
HKCR\Applications\<app.exe>): Definiert die Standardweise zu öffnen, wenn eine beliebige Datei unter „Öffnen mit“ übergeben wird, und den Anzeigenamen der App (FriendlyAppName). - RegisteredApplications + Capabilities: Deklariert die Erweiterungen und MIME-Typen, die die App behandeln kann, und ist die Registrierung, die sie als Kandidat auf der Windows-Seite Standard-Apps erscheinen lässt.
Die meisten Beratungen „unsere App erscheint nicht in der Liste der Standard-Apps“ sind Fälle, in denen die ProgID registriert und diese Capabilities-Registrierung weggelassen wurde.
flowchart TB
accTitle: Die drei Arten der Registrierung auf der App-Seite
accDescr: Die App-seitige Registrierung hat drei Arten — App Paths, Applications und RegisteredApplications — zuständig jeweils für den Start allein über den Dateinamen, die Standardweise zu öffnen unter Öffnen mit, und das Erscheinen auf der Seite Standard-Apps
app["App-seitige Registrierung"] --> ap["App Paths"]
app --> apps["Applications"]
app --> ra["RegisteredApplications"]
ap --> r1["Start allein über den Dateinamen"]
apps --> r2["Standard unter Öffnen mit"]
ra --> r3["Erscheint auf der Seite Standard-Apps"]
r3 -.-> cap["Eine Capabilities-Deklaration ist nötig"]
Abbildung 3: Es gibt drei Arten der App-seitigen Registrierung, und als Standard-Apps-Kandidat zu erscheinen erfordert eine Capabilities-Registrierung.
2.4. Die Standard-App gehört dem Benutzer — UserChoice-Schutz
Eine ProgID als Standardwert des Erweiterungsschlüssels zu schreiben macht sie nicht von selbst zur Standard-App. Das Ergebnis der ausdrücklichen Benutzerwahl unter „Öffnen mit“ und Ähnlichem wird in HKCU\...\Explorer\FileExts\<extension>\UserChoice gehalten, und die Zuordnungsauflösung bevorzugt diese Seite.
Und der wichtige Punkt ist, dass Windows die programmatische Änderung der Standard-App nicht unterstützt. Standard-App-Einstellungen sind so entworfen, dass sie der Benutzer über die Systemeinstellungen-UI vornimmt; UserChoice-Daten sind verschleiert, und ein Filtertreiber (UCPD.sys) blockiert Schreibvorgänge von Apps. In einer verwalteten Umgebung ist Gruppenrichtlinie / MDM-Richtlinie das offizielle Mittel.3
Dass Werkzeuge wie SetUserFTA, die „den Hash nachahmen und ihn umschreiben“, benutzt wurden, ist die andere Seite dieses Schutzes. Was Sie ins Installationsprogramm einer internen App legen sollten, ist nicht das Stehlen der Vorgabe, sondern die drei (a) korrekte Registrierung der ProgID und der Verben, (b) sich zu OpenWithProgIds hinzufügen, und (c) bei Bedarf zur Einstellungsseite lenken.
flowchart TB
accTitle: Standard-App-Auflösung und UserChoice-Schutz
accDescr: Das Ergebnis einer ausdrücklichen Benutzerwahl wird in UserChoice gehalten und in der Zuordnungsauflösung bevorzugt; UCPD.sys blockiert Umschreibungen von Apps, also kann ein Installationsprogramm sich als Kandidat registrieren und zur Einstellungsseite lenken
uc["UserChoice(die Wahl des Benutzers)"] -->|bevorzugt| res["Zuordnungsauflösung"]
ext["Standardwert des Erweiterungsschlüssels"] --> res
wr["Umschreiben von einer App"] -.->|UCPD.sys blockiert es| uc
res ~~~ inst["Die Aufgabe des Installationsprogramms"]
inst --> a1["ProgID und Verben registrieren"]
inst --> a2["Zu OpenWithProgIds hinzufügen"]
inst --> a3["Zur Einstellungsseite lenken"]
Abbildung 4: Die Zuordnungsauflösung bevorzugt die Wahl des Benutzers (UserChoice), und das Betriebssystem schützt sie vor Umschreibungen durch Apps.
3. Verben außer „Öffnen“ — print, edit, runas, eigene Verben
Ein Verb ist nicht nur open. Standardverben, deren Bedeutung das Betriebssystem kennt, umfassen edit, print, play und preview sowie open, und ein Standardverb erhält automatisch einen Anzeigenamen, der der Betriebssystemsprache folgt. Das Standardverb beim Doppelklick wird in der Reihenfolge entschieden: Standardwert des shell-Schlüssels → erstes Verb in der Registrierung → open → openwith.12
flowchart TB
accTitle: Reihenfolge, in der das Standardverb entschieden wird
accDescr: Das Standardverb beim Doppelklick ist das erste, das in der Reihenfolge Standardwert des shell-Schlüssels, erstes Verb in der Registrierung, open, openwith gefunden wird
s1["Standardwert des shell-Schlüssels"] -->|falls keiner| s2["Erstes Verb in der Registrierung"]
s2 -->|falls keines| s3["open"]
s3 -->|falls keines| s4["openwith"]
Abbildung 5: Das Standardverb beim Doppelklick ist das erste, das in dieser Reihenfolge gefunden wird.
Wenn Sie eine eigene Aktion hinzufügen wollen, registrieren Sie ein eigenes Verb.
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 ← eigenes Verb
(Default) = Verify report (&V) ← Menüanzeigename
command
(Default) = "C:\Program Files\KomuraSoft\Report.exe" /verify "%1"
Drei kleine Tatsachen, die zu kennen hilft.
- Registrieren Sie ein Verb namens runas, und Sie definieren einen Erhöhungstart, der „Als Administrator ausführen“ entspricht, und er wird auch verwendet, wenn eine API der
ShellExecute-Familierunasangibt. - Legen Sie einen leeren Wert namens
Extendedauf den Verbschlüssel, und es wird ein erweitertes Verb, das nur bei Umschalt+Rechtsklick gezeigt wird. Praktisch, um eine gefährliche, selten genutzte Operation zu verstecken.12 - Einige Zuordnungen älterer Apps haben noch eine Konfiguration, die ein Dokument mit DDE (der Schlüssel
ddeexec) in einen bestehenden Prozess schickt, aber ein Verb über DDE zu starten ist bereits ein Deprecated-Erbe. Es gibt keinen Grund, es neu zu schreiben.12
Ein weiterer Unfall, der oft passiert, ist das Anführungszeichen in der Befehlszeile. Kann ein Element der Befehlszeichenfolge ein Leerzeichen enthalten, müssen Sie es in Anführungszeichen setzen. Das gilt natürlich für einen EXE-Pfad wie C:\Program Files\..., und %1 (der Pfad der ausgewählten Datei) sollte immer als "%1" geschrieben werden. Sie können nicht garantieren, dass ein Benutzerdateipfad kein Leerzeichen enthält. Ein unquoted My Program.exe wird als „starte My mit dem Argument Program.exe“ interpretiert.13
flowchart TB
accTitle: Der Anführungszeichen-Unfall in der Befehlszeile
accDescr: Ein unquoted Befehl wird am Leerzeichen gespalten und als Start von My mit dem Argument Program.exe fehlinterpretiert, also sollten ein EXE-Pfad, der ein Leerzeichen enthalten kann, und %1, das den ausgewählten Dateipfad darstellt, immer in Anführungszeichen gesetzt werden
c1["Unquoted Befehl"] -->|am Leerzeichen gespalten| bad["Als Start einer anderen EXE fehlinterpretiert"]
c2["Quoted Befehl"] --> good["Startet wie beabsichtigt"]
c2 -.-> q1["Setzen Sie den EXE-Pfad in Anführungszeichen"]
q1 -.-> q2["Setzen Sie auch %1 immer in Anführungszeichen"]
Abbildung 6: Ein unquoted Befehl wird am Leerzeichen falsch gespalten, also setzen Sie EXE-Pfad und %1 immer in Anführungszeichen.
Der bisherige Nur-Registrierungs-Mechanismus (ein statisches Verb) lässt sich ohne eine einzige DLL realisieren und riskiert nicht, den Explorer instabil zu machen. Microsoft selbst sagt wiederholt „bevor Sie eine Shell-Erweiterung schreiben, prüfen Sie, ob das einfachste statische Verb, das die Anforderungen erfüllt, reicht“.9
4. Klassische Shell-Erweiterungen — eine DLL, die im Explorer läuft
4.1. Arten von Shell-Erweiterungen
Anforderungen, die ein statisches Verb nicht erfüllt — „das Menü dynamisch je nach Auswahl ändern“, „das Symbol oder das Eigenschaftenblatt ersetzen“ — nutzen einen Shell-Erweiterungshandler. Repräsentative Arten sind die folgenden.4
| Handler | Hauptschnittstelle | Was er tun kann |
|---|---|---|
| Kontextmenühandler | IContextMenu + IShellExtInit | Menüeinträge dynamisch hinzufügen und steuern |
| Symbolhandler / Symbolüberlagerung | IExtractIcon / IShellIconOverlayIdentifier | Symbol pro Datei und Überlagerung |
| Eigenschaftenblatthandler | IShellPropSheetExt | Eine Registerkarte zum Eigenschaftenblatt hinzufügen |
| Miniatur / Infotip | IThumbnailProvider / IQueryInfo | Miniaturansicht und Hover-Beschreibung |
| Drag-and-Drop- / Copy-Hook-Handler | IDropTarget / ICopyHook | Beim Ablegen oder bei Kopieren/Verschieben eingreifen |
Diese sind alle als COM-Klassen implementiert und in der Registrierung per CLSID registriert. Die Idee von COM selbst steht in „Was sind COM / ActiveX / OCX? – Unterschiede und Zusammenhänge im Überblick“.
4.2. Was es bedeutet, ein In-Process-COM-Server zu sein
Das Wesen einer klassischen Shell-Erweiterung ist, dass sie ein In-Process-COM-Server (DLL) ist, der in den Explorer (oder in jede App, die einen gemeinsamen Dateidialog geöffnet hat) geladen wird. Jede Vorsichtsmaßnahme folgt daraus.4
- Stürzt die Erweiterung ab, nimmt sie den Explorer mit. Hängt sie, friert ein Rechtsklick mehrere Sekunden ein. Der Schaden beschränkt sich auch nicht auf den Explorer; er erreicht jede App, die einen Dateiöffnen-Dialog angezeigt hat.
- Der Menüaufbau geschieht auf dem UI-Thread, also dürfen Sie zur Anzeigezeit keine langsame Arbeit wie Netzwerkzugriff oder Datei-E/A tun.
- Registrieren Sie das Threading-Modell in der Regel als
Apartment.
flowchart TB
accTitle: Kollateralschadenstruktur einer In-Process-Erweiterung
accDescr: Eine Shell-Erweiterungs-DLL wird nicht nur in den Explorer, sondern auch in den Prozess jeder App geladen, die einen Dateidialog geöffnet hat, sodass ein Absturz oder Hänger in der Erweiterung auf den ganzen Hostprozess übergreift
dll["Shell-Erweiterungs-DLL"] -->|in-process geladen| exp["Explorer"]
dll -->|in-process geladen| any["Jede App, die einen Dialog öffnet"]
exp --> dmg["Ein Absturz oder Hänger greift über"]
any --> dmg
dmg -.-> rule["Zur Anzeigezeit keine langsame Arbeit"]
Abbildung 7: Die Erweiterungs-DLL läuft im Hostprozess, sodass ein Absturz oder Hänger auf den Host als Ganzes übergreift.
Untersuchen Sie eine Beratung wie „der Explorer friert ein, wenn ich einen bestimmten Ordner öffne“ oder „ein Rechtsklick dauert fünf Sekunden“, und es ist nicht selten, dass die Ursache eine Drittanbieter-Shell-Erweiterung statt der internen App ist. Isolationsmethoden stehen in Kapitel 8.
4.3. Bittigkeit angleichen — eine 64-Bit-Umgebung braucht eine 64-Bit-DLL
Eine In-Process-DLL muss zur Bittigkeit des Prozesses passen, der sie lädt. Der Explorer unter 64-Bit-Windows ist ein 64-Bit-Prozess, also wird eine nur als 32-Bit gebaute Shell-Erweiterungs-DLL nie geladen und erscheint überhaupt nicht im Menü. Es gibt auch keinen Fehler, daher ist das eine Standardursache von „ich habe sie registriert, aber sie erscheint nicht“. Eine 32-Bit-App-Hauptkomponente mit einer 64-Bit-Shell-Erweiterungs-DLL zu kombinieren ist eine legitime Konfiguration, aber Sie müssen die Tatsache im Blick behalten, dass die COM-Registrierung nach Bittigkeit teilt (Wow6432Node). Der Start vom command eines Verbs ist eine eigene-Prozess-EXE, also unterliegt er dieser Einschränkung nicht (sie als 32-Bit-EXE zu lassen ist in Ordnung).
flowchart TB
accTitle: Bittigkeit einer Shell-Erweiterungs-DLL angleichen
accDescr: Die einzige Shell-Erweiterungs-DLL, die ein 64-Bit-Explorer laden kann, ist eine 64-Bit-DLL; eine nur-32-Bit-DLL erscheint nie im Menü und erzeugt keinen Fehler; eine vom Verb-Command gestartete EXE ist ein eigener Prozess und unterliegt der Einschränkung nicht
exp["64-Bit-Explorer"] -->|kann laden| d64["64-Bit-Shell-Erweiterungs-DLL"]
exp -.->|kann nicht laden| d32["Nur-32-Bit-DLL"]
d32 -.-> sym["Erscheint nicht im Menü, ohne Fehler"]
exe["Vom Verb gestartete EXE"] -->|eigener Prozess| ok32["Als 32-Bit in Ordnung"]
Abbildung 8: Die einzige in den 64-Bit-Explorer geladene DLL ist eine 64-Bit-DLL; eine vom Verb gestartete EXE unterliegt dieser Einschränkung nicht.
4.4. Warum Sie sie nicht in verwaltetem Code schreiben dürfen
Ich bekomme oft die Frage „kann ich eine Shell-Erweiterung in C# schreiben“, aber Microsoft hat klar gesagt, dass das Schreiben einer In-Process-Shell-Erweiterung in verwaltetem Code (.NET) nicht empfohlen und außerhalb des Supports ist.5
Der Grund ist die Natur der Erweiterung, die in einen beliebigen Prozess geladen wird. CLR-Versionskollisionen (besonders unter .NET Framework 4), das Problem, dass die CLR während des Wartens auf eine Sperre in die Nachrichtenschleife wiedereintritt, und nicht deterministische Objektlebensdauer durch Garbage Collection, die mit dem Referenzzählvertrag von COM kollidiert, sind strukturelle Gründe, warum die Host-App instabil wird. Einige Punkte wurden auf .NET Framework 4 und später und auf modernem .NET gemildert, aber die offizielle Position hat sich nicht geändert.
Die praktische Richtlinie ist einfach. Schreiben Sie eine In-Process-Erweiterung in nativem C++. Wenn Sie verwalteten Code nutzen wollen, machen Sie daraus eine normale EXE, die vom command eines Verbs gestartet wird, oder eine Out-of-Process-Erweiterung, die in einem eigenen Prozess läuft (ein Vorschauhandler und Ähnliches).5
flowchart TB
accTitle: Beurteilen, ob verwalteter Code erlaubt ist
accDescr: Eine In-Process-Erweiterung, die im Explorer läuft, wird in der Regel in nativem C++ geschrieben; wenn Sie verwalteten Code wollen, machen Sie daraus eine normale vom Verb-Command gestartete EXE oder eine Out-of-Process-Erweiterung, die in einem eigenen Prozess läuft
q1{"Läuft in-process?"} -->|ja| cpp["In nativem C++ schreiben"]
q1 -->|nein| mg["Verwalteter Code ist in Ordnung"]
cpp -.-> why["CLR- / Wiedereintrittsrisiko macht den Host instabil"]
mg --> e1["Vom Verb gestartete EXE"]
mg --> e2["Out-of-Process-Vorschau"]
Abbildung 9: Eine In-Process-Erweiterung ist in der Regel natives C++; verwalteter Code ist auf eine Konfiguration beschränkt, die in einem eigenen Prozess läuft.
5. Das neue Windows-11-Kontextmenü — das in zwei Teile gespaltene Menü
5.1. Was geschehen ist
Windows 11 hat das Kontextmenü des Datei-Explorers erneuert. Ausschneiden, Kopieren und Ähnliches wurden zu einer Zeile von Symbolen oben; „Öffnen“ und „Öffnen mit“ wurden oben zusammengefasst; und Befehle, die eine App hinzufügt, werden unter den Standardbefehlen der Shell gruppiert. Wenn eine App mehrere Befehle hinzufügt, werden sie in einem Flyout (Untermenü) mit dem Namen der App gesammelt.6
Und der entscheidende Punkt ist dieser. Klassische IContextMenu-basierte Shell-Erweiterungen wurden nicht gelöscht; sie wurden auf die Seite des alten Menüs verschoben, das mit „Weitere Optionen anzeigen“ (Umschalt+F10) öffnet und das Windows-10-Menü unverändert lädt.6 Die Identität der Eröffnungsberatung „das Menü wurde versteckt“ ist diese Spaltung.
flowchart TB
accTitle: Das Kontextmenü, das Windows 11 in zwei Teile gespalten hat
accDescr: Was beim Rechtsklick zuerst öffnet, ist das neue Menü; die einzigen Befehle, die dort erscheinen, sind solche, die mit IExplorerCommand und Paketidentität registriert sind; klassische IContextMenu-Erweiterungen werden ins alte Menü verschoben, das mit Weitere Optionen anzeigen öffnet
rc["Rechtsklick auf eine Datei"] --> newm["Neues Menü(Windows 11)"]
newm --> newi["IExplorerCommand- + Identitätsbefehle"]
newm -->|Weitere Optionen anzeigen Umschalt+F10| oldm["Altes Menü(das Windows-10-Menü)"]
oldm --> oldi["Klassische IContextMenu-Erweiterungen"]
newi -.-> fly["Mehrere Befehle werden in einem Flyout gesammelt"]
Abbildung 10: Die einzigen Befehle, die im neuen Menü erscheinen, sind IExplorerCommand- + Identitätsbefehle; klassische Erweiterungen werden auf die Seite des alten Menüs verschoben.
5.2. Der offizielle Weg ins neue Menü — IExplorerCommand + Manifestregistrierung
Es gibt eine Weise, einen eigenen Befehl ins neue Menü zu setzen. Bereiten Sie eine native DLL vor, die die Schnittstelle IExplorerCommand implementiert, und deklarieren Sie den COM-Server und die Kontextmenüerweiterung in einem MSIX-Paketmanifest.7
<!-- Paketmanifest (Auszug) -->
<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>
Das Type von ItemType kann eine bestimmte Erweiterung angeben, oder * (alle Dateien), Directory (Ordner) oder Directory\Background (ein Ordnerhintergrund). Stimmen Sie die DLL auf die Architektur des Explorers ab (64-Bit / ARM64).7
IExplorerCommand selbst ist eine Schnittstelle, die seit der Windows-7-Ära existiert; Sie implementieren den Titel (GetTitle), das Symbol (GetIcon), den Zustand aktiviert / deaktiviert / ausgeblendet (GetState) und die Ausführung (Invoke). Die Methoden werden vom UI-Thread aufgerufen, also ist der Zugriff auf Netzwerkressourcen verboten, und Methoden zum Menüaufbau müssen schnell zurückkehren. Schwere Arbeit nach Invoke.147
flowchart TB
accTitle: Manifeststruktur einer Registrierung im neuen Menü
accDescr: Die COM-Server-Deklaration des MSIX-Manifests mappt eine CLSID auf eine DLL, und die Kontextmenüerweiterungsdeklaration bindet Ziel und Implementierung mit ItemType und Verb, sodass ein eigener Befehl im neuen Menü erscheint
man["MSIX-Manifest"] --> com["COM-Server-Deklaration"]
man --> ctx["Menüerweiterungsdeklaration"]
com -->|mappt CLSID auf DLL| impl["IExplorerCommand-Implementierungs-DLL"]
ctx -->|gibt mit ItemType und Verb an| impl
impl --> shown["Befehl erscheint im neuen Menü"]
ctx -.-> tgt["Das Ziel ist eine Erweiterung, alle Dateien und Ähnliches"]
Abbildung 11: Zwei Deklarationen im Manifest binden die Implementierungs-DLL an das Ziel, und der Befehl erscheint im neuen Menü.
5.3. Die Option für eine nicht verpackte App — Identität allein mit einem Sparse-Paket holen
Die Notluke, wenn „unsere App kann nur als MSI verteilt werden; MSIX ist unmöglich“, ist ein Sparse-Paket (MSIX mit externem Speicherort). Sie signieren ein kleines MSIX, das nur ein Manifest ist, ohne App-Rumpf, und registrieren es am Ende des vorhandenen Installationsprogramms. Die App erwirbt dann Paketidentität, und die Manifestregistrierung oben (= Erscheinen im neuen Menü) wird möglich. Es ist ab Windows 10 Version 2004 verfügbar, und das Paket braucht eine Signatur mit einem Zertifikat, dem auf dem Zielrechner vertraut wird.8
flowchart TB
accTitle: Der Ablauf, Identität mit einem Sparse-Paket zu holen
accDescr: Nachdem das vorhandene Installationsprogramm den App-Rumpf abgelegt hat, gibt die Registrierung eines nur-Manifest-Sparse-Pakets mit einem externen Speicherort der App Paketidentität und macht die Manifestregistrierung des neuen Menüs möglich
inst["Vorhandenes Installationsprogramm"] --> files["App-Rumpf ablegen"]
sp["Sparse-Paket"] -.-> only["Nur Manifest, kein Rumpf"]
files --> reg["Mit externem Speicherort registrieren"]
sp --> reg
reg --> id["Paketidentität erwerben"]
id --> ok["Registrierung im neuen Menü wird möglich"]
sp -.-> sign["Eine vertrauenswürdige Signatur ist nötig"]
Abbildung 12: Registrieren Sie ein Sparse-Paket ohne Rumpf mit einem externen Speicherort, und die App erwirbt Paketidentität.
Der größte Vorteil ist, dass Sie das Installationsprogramm nicht ersetzen müssen; es ist die realistische Antwort für eine App, die bereits ein MSI-/EXE-Installationsprogramm-Asset hat. Zum Vergleich mit einem vollständigen Umzug auf MSIX siehe auch „Windows-App-Verteilung wählen – MSI/MSIX/ClickOnce/xcopy/eigener Updater“.
5.4. Wie Zuordnungsverben im neuen Menü erscheinen
Ein Punkt, der leicht missverstanden wird: die Zuordnungen der Kapitel 2 und 3 (ProgID und Verb) leben im neuen Menü noch. Das Standardverb beim Doppelklick, „Öffnen“ und die „Öffnen mit“-Kandidaten werden aus der Zuordnung aufgelöst und oben im neuen Menü angezeigt. Wenn Sie also nur „mit dieser App öffnen können“ wollen, braucht Windows 11 keine Extraarbeit. Andererseits ist eine Zuordnung keine Allzweck-Menüerweiterung, sodass Sie für einen beliebigen eigenen Befehl in der ersten Schicht des neuen Menüs IExplorerCommand plus Identität brauchen — das ist die Rollenteilung.7
flowchart TB
accTitle: Die Rollenteilung zwischen Zuordnungen und neuem Menü
accDescr: Eine ProgID-und-Verb-Zuordnung wird im neuen Menü noch genutzt, um das Standardverb, Öffnen und Öffnen mit aufzulösen, und wird oben angezeigt; einen beliebigen eigenen Befehl in die erste Schicht des neuen Menüs zu setzen erfordert IExplorerCommand und Identität
assoc["Zuordn.(ProgID + Verb)"] --> sol["Standard / Öffnen auflösen"]
sol --> top["Oben im neuen Menü"]
assoc -.-> keep["Keine Extraarbeit unter Win11"]
cmd["Ein eigener Befehl"] --> need["IExplorerCommand+Identität"]
need --> first["Erste Schicht des neuen Menüs"]
Abbildung 13: Zuordnungen erledigen im neuen Menü noch die Auflösung der „Öffnen“-Familie; nur ein eigener Befehl braucht IExplorerCommand plus Identität.
6. Eine praktische Entscheidungstabelle — welche der drei Optionen
Wir ordnen das Bisherige in eine praktische Dreiwege-Wahl.
| Was Sie erreichen wollen | Empfohlenes Mittel | Aussehen unter Windows 11 | Erforderliche Arbeit und Kosten |
|---|---|---|---|
| (a) Die interne App beim Doppelklick oder „Öffnen“ starten | Zuordnung + statisches Verb (nur Registrierungsregistrierung) | In „Öffnen“ und „Öffnen mit“ im neuen Menü integriert | Nur Registrierungsregistrierung des Installationsprogramms. Keine DLL, keine Extra-Signaturanforderung |
| (b) Einen eigenen Befehl für die ausgewählte Datei/den ausgewählten Ordner ins neue Menü setzen | IExplorerCommand-Implementierung + MSIX-Manifestregistrierung. Eine nicht verpackte App erhält Identität mit einem Sparse-Paket | Erste Schicht des neuen Menüs (mehrere Befehle werden in einem App-Namen-Flyout gesammelt) | Native C++-DLL + Paketidentität + Codesignatur |
| (c) Eine vorhandene klassische IContextMenu-Erweiterung weiter nutzen | Vorerst so lassen (nicht für neue Entwicklung wählen) | Nur Seite des alten Menüs, unter „Weitere Optionen anzeigen“ (Umschalt+F10) | Einen 64-Bit-Build und die COM-Registrierung pflegen. Einen späteren Umzug nach (b) planen |
Es gibt zwei Urteilspunkte. Erstens: holen Sie (b) oder (c) nicht für eine Anforderung, die (a) erfüllt. In dem Moment, in dem Sie eine Shell-Erweiterung schreiben, übernehmen Sie die Verantwortung für die Stabilität des Explorers. Zweitens: (c) ist nur „nicht kaputt“; als Benutzererlebnis bleibt es einen Schritt schlechter. Je häufiger ein Befehl im Tagesbetrieb genutzt wird, desto größer die Rendite eines Umzugs nach (b).
flowchart TB
accTitle: Wie Sie unter den drei Optionen wählen
accDescr: Wenn Sie nur den Start beim Doppelklick oder Öffnen wollen, reichen eine Zuordnung und ein statisches Verb; um einen eigenen Befehl ins neue Menü zu setzen, nutzen Sie IExplorerCommand und MSIX-Manifestregistrierung; wenn Sie nicht MSIX werden können, vergeben Sie Identität mit einem Sparse-Paket; behalten Sie eine vorhandene klassische IContextMenu-Erweiterung vorerst auf der Seite des alten Menüs
q1{"Reicht Öffnen?"} -->|ja| pa["Zuordn. + statisches Verb"]
q1 -->|nein| q2{"Eigener Befehl im neuen Menü?"}
q2 -->|ja| q3{"Können Sie MSIX werden?"}
q3 -->|ja| pb1["IExplorerCommand+MSIX"]
q3 -->|nein| pb2["Sparse-Pkg-Identität"]
q2 -->|nein| pc["Klassisches vorerst behalten"]
pc -.-> old["Nur Seite des alten Menüs"]
pa -.-> dllfree["Keine DLL, kleines Risiko"]
Abbildung 14: Wählen Sie unter einem statischen Verb, IExplorerCommand plus Identität und dem Behalten des Klassischen je nach Anforderung.
7. Bereitstellung und Registrierung in der Praxis — Installationsprogramm, Sparse-Paket, Aufräumen
7.1. HKLM oder HKCU
Stimmen Sie es auf die Form des Installationsprogramms ab. Alle Benutzer (unter Program Files abgelegt, Administratorrechte) ist HKLM\Software\Classes; Pro-Benutzer-Installation (keine Erhöhung) ist HKCU\Software\Classes. Mischen Sie sie, und Sie erzeugen die Anfrage der Art „A kann es öffnen, aber B nicht“. Für eine Shell-Erweiterung, die CLSID-Registrierung betrifft, ist Reg-Free COM — das die Registrierungsregistrierung selbst überflüssig macht — eine gültige Option für COM-Nutzung in der App, lässt sich aber nicht auf eine Shell-Erweiterung anwenden, die der Explorer lädt, daher brauchen Sie die direkte Registrierung („Was ist Reg-Free COM - COM ohne Registrierung nutzen“).
7.2. Nach einer Änderung benachrichtigen — SHChangeNotify
Nachdem Sie eine Zuordnung registriert, geändert oder gelöscht haben, benachrichtigen Sie das Ereignis SHCNE_ASSOCCHANGED mit SHChangeNotify. Überspringen Sie das, und der Explorer kann die Änderung bis zu einem Neustart übersehen.110
// Nach dem Ändern von Zuordnungen einmal aufrufen, z. B. aus einer Installationsprogramm-Custom-Action
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);
7.3. Ein Sparse-Paket registrieren und entfernen
Das Registrieren und Entfernen eines Sparse-Pakets ist die Aufgabe des Installationsprogramms. Registrieren Sie nach dem Ablegen der Dateien; entfernen Sie vor dem Löschen der Dateien.8
# Zur Installationszeit: nach dem Ablegen der Dateien den Installationsordner als externen Speicherort registrieren
Add-AppxPackage -Path "C:\Program Files\KomuraSoft\KomuraReport.identity.msix" `
-ExternalLocation "C:\Program Files\KomuraSoft"
# Zur Deinstallationszeit: die Paketregistrierung entfernen, bevor die Dateien gelöscht werden
Remove-AppxPackage <package full name>
Ein Punkt zum Beobachten: Add-AppxPackage registriert für den Benutzer, der es ausgeführt hat. Wenn Sie es aus einer Custom Action eines Per-Machine-MSI unter LocalSystem aufrufen, vergibt das dem installierenden Benutzer keine Identität, daher konfigurieren Sie es so, dass es unter Benutzerimitation läuft. Selbst dann gilt die Registrierung unter Imitation nur für den Benutzer, der diese Installation ausgeführt hat. Auf einem PC, den mehrere Benutzer nutzen, haben andere Benutzer und später angelegte Benutzer keine Paketidentität, und der Befehl erscheint nicht im neuen Menü. Damit jeder Benutzer es nutzt, stellen Sie einen Mechanismus bereit, etwa beim ersten Start die eigene Paketregistrierung zu prüfen und zu registrieren, falls sie fehlt (Pro-Benutzer-Registrierung), und nehmen Sie das Entfernen von jedem Benutzer, der eine Registrierung hat, in den Deinstallationsplan auf. Das Widerspiegeln einer Manifestregistrierung kann auch einen Explorer-Neustart (oder eine Abmeldung) erfordern.7
flowchart TB
accTitle: Reihenfolge beim Registrieren und Entfernen eines Sparse-Pakets
accDescr: Zur Installationszeit registrieren Sie das Sparse-Paket nach dem Ablegen der Dateien; zur Deinstallationszeit entfernen Sie die Registrierung vor dem Löschen der Dateien; beachten Sie, dass die Registrierung nur für den Benutzer gilt, der sie ausgeführt hat
i1["Installation"] --> i2["Dateien ablegen"]
i2 --> i3["Sparse-Paket registrieren"]
u1["Deinstallation"] --> u2["Paketregistrierung entfernen"]
u2 --> u3["Dateien löschen"]
i3 -.-> pu["Registrierung gilt nur für den laufenden Benutzer"]
Abbildung 15: Registrieren Sie nach dem Ablegen der Dateien, entfernen Sie vor dem Löschen, und beachten Sie, dass die Registrierung pro laufendem Benutzer gilt.
7.4. Aufräumen bei der Deinstallation — was löschen und was lassen
Das Aufräumen bei der Deinstallation hat eine klare offizielle Anleitungslinie.1
- Löschen: den ganzen internen ProgID-Schlüssel, die Capabilities-/RegisteredApplications-Registrierung, die CLSID-Registrierung der Shell-Erweiterung, das Sparse-Paket (Remove-AppxPackage).
- Lassen: den Standardwert des Erweiterungsschlüssels (
.kmrpt). Die offizielle Empfehlung ist, ihn nicht zu löschen, selbst wenn er noch auf die interne ProgID zeigt. Nach der Installation zu beurteilen, ob eine andere App die Vorgabe übernommen hat, ist schwierig, und Windows ignoriert einfach eine Standardwert-ProgID, die nicht registriert ist, sodass das Lassen keinen echten Schaden anrichtet. - Rufen Sie SHChangeNotify(SHCNE_ASSOCCHANGED) auch am Ende des Aufräumens auf.
Die meisten Probleme „wir haben deinstalliert und Reste erscheinen noch im Menü“ sind ein Leck in diesem Aufräumen-Entwurf.
flowchart TB
accTitle: Aufräumen-Entwurf bei der Deinstallation
accDescr: Bei der Deinstallation löschen Sie den internen ProgID-Schlüssel, die CLSID-Registrierung und das Sparse-Paket; lassen Sie den Standardwert des Erweiterungsschlüssels, weil eine nicht registrierte ProgID ignoriert wird; benachrichtigen Sie die Änderung am Ende des Aufräumens mit SHChangeNotify
un["Deinstallation"] --> del["Löschen"]
un --> keep["Lassen"]
del --> d1["ProgID- und CLSID-Registrierung"]
del --> d2["Sparse-Paket"]
keep --> k1["Standardwert des Erweiterungsschlüssels"]
k1 -.-> why["Eine nicht registrierte ProgID wird ignoriert"]
d1 --> fin["Am Ende mit SHChangeNotify benachrichtigen"]
k1 --> fin
Abbildung 16: Löschen Sie die interne Registrierung, lassen Sie den Standardwert des Erweiterungsschlüssels, und benachrichtigen Sie die Änderung am Ende des Aufräumens.
8. Fehlerbehebung — fehlend, doppelt, schwer
8.1. Es erscheint nicht im Menü
Isolieren Sie in dieser Reihenfolge.
- Welches Menü Sie ansehen: Eine Registrierung im klassischen Stil erscheint nur auf der Seite des alten Menüs unter Umschalt+F10. Prüfen Sie zuerst beide.
- Bittigkeit: Eine nur-32-Bit-Shell-Erweiterungs-DLL wird nicht in den 64-Bit-Explorer geladen (Abschnitt 4.3).
- Registrierungsziel: HKLM/HKCU, eine Wow6432Node-Verwechslung. Bestätigen Sie den tatsächlichen Schlüssel mit
reg query. - Paketregistrierung: Für das neue Menü bestätigen Sie die Anwesenheit mit
Get-AppxPackage, das Vertrauen des Signaturzertifikats und den-ExternalLocation-Pfad, dann starten Sie den Explorer neu.7 - Vergessene Benachrichtigung: Wenn SHChangeNotify vergessen wurde, können Sie es daran erkennen, ob ein Explorer-Neustart es wirksam macht.
flowchart TB
accTitle: Isolationsreihenfolge, wenn es nicht im Menü erscheint
accDescr: Beginnen Sie damit zu bestätigen, welches Menü Sie ansehen, isolieren Sie dann DLL-Bittigkeit, Registrierungsziel, Paketregistrierung und Signatur sowie ein vergessenes SHChangeNotify, in dieser Reihenfolge
c1["Bestätigen, welches Menü, alt oder neu"] --> c2["DLL-Bittigkeit bestätigen"]
c2 --> c3["HKLM- und HKCU-Registrierungsziel bestätigen"]
c3 --> c4["Paketregistrierung und Signatur bestätigen"]
c4 --> c5["Eine vergessene Benachrichtigung am Neustart erkennen"]
Abbildung 17: Wenn es „nicht erscheint“, isolieren Sie in der Reihenfolge Menü, das Sie ansehen, Bittigkeit, Registrierungsziel, Paketregistrierung, vergessene Benachrichtigung.
8.2. Es erscheint doppelt oder geht nicht weg
Typische Ursachen sind die Koexistenz einer klassischen Registrierungsregistrierung und einer Manifestregistrierung, ein Leck im Deinstallations-Aufräumen (Abschnitt 7.4) oder Reste einer alten-Version-ProgID. Erscheint es nur im alten Menü doppelt, denken Sie an Reste; erscheint es auf alt und neu, denken Sie an Koexistenz.
flowchart TB
accTitle: Eine Doppelanzeige isolieren
accDescr: Zweimal nur im alten Menü deutet auf Reste wie ein Aufräumen-Leck oder eine alte ProgID; zweimal auf alt und neu deutet auf die Koexistenz einer klassischen Registrierungsregistrierung und einer Manifestregistrierung
q{"Auf welchem erscheint es doppelt?"} -->|nur altes Menü| zan["Reste"]
q -->|alt und neu| hei["Koexistenz"]
zan -.-> z1["Aufräumen-Leck oder eine hinterlassene alte ProgID"]
hei -.-> h1["Klassische Registrierungsregistrierung koexistiert mit der neuen"]
Abbildung 18: Zweimal nur im alten Menü deutet auf Reste; zweimal auf alt und neu deutet auf Koexistenz.
8.3. Der Explorer ist schwer oder stürzt ab
Wenn ein Rechtsklick langsam ist oder ein bestimmter Ordner abstürzt, inventarisieren Sie zuerst die installierten Shell-Erweiterungen. Listen Sie Nicht-Microsoft-Erweiterungen mit einem Werkzeug wie NirSofts ShellExView, deaktivieren Sie die verdächtigen vorübergehend und identifizieren Sie die Täter-DLL per binärer Suche. Bei einem Absturz ist das „Faulting module“ der Ereignisanzeige ebenfalls ein Hinweis. War die interne Erweiterung die Ursache, verdächtigen Sie synchrone E/A oder Netzwerkzugriff auf dem Menüaufbaupfad (Abschnitte 4.2 und 5.2).
flowchart TB
accTitle: Die Täter-DLL identifizieren, wenn es schwer ist oder abstürzt
accDescr: Listen Sie Nicht-Microsoft-Shell-Erweiterungen in ShellExView, deaktivieren Sie die verdächtigen vorübergehend und identifizieren Sie die Täter-DLL per binärer Suche; bei einem Absturz ist das Faulting module der Ereignisanzeige ebenfalls ein Hinweis
s1["Shell-Erweiterungen inventarisieren"] --> s2["Die Nicht-Microsoft-auflisten"]
s2 --> s3["Vorübergehend deaktivieren und binär suchen"]
s3 --> s4["Die Täter-DLL identifizieren"]
crash["Bei einem Absturz"] -.-> ev["Das Faulting module prüfen"]
ev -.-> s4
Abbildung 19: Deaktivieren Sie Nicht-Microsoft-Erweiterungen vorübergehend und suchen Sie binär; bei einem Absturz nutzen Sie auch die Ereignisanzeige.
8.4. Windows Sandbox ist zur Prüfung praktisch
Die Prüfung der Shell-Integration beruht darauf, „auf einer sauberen Umgebung installieren → bedienen → deinstallieren → Reste null“ zu bestätigen. Praktisch hier ist Windows Sandbox (Pro/Enterprise/Education): jeder Start bringt in wenigen Sekunden ein brandneues Einweg-Windows, sodass Sie Tests zur Installationsprogramm-Registrierung und zum Aufräumen beliebig oft fahren können. Schließen Sie es, und alles verschwindet, daher eignet es sich auch zur Untersuchung von Rest-Registrierung.15
9. Zusammenfassung
- Dateizuordnung ist die Dreischichtstruktur „Erweiterungsschlüssel → ProgID → Verb“, und HKCR ist eine zusammengeführte Ansicht von HKLM-/HKCU-Classes. Nennen Sie das Schreibziel ausdrücklich, und setzen Sie
%1immer in Anführungszeichen. - Die Standard-App ist so entworfen, dass sie der Benutzer wählt, und kann nicht von einem Programm geändert werden. Die Aufgabe des Installationsprogramms ist, sich korrekt als Kandidat zu registrieren.
- Eine klassische Shell-Erweiterung ist eine In-Process-COM-DLL, die in den Explorer geladen wird. Ein Absturz oder eine Verzögerung greift auf das Ganze über; 64-Bit ist erforderlich; verwalteter Code ist nicht unterstützt; die Implementierung in nativem C++ ist die Regel.
- Unter Windows 11 ist das Kontextmenü in zwei Teile zerfallen. Einen eigenen Befehl ins neue Menü zu setzen erfordert IExplorerCommand plus ein MSIX-Manifest; klassisches IContextMenu wird auf die Seite „Weitere Optionen anzeigen“ verschoben.
- Für eine App, die nicht MSIX werden kann, ist das Holen der Identität mit einem Sparse-Paket (MSIX mit externem Speicherort) die realistische Antwort.
- Wenn Sie nur „mit dieser App öffnen“ wollen, reichen eine Zuordnung und ein statisches Verb immer noch. Vom einfachsten Mittel zu starten ist auch die offizielle Richtlinie.
- Nach Registrierung, Änderung oder Löschung benachrichtigen Sie mit SHChangeNotify; bei der Deinstallation löschen Sie die ProgID, lassen aber den Standardwert des Erweiterungsschlüssels. Windows Sandbox ist zur Prüfung praktisch.
Wenn ein Windows-11-PC-Austausch Sie merken ließ, dass „das Menü versteckt wurde“, bestätigen Sie zuerst, welches von (a), (b) und (c) in der Entscheidungstabelle von Kapitel 6 es ist. Sie sollten den Umfang der Arbeit an Ort und Stelle abschätzen können.
Verwandte Artikel
- Was sind COM / ActiveX / OCX? – Unterschiede und Zusammenhänge im Überblick
- Was ist Reg-Free COM - COM ohne Registrierung nutzen
- Registry-32-Bit/64-Bit-Umleitung und Virtualisierungsfallen — Wow6432Node und das Problem „Der Wert, den ich geschrieben habe, ist nicht da“
- Windows-App-Verteilung wählen – MSI/MSIX/ClickOnce/xcopy/eigener Updater
- Abwärtskompatibilität von DLL- und COM-Schnittstellen — Eine Entscheidungstabelle dafür, welche Änderungen Aufrufer brechen
- Wie Windows-App-Kompatibilität funktioniert — alte Apps mit Kompatibilitätsmodus, Shims und Compatibility Administrator am Leben halten
Verwandte Beratungsbereiche
KomuraSoft LLC übernimmt Entwurf und Implementierung von Dateizuordnung, Kontextmenüs und Shell-Erweiterungen für Geschäftsanwendungen; das Ansteuern des neuen Windows-11-Kontextmenüs (Umzug zu IExplorerCommand, Einführung eines Sparse-Pakets); die Prüfung von Registrierung und Aufräumen eines vorhandenen Installationsprogramms; und die Ursachenuntersuchung, wenn der Explorer schwer ist oder abstürzt. Es ist in Ordnung, damit zu beginnen, was mit „dem Menü, das unter Weitere Optionen anzeigen versteckt wurde“ zu tun ist.
- Windows-App-Entwicklung
- Nutzung und Migration bestehender Assets
- Technische Beratung und Design-Review
- Kontakt
Quellen
-
Microsoft Learn, File Types. Zur Struktur eines Erweiterungsschlüssels, der auf eine ProgID zeigt; OpenWithProgIds; die Teilung der Registrierung zwischen HKLM/HKCU\Software\Classes; das Aufrufen von SHChangeNotify(SHCNE_ASSOCCHANGED) nach einer Zuordnungsänderung; und das Löschen der ProgID bei der Deinstallation bei Belassen des Standardwerts des Erweiterungsschlüssels. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, HKEY_CLASSES_ROOT Key. Dazu, dass HKEY_CLASSES_ROOT eine zusammengeführte Ansicht von HKLM\Software\Classes und HKCU\Software\Classes ist; benutzerseitige Definitionen Vorrang vor maschinenseitigen haben; und die Verteilungsregeln beim Schreiben. ↩ ↩2
-
Microsoft Learn, Windows app defaults platform. Dazu, dass das Ändern der Standard-App so entworfen ist, dass es nur über die Systemeinstellungen-UI geschieht; Benutzerdaten verschleiert und von einem Filtertreiber (UCPD.sys) schreibgeschützt sind; die registrierungsbasierte Änderung nicht unterstützt ist; und in einer verwalteten Umgebung Gruppenrichtlinie / MDM-Richtlinie genutzt wird. ↩ ↩2
-
Microsoft Learn, Working with Shell Extensions. Zu den Arten von Shell-Erweiterungshandlern; einer Erweiterung als In-Process-COM-DLL, die in den Explorer (und in Prozesse, die die Shell hosten) geladen wird, sodass ein Absturz oder Hänger auf den Explorer als Ganzes übergreift; der Registrierung mit ThreadingModel=Apartment; und dem Erwägen einer einfacheren Alternative vor einer Shell-Erweiterung. ↩ ↩2 ↩3
-
Microsoft Learn, Guidance for Implementing In-Process Extensions. Dazu, dass Microsoft eine In-Process-Shell-Erweiterungsimplementierung in verwaltetem Code nicht empfiehlt und nicht unterstützt; Gründe einschließlich CLR-Versionskollisionen, Wiedereintritt und nicht deterministischer Objektlebensdauer; und verwalteter Code für eine Out-of-Process-Erweiterung (einen Vorschauhandler oder einen Start von shell\verb\command) akzeptabel ist. ↩ ↩2 ↩3
-
Windows Developer Blog, Extending the Context Menu and Share Dialog in Windows 11. Zum Entwurf des neuen Windows-11-Kontextmenüs; der Erweiterung über IExplorerCommand plus App-Identität; dem Platzieren von „Öffnen“ und „Öffnen mit“ oben; dem Sammeln mehrerer Befehle in einem App-Namen-Flyout; und klassischen IContextMenu-Erweiterungen, die unter „Weitere Optionen anzeigen“ (Umschalt+F10) als Windows-10-Menü geladen werden. ↩ ↩2 ↩3
-
Microsoft Learn, Add a File Explorer context menu command to a packaged desktop app. Dazu, dass die Registrierung im neuen Windows-11-Kontextmenü mit einer IExplorerCommand-Implementierung plus windows.comServer plus einer desktop4:FileExplorerContextMenus-Manifestdeklaration geschieht; ItemType *, Directory oder Directory\Background angeben kann; die DLL-Architektur abzustimmen ist; Methoden zum Menüaufbau schnell zu halten sind; eine nicht verpackte App mit einem Sparse-Paket abgedeckt wird; ein Explorer-Neustart manchmal nötig ist, damit die Registrierung greift; und eine Dateizuordnung keine Allzweck-Menüerweiterung ist. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Microsoft Learn, Grant package identity by packaging with external location. Zum Holen von Paketidentität durch Registrieren eines Pakets mit externem Speicherort (Sparse-Paket) ohne Änderung des vorhandenen Installationsprogramms; der Verfügbarkeit ab Windows 10 Version 2004; und Windows-Funktionen, die Identität erfordern (Kontextmenüregistrierung, Benachrichtigungen und Ähnliches), die nutzbar werden. ↩ ↩2 ↩3
-
Microsoft Learn, Choosing a Static or Dynamic Shortcut Menu Method. Zur Wahl der einfachsten statischen-Verb-Methode, die die Anforderungen erfüllt; IContextMenu als der mächtigsten, aber auch komplexesten und zur nicht empfohlenen Seite klassifizierten; und IExplorerCommand/IExplorerCommandState als der empfohlenen Methode. ↩ ↩2
-
Microsoft Learn, SHChangeNotify function. Zur Erhebung des Ereignisses SHCNE_ASSOCCHANGED, das das System über eine Dateizuordnungsänderung benachrichtigt, und zur Nutzung, damit die Shell die Änderung merkt. ↩ ↩2
-
Microsoft Learn, Application Registration. Dazu, dass die Registrierung einer ausführbaren Datei über den Unterschlüssel App Paths empfohlen wird; die Rolle des Unterschlüssels Applications; die Verbregistrierung über SystemFileAssociations; und die Priorität der ProgID und zugehöriger Informationen, wenn die Standard-App wechselt. ↩
-
Microsoft Learn, Verbs and File Associations. Dazu, dass ein Verb eine Aktion ist, die auch von ShellExecuteEx genutzt wird; Elemente einer Befehlszeichenfolge, die ein Leerzeichen enthalten können, in Anführungszeichen gesetzt werden müssen und “%1” immer quoted geschrieben wird; und die Registrierung einer Standardprozedur unter HKCR\Applications. ↩
-
Microsoft Learn, IExplorerCommand interface. Zur Methodenzusammensetzung von GetTitle, GetIcon, GetState, Invoke, EnumSubCommands und Ähnlichem; Methoden, die auf dem UI-Thread aufgerufen werden und daher nicht mit Netzwerkressourcen kommunizieren dürfen; und der Verfügbarkeit ab Windows Vista. ↩
-
Microsoft Learn, Windows Sandbox. Dazu, ein wegwerfbares, isoliertes Windows in wenigen Sekunden starten zu können, alle Änderungen beim Schließen verworfen werden, es sich für Softwaretests und Installationsprogrammprüfung eignet, und es auf Pro/Enterprise/Education verfügbar ist. ↩
Verwandte Artikel
Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.
Wie Zwischenablage und Drag-and-Drop funktionieren — OLE-Datenübertragung in Geschäftsanwendungen richtig behandeln
Eine Excel-Tabelle einfügen und die Formatierung fällt auseinander; die Quell-App schließen und Sie können nicht mehr einfügen — beides k...
Windows-App-Outsourcing und Auftragsentwicklung: Was Sie vor der Beauftragung klären sollten
Bevor Sie die Entwicklung einer Windows-App outsourcen oder in Auftrag geben, sollten Sie folgende Punkte klären: Überarbeitung bestehend...
Die seltsame Liebe eines Entwicklers, oder: Wie ich lernte, mir keine Sorgen mehr zu machen, und Windows lieben lernte
Windows ist umständlich. Aber diese Umständlichkeit ist auch die Umständlichkeit eines Betriebssystems, das jahrzehntelang reale Geschäft...
Warum Windows die Meldung „Der Computer wurde durch Windows geschützt“ anzeigt
Warum SmartScreen-Warnungen bei der Verteilung von Windows-Apps auftreten — eine praxisnahe Einordnung von Codesignierung, EV-/OV-Zertifi...
Die Win32-Thread-Pool-API — Nebenläufigkeit ohne eigene Threads, über CreateThreadpoolWork
Verstreuen Sie CreateThread-Aufrufe über Ihren nativen Code? Dieser Artikel erklärt die in Vista neu entworfene Win32-Thread-Pool-API — d...
Verwandte Themen
Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.
Technische Windows-Themen
Portal zu Windows-Entwicklung, Fehleranalyse und der Nutzung bestehender Assets.
ActiveX-Migration
Entscheidungen zum Beibehalten, Kapseln oder Ersetzen von COM / ActiveX / OCX.
Leistungen zu diesem Thema
Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.
Windows-App-Entwicklung
Geschäftsanwendungen, Geräteintegration und Kommunikationstools von den Anforderungen bis zur Umsetzung.
Wartung und Modernisierung von Windows-Software
Funktionserweiterungen, Wartung und schrittweise Modernisierung bestehender Windows-Software.
Häufige Fragen
Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.
- Warum erscheint der Kontextmenüeintrag unserer App unter Windows 11 nur unter „Weitere Optionen anzeigen“?
- Weil unter Windows 11 das Kontextmenü des Datei-Explorers in zwei Schichten zerfallen ist, alt und neu. Im neuen Menü erscheinen nur Befehle, die die Schnittstelle IExplorerCommand implementieren und in einem MSIX-Paketmanifest registriert sind (= die eine Paketidentität haben). Klassische IContextMenu-basierte Shell-Erweiterungen wurden ins alte Menü verschoben, das Sie mit „Weitere Optionen anzeigen“ (Umschalt+F10) öffnen. Die Erweiterung selbst ist nicht kaputt, sie funktioniert vorerst weiter, aber wenn Sie sie im neuen Menü wollen, brauchen Sie eine Migration zu IExplorerCommand und entweder die Verpackung als MSIX oder die Vergabe der Identität mit einem Sparse-Paket.
- Kann das Installationsprogramm unsere App als Standard-App für eine Datei festlegen (die App, die beim Doppelklick öffnet)?
- Nein. Die Wahl der Standard-App ist so entworfen, dass sie der Benutzer trifft, und Windows unterstützt das Ändern der Standard-App von nirgendwo sonst als der Systemeinstellungen-UI. Die UserChoice-Informationen, die die Wahl jedes Benutzers halten, sind verschleiert, und ein Filtertreiber (UCPD.sys) schützt sie zusätzlich schreibend vor Apps. Was ein Installationsprogramm tun kann, ist, eine ProgID und Verben zu registrieren, sich zu OpenWithProgIds hinzuzufügen, damit es als Kandidat unter „Öffnen mit“ erscheint, und den Benutzer zur Seite Standard-Apps zu lenken. Die korrekte Implementierung ist nicht, die Vorgabe zu stehlen, sondern bereit zu sein, gewählt zu werden.
- Darf ich eine Shell-Erweiterung in verwaltetem Code wie C# schreiben?
- Microsoft hat klar gesagt, dass das Schreiben einer In-Process-Shell-Erweiterung (eines Kontextmenühandlers, eines Symbolhandlers und Ähnlichem) in verwaltetem Code nicht empfohlen und nicht unterstützt wird. Die Erweiterung wird in den Explorer und in den Prozess jeder App geladen, die einen gemeinsamen Dateidialog öffnet, sodass CLR-Versionskollisionen, Wiedereintritt und nicht deterministische Objektlebensdauer die Host-App instabil machen. Die Regel ist eine Implementierung in nativem C++. Eine normale EXE, die von einem Verb-Command gestartet wird, oder eine Out-of-Process-Erweiterung wie ein Vorschauhandler, der in einem eigenen Prozess läuft, ist in verwaltetem Code in Ordnung.
- Was ist ein Sparse-Paket (MSIX mit externem Speicherort)?
- Ein kleines MSIX-Paket, das keine App-Dateien enthält, nur ein Manifest (Identitätsinformationen). Für eine App, die auf gewöhnliche Weise mit einem vorhandenen Installationsprogramm (MSI, Inno Setup und Ähnliches) installiert wird, registrieren Sie es mit Add-AppxPackage -ExternalLocation auf den Installationsordner, und die App erwirbt Paketidentität und kann Funktionen nutzen, die Identität erfordern, etwa die Registrierung im neuen Windows-11-Kontextmenü und Toastbenachrichtigungen. Es ist ab Windows 10 Version 2004 verfügbar, und das Paket braucht eine Codesignatur, der auf dem Zielrechner vertraut wird. Es ist die realistische Option, wenn Sie die neue Menüunterstützung wollen, ohne die gesamte Verteilung auf MSIX umzustellen.
- Was soll ich tun, wenn ein Kontextmenüeintrag doppelt erscheint oder nicht verschwindet?
- Isolieren Sie zuerst die Ursache, indem Sie prüfen, auf welchem Menü er erscheint: dem neuen oder dem alten (Weitere Optionen anzeigen). Die typische Doppelanzeige ist, dass eine klassische Registrierungsregistrierung und eine MSIX-Manifestregistrierung koexistieren, oder dass eine ProgID- oder Erweiterungs-CLSID-Registrierung bei der Deinstallation zurückgeblieben ist. Nach dem Ändern von Zuordnungen verdächtigen Sie auch ein vergessenes SHChangeNotify(SHCNE_ASSOCCHANGED); direkt nach der Paketregistrierung ein vergessenes Explorer-Neustart. Wenn das immer noch nicht löst, deaktivieren Sie vorübergehend Nicht-Microsoft-Erweiterungen in ShellExView und identifizieren Sie die Täter-DLL per binärer Suche.
Autorenprofil
Profilseite des Artikelautors.
Go Komura
Geschäftsführer von KomuraSoft LLC
Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.