Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Некоторые приложения Windows определяют расширения проводника, добавляющие записи контекстного меню, позволяющие клиентам выполнять параметры, связанные с приложением. Старые технологии развертывания приложений Windows, такие как MSI и ClickOnce, определяют расширения проводника через реестр. В реестре есть ряд ячеек, которые управляют расширениями Проводника и другими типами расширений оболочки. Эти установщики обычно создают ряд разделов реестра, чтобы настроить разные элементы и включить их в контекстное меню.
Если вы упаковаете приложение Windows с помощью MSIX, реестр виртуализирован, поэтому приложение не может зарегистрировать расширения проводника через реестр. Вместо этого необходимо определить расширения проводника с помощью расширений пакетов, которые определяются в манифесте пакета. В этой статье описано несколько способов этого.
Вы можете найти полный пример кода, использованный в этой статье на GitHub.
Добавление записи контекстного меню, поддерживающей параметры запуска
Одним из самых простых способов интеграции с проводником является определение расширения пакета, добавляющего приложение в список доступных приложений в контекстном меню, когда пользователь щелкает правой кнопкой мыши определенный тип файла в проводнике. Если пользователь открывает приложение, расширение может передавать параметры приложению.
Этот сценарий имеет несколько ограничений:
- Он работает только в сочетании с функцией сопоставления типов файлов. Дополнительные параметры в контекстном меню можно отобразить только для типов файлов, связанных с основным приложением (например, приложение поддерживает открытие файла, дважды щелкнув его в проводнике).
- Параметры в контекстном меню будут отображаться только в том случае, если ваше приложение задано в качестве приложения по умолчанию для этого типа файла.
- Единственное поддерживаемое действие — запустить основной исполняемый файл приложения (то есть тот же исполняемый файл, который подключен к записи меню "Пуск"). Однако каждое действие может задавать разные параметры, которые можно использовать при запуске приложений, чтобы понять, какое именно действие вызвало выполнение, и выполнять разные задачи.
Несмотря на эти ограничения, этот подход достаточно для многих сценариев. Например, если вы создаете редактор изображений, вы можете легко добавить запись в контекстное меню, чтобы изменить размер изображения, который запустит редактор изображений непосредственно с помощью мастера, чтобы запустить процесс изменения размера.
Реализовать пункт контекстного меню
Чтобы поддержать этот сценарий, добавьте элемент расширения категории windows.fileTypeAssociation
в манифест пакета. Этот элемент должен быть добавлен в качестве дочернего к элементу Extensions в рамках элемента Application.
В следующем примере демонстрируется регистрация приложения, которое включает контекстные меню для файлов с расширением .foo
. В этом примере указывается .foo
расширение, так как это поддельные расширения, которые обычно не зарегистрированы в других приложениях на любом компьютере. Если вам нужно управлять типом файла, который уже может быть принят (например, .txt или .jpg), помните, что вы не сможете видеть этот параметр, пока приложение не будет задано как по умолчанию для этого типа файла. Этот пример представляет собой фрагмент из файла Package.appxmanifest в соответствующем примере на GitHub.
<Extensions>
<uap3:Extension Category="windows.fileTypeAssociation">
<uap3:FileTypeAssociation Name="foo" Parameters=""%1"">
<uap:SupportedFileTypes>
<uap:FileType>.foo</uap:FileType>
</uap:SupportedFileTypes>
<uap2:SupportedVerbs>
<uap3:Verb Id="Resize" Parameters=""%1" /p">Resize file</uap3:Verb>
</uap2:SupportedVerbs>
</uap3:FileTypeAssociation>
</uap3:Extension>
</Extensions>
В этом примере предполагается, что следующие пространства имен и псевдонимы объявляются в корневом <Package>
элементе манифеста.
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap uap2 uap3 rescap">
...
</Package>
Элемент FileTypeAssociation связывает приложение с типами файлов, которые требуется поддерживать. Дополнительные сведения см. в статье "Связывание упакованного приложения с набором типов файлов". Ниже приведены наиболее важные элементы, связанные с этим элементом.
Атрибут или элемент | Описание |
---|---|
Атрибут Name |
Соответствует имени расширения, которое нужно зарегистрировать, без точки (в предыдущем примере foo ). |
Атрибут Parameters |
Содержит параметры, которые необходимо передать приложению, когда пользователь дважды щелкает файл с таким расширением. Как правило, по крайней мере, передается специальный параметр %1 , содержащий путь выбранного файла. Таким образом, если дважды щелкнуть файл, приложение знает полный путь и может загрузить его. |
элемент SupportedFileTypes | Указывает имена расширения, которое требуется зарегистрировать, включая точку (в этом примере .foo ). Можно указать несколько записей <FileType> , чтобы поддерживать больше типов файлов. |
Чтобы определить интеграцию контекстного меню, необходимо также добавить дочерний элемент SupportedVerbs . Этот элемент содержит один или несколько элементов Verb, определяющих опции, которые будут перечислены при правом клике файла с расширением .foo в Проводнике. Дополнительные сведения см. в разделе "Добавление параметров" в контекстное меню файлов с определенным типом файла. Вот наиболее важные пункты, связанные с элементом Verb.
Атрибут или элемент | Описание |
---|---|
Атрибут Id |
Указывает уникальный идентификатор действия. |
Атрибут Parameters |
Как и элемент FileTypeAssociation %1 специального параметра, чтобы получить путь к выбранному файлу, вы передаете также один или несколько параметров для получения контекста. Это позволяет приложению понять, что оно было открыто из элемента контекстного меню. |
Значение элемента | Значение элемента Verb содержит метку, отображаемую в пункте контекстного меню (в этом примере изменение размера файла). |
Доступ к параметрам запуска в коде приложения
Способ получения параметров зависит от типа созданного приложения. Например, приложение WPF обычно обрабатывает параметры событий запуска в методе OnStartup
класса App
. Вы можете проверить наличие параметров запуска и в зависимости от результата выполнить наиболее подходящее действие (например, открытие определенного окна приложения вместо основного).
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
if (e.Args.Contains("Resize"))
{
// Open a specific window of the app.
}
else
{
MainWindow main = new MainWindow();
main.Show();
}
}
}
На следующем снимке экрана показана запись контекстного меню Изменение размера файла, созданная в предыдущем примере.
Поддержка универсальных файлов или папок и выполнение сложных задач
Хотя использование расширения FileTypeAssociation в манифесте пакета, как описано в предыдущем разделе, является достаточным для многих сценариев, вы можете посчитать его ограничивающим. Две самые большие проблемы:
- Вы можете обрабатывать только типы файлов, с которыми вы связаны. Например, нельзя обрабатывать универсальную папку.
- Приложение можно запустить только с рядом параметров. Вы не можете выполнять расширенные операции, например запуск другого исполняемого файла или выполнение задачи без открытия основного приложения.
Для достижения этих целей необходимо создать расширение оболочки , которое обеспечивает более мощные способы интеграции с Проводником. В этом сценарии создается библиотека DLL, содержащая все необходимые для управления контекстным меню файла, включая метку, значок, состояние и задачи. Так как эта функция реализована в библиотеке DLL, вы можете сделать практически все, что можно сделать с обычным приложением. После реализации библиотеки DLL необходимо зарегистрировать его с помощью расширений, которые определяются в манифесте пакета.
Замечание
Процесс, описанный в этом разделе, имеет одно ограничение. После установки пакета MSIX, содержащего расширение, на целевом компьютере необходимо перезапустить проводник перед загрузкой расширения оболочки. Для этого пользователь может перезагрузить компьютер или перезапустить процесс explorer.exe с помощью диспетчера задач.
Внедрение расширения оболочки
Расширения оболочки основаны на COM (компонентной объектной модели). Библиотека DLL предоставляет один или несколько COM-объектов, зарегистрированных в системном реестре. Windows обнаруживает эти COM-объекты и интегрирует ваше расширение с Проводником. Поскольку вы интегрируете свой код с оболочкой Windows, производительность и объем памяти имеют значение. Поэтому эти типы расширений обычно создаются с помощью C++.
Пример кода, иллюстрирующий реализацию расширений оболочки, см. в проекте ExplorerCommandVerb в соответствующем примере на GitHub. Этот проект основан на этом образце в примерах для настольных приложений Windows, и было внесено несколько изменений, чтобы упростить использование образца с последними версиями Visual Studio.
Этот проект содержит много стандартных кодов для различных задач, таких как динамические и статические меню и ручная регистрация библиотеки DLL. Большая часть этого кода не требуется, если вы упаковывайте приложение с помощью MSIX, так как поддержка упаковки будет заботиться об этих задачах. Файл ExplorerCommandVerb.cpp содержит реализацию контекстного меню, и это основной файл кода для этого пошагового руководства.
Ключевой функцией является CExplorerCommandVerb::Invoke
. Это функция, которая вызывается, когда пользователь щелкает запись в контекстном меню. В данном примере, чтобы минимизировать влияние на производительность, операция выполняется в другом потоке, поэтому реализацию можно найти в CExplorerCommandVerb::_ThreadProc
.
DWORD CExplorerCommandVerb::_ThreadProc()
{
IShellItemArray* psia;
HRESULT hr = CoGetInterfaceAndReleaseStream(_pstmShellItemArray, IID_PPV_ARGS(&psia));
_pstmShellItemArray = NULL;
if (SUCCEEDED(hr))
{
DWORD count;
psia->GetCount(&count);
IShellItem2* psi;
HRESULT hr = GetItemAt(psia, 0, IID_PPV_ARGS(&psi));
if (SUCCEEDED(hr))
{
PWSTR pszName;
hr = psi->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &pszName);
if (SUCCEEDED(hr))
{
WCHAR szMsg[128];
StringCchPrintf(szMsg, ARRAYSIZE(szMsg), L"%d item(s), first item is named %s", count, pszName);
MessageBox(_hwnd, szMsg, L"ExplorerCommand Sample Verb", MB_OK);
CoTaskMemFree(pszName);
}
psi->Release();
}
psia->Release();
}
return 0;
}
Когда пользователь щелкает правой кнопкой мыши файл или папку, эта функция отображает окно сообщения с полным путем выбранного файла или папки. Если вы хотите настроить расширение оболочки другими способами, можно расширить следующие функции в примере:
- Вы можете изменить функцию GetTitle , чтобы настроить метку записи в контекстном меню.
- Вы можете изменить функцию GetIcon , чтобы настроить значок, отображаемый рядом с записью в контекстном меню.
- Вы можете изменить функцию GetTooltip, чтобы настроить подсказку, которая отображается при наведении курсора на запись в контекстном меню.
Зарегистрируйте расширение оболочки
Поскольку расширение оболочки основано на COM, библиотека DLL реализации должна быть представлена как COM-сервер, чтобы Windows могла интегрировать её с Проводником. Как правило, это делается путем назначения уникального идентификатора (с именем CLSID) COM-серверу и регистрации его в определенной ветке системного реестра. В проекте ExplorerCommandVerb CLSID для расширения CExplorerCommandVerb
определяется в файле Dll.h.
class __declspec(uuid("CC19E147-7757-483C-B27F-3D81BCEB38FE")) CExplorerCommandVerb;
При упаковке библиотеки DLL расширения оболочки в пакете MSIX следует использовать аналогичный подход. Однако GUID должен быть зарегистрирован в манифесте пакета, а не в реестре, как описано здесь.
В манифесте пакета начните с добавления следующих пространств имен в элемент Package.
<Package
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
IgnorableNamespaces="desktop desktop4 desktop5 com">
...
</Package>
Чтобы зарегистрировать CLSID, добавьте элемент com.Extension с категорией windows.comServer
в манифест пакета. Этот элемент должен быть добавлен в качестве дочернего к элементу Extensions в рамках элемента Application. Этот пример представляет собой фрагмент из файла Package.appxmanifest в соответствующем примере на GitHub.
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:SurrogateServer DisplayName="ContextMenuSample">
<com:Class Id="CC19E147-7757-483C-B27F-3D81BCEB38FE" Path="ExplorerCommandVerb.dll" ThreadingModel="STA"/>
</com:SurrogateServer>
</com:ComServer>
</com:Extension>
В элементе com:Class есть два критически важных атрибута.
Свойство | Описание |
---|---|
Атрибут Id |
Это должно соответствовать CLSID объекта, который требуется зарегистрировать. В этом примере CLSID объявлен в файле Dll.h , связанном с классом CExplorerCommandVerb . |
Атрибут Path |
Это должно содержать имя библиотеки DLL, которая экспортирует COM-объект. Этот пример включает библиотеку DLL в корень пакета, поэтому он может просто указать имя библиотеки DLL, созданной проектом ExplorerCommandVerb . |
Затем добавьте другое расширение, которое регистрирует контекстное меню файла. Для этого добавьте в манифест пакета элемент desktop4:Extension с категорией windows.fileExplorerContextMenus
. Этот элемент также должен быть добавлен в качестве дочернего элемента Extensions в элементе Application.
<desktop4:Extension Category="windows.fileExplorerContextMenus">
<desktop4:FileExplorerContextMenus>
<desktop5:ItemType Type="Directory">
<desktop5:Verb Id="Command1" Clsid="CC19E147-7757-483C-B27F-3D81BCEB38FE" />
</desktop5:ItemType>
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>
В элементе desktop4:Extension необходимо настроить два важных атрибута.
Атрибут или элемент | Описание |
---|---|
атрибут Type объекта desktop5:ItemType |
Это определяет тип элементов, которые необходимо связать с контекстным меню. Это может быть звезда (* ), если вы хотите отобразить его для всех файлов; это может быть определенное расширение файла (.foo ); или оно может быть доступно для папок (Directory ). |
атрибут Clsid desktop5:Verb |
Это должно соответствовать CLSID, который вы ранее зарегистрировали в качестве COM-сервера в файле манифеста пакета. |
Настройка библиотеки DLL в пакете
Включите библиотеку DLL, реализующую расширение оболочки (в этом примере ExplorerCommandVerb.dll) в корне пакета MSIX. Если вы используете проект упаковки приложений Windows , проще всего скопировать и вставить DLL в проект и убедиться, что параметр "Копировать в выходной каталог" для свойств файла DLL установлен на "Копировать, если новее".
Чтобы пакет всегда содержал последнюю версию библиотеки DLL, вы можете добавить послестроечное событие в проект расширения оболочки, чтобы при каждой сборке DLL копировалась в проект упаковки приложений Windows.
Перезапуск файлового проводника
После установки пакета расширения оболочки необходимо перезапустить проводник перед загрузкой расширения оболочки. Это ограничение расширений оболочки, развернутых и зарегистрированных с помощью пакетов MSIX.
Чтобы проверить расширение оболочки, перезапустите компьютер или перезапустите процесс explorer.exe с помощью диспетчера задач. После этого вы сможете увидеть запись в контекстном меню.
Если щелкнуть его, CExplorerCommandVerb::_ThreadProc
функция будет вызвана для отображения поля сообщения с путем выбранной папки.
Windows developer