Проводник Windows 11 получил новое контекстное меню и способы интеграции приложений в него. Поначалу в меню было пустовато. Но со временем разработчики освоились и начали добавлять туда свои программы. Сегодня я расскажу, как убрать ненужные пункты, чтобы улучшить UX и ускорить открытие меню. И нет, старые утилиты от NirSoft вам с этим не помогут.
[+] Сегодня в программе
- История вопроса: меню новое и старое
- Как приложения регистрируются в контекстном меню
- Как вручную удалить пункт приложения из контекстного меню
- Шаг 1 — Определите уникальную часть имени приложения
- Шаг 2 – Откройте манифест и найдите CLSID
- Шаг 3 – Внесите изменения в реестр
- Скрипт PowerShell для удаления приложений из контекстного меню
- Случаи, в которых этот способ не работает
- Мое мнение о ситуации с контекстными меню
- Заключение
История вопроса: меню новое и старое
Старое меню исторически вызывались правой кнопкой мыши (ПКМ) на файле или папке, а также сочетанием клавиш Shift + F10. Теперь оба варианта вызывают новое меню. Старое напрямую открывается сочетанием Shift + ПКМ, а также в сторонних файловых менеджерах (например, в Total Commander).
На картинке контекстное меню MP3-файла в папке OneDrive. Количество приложений в списке зависит от типа файла (например, ClipChamp и Mp3tag связаны с mp3, но не с txt). Если файл или папка входят в сферу облачного диска, в меню появляются пункты для управления состоянием объекта.
Все написанное в этой статье также применимо к контекстному меню папки и фона папки. Просто пунктов там поменьше обычно.
Основным мотивом для изменений стало безобразное разрастание меню. Осенью 2021 года я писал в канале Telegram:
Действительно, для некоторых типов файлов меню уже перестали помещаться в экран по вертикали, даже если не особо злоупотреблять сторонними программами. То есть Microsoft к этому тоже прикладывает руку. А как меню выглядит при двух архиваторах и паре облачных дисков, страшно представить :)
Для борьбы с разрастанием меню решили лечить конкретные болезни:
- неподписанные приложения (для регистрации в новом меню фактически нужна цифровая подпись)
- «варварская» регистрация в разделе реестра
HKCR\shell\*\
(Notepad++) - нежелание разработчиков писать толковое расширение оболочки, что выливается в наполнение меню множеством пунктов вместо раскрывающегося списка (OneDrive↑)
Как приложения регистрируются в контекстном меню
Это необходимо знать, если мы хотим отменить регистрацию. У Microsoft исторически была весьма развесистая документация по контекстным меню. В выходом новой ОС компания опубликовала рамочный пост в блоге для разработчиков: Extending the Context Menu and Share Dialog in Windows 11. Там пара ссылок на документацию (не приводящих четко к цели), общие фразы и лучшие практики – для тех, кто в теме.
Теперь по гайдлайнам следует регистрировать программу в меню с помощью манифеста. Центральное хранилище манифестов приложений – папка C:\Program Files\WindowsApps
. Даже если зарегистрированное классическое приложение установлено не из магазина, у него будет там своя подпапка.
Для доступа в эту системную папку необходимы правa администратора. Запускайте с полными правами PowerShell, сторонний файловый менеджер или проводник.
В папке магазинного приложения может быть побольше ресурсов, а у классических самый минимум – значки, подпись, манифест. На картинке Notepad++ (я не призываю его блокировать, это просто пример).
Манифест приложения – это файл AppxManifest.xml
. В узле Extensions
прописаны расширения оболочки.
<Extensions> <desktop4:Extension Category="windows.fileExplorerContextMenus"> <desktop4:FileExplorerContextMenus> <desktop5:ItemType Type="*"> <desktop5:Verb Id="EditWithNotepadPlusPlus" Clsid="E6950302-61F0-4FEB-97DB-855E30D4A991" /> </desktop5:ItemType> </desktop4:FileExplorerContextMenus> </desktop4:Extension> <com:Extension Category="windows.comServer"> <com:ComServer> <com:SurrogateServer DisplayName="Notepad++ Shell Extension"> <com:Class Id="E6950302-61F0-4FEB-97DB-855E30D4A991" Path="NppShell.dll" ThreadingModel="STA"/> </com:SurrogateServer> </com:ComServer> </com:Extension> </Extensions>
В частности, здесь программа прописывается в:
- старое меню — узел
desktop4:Extension Category="windows.fileExplorerContextMenus"
- новое меню – узел
com:Extension Category="windows.comServer"
Ключом к регистрации служит уникальный идентификатор – CLSID. Так, у Notepad++ идентификатор E6950302-61F0-4FEB-97DB-855E30D4A991
.
CLSID приложения — это все что нужно знать, чтобы заблокировать отображение программы в контекстном меню! Как правило, приложения используют одно и то же расширение оболочки для регистрации в обоих меню. В этом случае блокировка по CLSID уберет пункты приложения из нового и старого меню!
У Notepad++ только один CLSID, и это вполне типичный случай. Однако таких CLSID может быть и несколько – например, у OneDrive их почти два десятка.
Как вручную удалить пункт приложения из контекстного меню
Я объясню ручной способ, а ниже предоставлю скрипт, который решает вопрос за пару секунд одной командой сразу для нескольких приложений. Но сначала расставлю грабли:
- для новых меню способ работает только с приложениями, которые зарегистрировались помощью манифеста
- побочным или наоборот желаемым эффектом может быть удаление пунктов программы из старого контекстного меню, когда зарегистрирован единый CLSID
- у OneDrive и других облачных провайдеров есть нюанс, который я разберу ниже
Задача решается в три простых шага. Все команды выполняйте в PowerShell от имени администратора.
Шаг 1 — Определите уникальную часть имени приложения
Она понадобится для поиска конкретного манифеста. В большинстве случаев это не нужно, но полезно при наличии программ с частично совпадающими именами.
Выполните команду ниже, заменив notepad
на часть имени своего приложения:
Get-AppxPackage | where PackageFamilyname -match 'notepad' | ft Name Name ---- NotepadPlusPlus Microsoft.WindowsNotepad
В моем примере нашлось два приложения. Уникальной частью имени будет NotepadPlusPlus
или WindowsNotepad
.
Шаг 2 – Откройте манифест и найдите CLSID
Выполните команду ниже, заменив NotepadPlusPlus
на уникальную часть имени своего приложения:
Get-ChildItem -Force "C:\Program Files\WindowsApps\*NotepadPlusPlus*\AppxManifest.xml" | ForEach-Object {explorer $_.FullName}
Манифесты откроются в программе, ассоциированной с XML-файлами. У классического приложения, скорее всего, один манифест. Но у магазинных приложений их может быть несколько, причем только один содержит сведения о регистрации в контекстном меню.
Поиском в манифесте найдите узел com:SurrogateServer
и скопируйте оттуда все CLSID.
Шаг 3 – Внесите изменения в реестр
В Windows исторически предусмотрен раздел реестра, с помощью которого можно блокировать работу расширений оболочки.
- Перейдите в раздел реестра (создайте при отсутствии):
HKCU\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked
В этом разделе блокируются расширения оболочки текущего пользователя. Если вы хотите заблокировать их для всех пользователей, замените HKCU на HKLM. - Для каждого найденного CLSID создайте строковый параметр:
- Имя: CLSID в фигурных скобках. Например, для Notepad++ это
{E6950302-61F0-4FEB-97DB-855E30D4A991}
- Значение: необязательно, но стоит указать имя программы
Это все! Для вступления изменений в силу перезапустите проводник или выйдите из системы.
Чтобы отменить внесенные изменения, удалите отдельные параметры или весь раздел реестра.
Скрипт PowerShell для удаления приложений из контекстного меню
Я написал скрипт PowerShell, который автоматизирует ручной способ выше и обрабатывает сразу несколько приложений.
Скачайте скрипт context-menu.zip, разблокируйте его, потом выполняйте.
Запуск скрипта без параметров выведет имена приложений, у которых зарегистрированы расширения оболочку, наряду с идентификаторами (CLSID). Чтобы убрать программы из контекстного меню передавайте, скрипту их имена через запятую параметром -Apps
так:
.\context-menu.ps1 -Apps onedrive,windowsnotepad,skype
Скрипт целиком.
<# .SYNOPSIS Removes application entries from the Windows file and folder context menus. .DESCRIPTION The script removes app context menu items from the new menu in Windows 11 and legacy menu in Windows 11/10. The script takes care only of the apps registered via a manifest. It collects extensions IDs from app manifests and blocks them via Windows Registry. .PARAMETER Apps Comma-separated list of app names to remove from the context menu. If not provided, the script lists all registered apps and their CLSIDs. .PARAMETER Scope Accepts HKLM (all users) or HKCU (current user, default behavior). .EXAMPLE PS> .\context-menu.ps1 Lists all registered app names and their CLSIDs. .EXAMPLE PS> .\context-menu.ps1 -Apps onedrive,windowsnotepad,skype Removes the listed apps from the current user context menu. Unique partial names are ok. .EXAMPLE PS> .\context-menu.ps1 -Apps onedrive,windowsnotepad,skype -Scope HKLM Removes the listed apps from all users context menu. Unique partial names are ok. .LINK _https://www.outsidethebox.ms/22361/ #> param( [Parameter()] [string[]]$Apps, [string]$Scope = 'HKCU' ) # script scope - HKCU (current user, default) or HKLM (all users) if ( ($Scope -ne 'HKCU') -and ($Scope -ne 'HKLM') ) { Write-Error 'Unacceptable scope. Use HKLM or HKCU.' -ErrorAction Stop } $regpath = "$($Scope):Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked" New-Item -Path $(Split-Path $regpath -Parent) -Name $(Split-Path $regpath -Leaf) -ErrorAction SilentlyContinue | Out-Null # if no app list supplied, we'll get all registered apps and CLSIDs if (-Not ($PSBoundParameters.ContainsKey('Apps'))) { Write-Host "Here's the list of context menu apps and their CLISDs:" $Apps = '*' } foreach ($app in $Apps) { # Get all manifests with registered context menu extensions $manifests = Get-ChildItem -Force "C:\Program Files\WindowsApps\*$App*\AppxManifest.xml" foreach ($manifest in $manifests) { $xml = [xml] (Get-Content ($manifest).FullName) $elem = $xml.get_DocumentElement() #Get app name and extension CLSIDs $app = $elem.Identity.Name $clsids = $elem.Applications.Application.Extensions.Extension.comServer.SurrogateServer.class.id if ($Apps -ne '*') { # If apps were supplied, write CLSIDs to the registry foreach ($clsid in $clsids) { $name = '{' + $clsid + '}' New-ItemProperty -Path $regpath -Name $name -Type String -Value $app -Force | Out-Null } } else { # Output apps and their CLSIDs foreach ($clsid in $clsids) { Write-Host "{$($clsid)} $($app)" } } } } if ($Apps -ne '*') { # Restart explorer for the current user to apply the changes Get-Process explorer -IncludeUserName | where UserName -match $ENV:USERNAME | Stop-Process # Export REG-file to %temp% $regexportpath = $regpath.replace(':','\') reg export "$regexportpath" "$ENV:TEMP\context-menu.reg" /y }
Прокомментирую на русском логику скрипта.
- Создается раздел реестра, если его нет. Как и в ручных инструкциях, изменения вносятся в пользовательский раздел HKCU. Если вы хотите навязать свою волю всем пользователям, выполняйте скрипт с параметром
-Scope HKLM
. В качестве полезного упражнения можете сделать параметр скрипта для этой цели. - Если скрипт запускается без параметров, выполняется выборка по всем манифестам в папке WindowsApps. Иначе отбираются только перечисленные в параметре
-Apps
приложения. - В каждом манифесте скрипт опирается на схему XML, добираясь до узла
comServer
и далееcom:Class Id
, чтобы извлечь оттуда CLSID. Я раньше не сталкивался с именами узлов, содержащими двоеточия или/и пробелы —com:Class Id
. Но все оказалось просто – для выборки важна лишь последняя часть –Id
в этом случае. - Далее простой перебор всех найденных CLSID и запись значений в реестр. Если скрипт запускался без параметров, он просто выводит имена приложений и их CLSID на экран.
- Если создавались записи в реестре, скрипт перезапускает проводник для вступления изменений в силу. Также во временную папку экспортируется REG-файл на память.
Случаи, в которых этот способ не работает
Есть сценарии, в которых этот способ не поможет убрать некоторые или все пункты приложения из контекстного меню.
OneDrive и другие облачные провайдеры
Этот раздел про OneDrive, iCloud Drive и Photos, Nextcloud и другие облачные диски, опирающиеся на API Windows.
Если вызывать контекстное меню из папки облачного диска, его пункты отобразятся в отдельном блоке. Причем в нем два раздела без видимой границы между ними.
Здесь:
- Управление состоянием файлов по запросу. В соответствии с документацией, эти пункты появляются автоматически при регистрации приложения в качестве провайдера облачных файлов.
- Регистрация в контекстном меню с помощью манифеста, т.е. описанным выше способом.
Следуя моим инструкциям, вы сможете убрать только второй блок. Для удаления первого блока потребуется отменить регистрацию приложения в качестве облачного провайдера, что не имеет смысла.
Устаревшие способы регистрации в старом контекстном меню
Выше я показал, как с помощью манифеста программа одновременно регистрируется в новом и старом контекстном меню. Это хорошее решение для обратной совместимости, в том числе для:
- Windows 10, где нового меню нет
- сторонних файловых менеджеров, которые сразу показывают старое меню (Total Commander)
Но старые способы никто не убирал, просто они работают только для старого меню.
Раздел реестра shell
Ранее я упомянул «варварскую» регистрацию путем прямой записи в HKCR\*\shell
. И Notepad++ — отличный пример. Да, у него есть расширение оболочки, но здесь он прописывается для всех типов файлов напрямую.
Описанный в статье метод тут не поможет. Утилиты ShellMenuView и ShellExView против этого тоже бессильны. Надо удалять запись из реестра.
Впрочем, ShellMenuView вполне справляется с приложениями, которые применяет более щадящий метод регистрации — только для своих типов файлов. Например, VLC создает много записей вида HKEY_CLASSES_ROOT\VLC.mxf.Document\shell\enqueue\command
.
Раздел реестра shellex
Также заметьте на скриншоте выше↑ пункты WinRAR, прописанные в соседнем разделе HKCR\*\shellex
. Раздел shellex
исторически предназначен для регистрации расширения оболочки.
WinRAR — любопытный пример программы с опцией двойной регистрации.
По умолчанию приложение регистрируется новым методом, но в установщике есть пункт для старого! Активировав его, вы получите дополнительный блок в старом меню. На картинке нижний блок относится к устаревшему методу регистрации расширения оболочки в shellex
.
Однако WinRAR использует один и тот же CLSID для обоих методов, поэтому блокировка в реестре убирает оба пункта. Благодаря наличию записей в разделе HKCR\*\shellex
, утилита ShellExView отобразит это расширение оболочки и тоже выключит все пункты.
Резюме: зарегистрированные только по-старинке программы нужно выпиливать старыми же способами.
Мое мнение о ситуации с контекстными меню
Этот материал остался бы неполным, не коснись я двух тесно связанных тем. Это производительность новых меню и недостаточное внимание к ним разработчиков.
О производительности меню
По ходу работы над статьей и скриптом я поднял тему неприемлемой производительности новых контекстных меню в канале Telegram.
О разработчиках
Между тем, некоторые (многие?) разработчики не торопятся добавлять свои программы в новое меню. 7-Zip Игоря Павлова — яркий пример. И не случайно магазинный форк NanaZip так популярен — он дружит с новым меню!
Игнорирование гайдлайнов Microsoft разработчиками — это полбеды. Куда хуже, что тем самым они забивают на базовые нужды своих пользователей. Контекстное меню — важная часть пользовательского опыта, особенно у архиваторов.
Вне зависимости от производительности оболочки и личного отношения к изменениям надо доставлять наилучший опыт людям, для которых в конце концов и создаются программы!
Заключение
Oпрос читателей канала показал, что как минимум 6 из 10 человек не устраивает скорость открытия меню и/или лишние пункты в нем. Воспользовавшись моим решением, вы сможете снять по крайней мере часть этих проблем. А для борьбы со старыми методами регистрации сгодятся уже хорошо зарекомендовавшие себя утилиты.
Виталий Орехов
Если к тормозам нового контекстного меню прибавить установку Windows 11 на системы, где процессор явно мимо системных требований, то получается великолепный рецепт ночного ужаса. :)
Vadim Sterkin
Ну у меня как раз явно:) Но меню же не из-за этого тормозит. Да и системные требования обусловлены не производительностью, а безопасностью.
Ночной ужас получается, кстати, когда тестируешь переустановку поверх на виртуальной машине и получаешь отлуп из-за того, что не соответствует требованиям процессор… на хосте!
Aqu Ila
Это еще фигня. Вот проводник насколько долго открывается, это капец. Да, он красиво появляется с анимацией, но эта прогрузка ярлыков и значеов, будто они в формате png или даже gif, которые пытаешься открыть в opera 12 на pentium 4…
Vadim Sterkin
Это связанные вещи, звенья одной цепи. Об этом я пишу во врезке — пост telegram.
Просто в случае с контекстным меню мы можем слегка его разгрузить и ускорить. Но в целом медленную оболочку этим не исправишь.
Lecron
Осталось сделать контекстное меню для контекстного меню с пунктами Изменить, Удалить, Переместить и т.д. :))
Vadim Sterkin
Не понял. Эти пункты сверху же.
Lecron
Открываете контекстное меню. Тыкате ПКМ на пункт этого меню — открывается еще одно. Для работы с этим пунктом меню, а не файлом.
Vadim Sterkin
Я не понял смысла этих манипуляций. Не то чтобы я фанат этих кнопок, которые они приделали сверху меню… особенно ужасно это выглядит, если открывать с клавиатуры и отобразить подсказки к нему.
Если это шутка то не смешная, на фоне того что происходит с оболочкой…
Lecron
Это скорее ирония. Как раз на фоне того, что происходит с оболочкой.
Но только наполовину ирония. На вторую — разумное пожелание.
Вызовите контекстное меню у иконки Проводника на панели задач. Появятся «закрепленные», «часто используемые» и служебный блок.
Теперь вызовите контекстное меню для любого из пунктов. Появятся «открыть», «закрепить», «открепить», «свойства».
Так почему бы при клике ПКМ например на «Edit in Notepad» не появиться меню «удалить», «переместить», «изменить»?
Николай
Спасибо за скрипт.
Я работаю с обычным профилем пользователя и мне пришлось сделать своего пользователя админом и запустить скрипт с админскими правами от себя чтобы он сработал.
Vadim Sterkin
Николай, я не помню проверял ли под обычным пользователем. Но под админом с обычными правами запускался нормально. Возможно, для изменения политики запуска скриптов надо было от админа.