VSIX расширение для Visual Studio 2019: интеграция в меню и раздел About
Решение проблемы, когда VSIX расширение установлено, но не отображается в меню и разделе About Visual Studio 2019. Пошаговая инструкция по правильной интеграции.
VSIX расширение для Visual Studio 2019: установлено и отображается в списке расширений и логах, но не появляется в меню и разделе About. Как заставить расширение правильно интегрироваться в интерфейс Visual Studio?
VSIX расширение для Visual Studio 2019 установлено и отображается в списке расширений, но не появляется в меню и разделе About. Это распространенная проблема при разработке расширений для Visual Studio, которая обычно связана с неправильной настройкой манифеста VSIX или отсутствием необходимого кода для интеграции в интерфейс. Чтобы решить эту проблему, необходимо проверить структуру вашего расширения и правильно настроить его интеграцию в Visual Studio.
Содержание
- Причины проблемы интеграции VSIX расширений
- Проверка конфигурации VSIX манифеста
- Настройка меню в Visual Studio 2019
- Интеграция в раздел About
- Отладка и тестирование расширения
- Создание корректной структуры проекта
Причины проблемы интеграции VSIX расширений
VSIX расширения, которые устанавливаются через VSIX файл, но не отображаются в меню или разделе About Visual Studio 2019, обычно сталкиваются с несколькими типичными проблемами. Основные причины, по которым расширение может не интегрироваться правильно в интерфейс:
Неправильная конфигурация меню в VSIX манифесте. В Visual Studio 2019 и более новых версиях верхнеуровневые меню от расширений размещаются под меню “Extensions”. Если вы не указали правильную структуру меню в манифесте, ваше расширение не будет отображаться в интерфейсе.
Отсутствие необходимых атрибутов в манифесте. Манифест VSIX должен содержать правильные атрибуты для меню, команд, окон инструментов и других компонентов расширения. Без этих атрибутов расширение будет установлено, но не интегрировано в интерфейс.
Проблемы с экспериментальным экземпляром. Visual Studio использует экспериментальный экземпляр для отладки расширений. Если экспериментальный экземпляр не настроен правильно или был поврежден, расширения могут не отображаться должным образом.
Неправильная структура проекта. VSIX расширение должно иметь правильную структуру файлов, включая правильные файлы ресурсов, иконки и необходимые файлы поддержки.
Важно понимать, что в Visual Studio 2019 изменилась политика размещения меню расширений. Теперь все верхнеуровневые меню от расширений размещаются под меню “Extensions”, а не как отдельные меню в основной строке меню.
Проверка конфигурации VSIX манифеста
VSIX манифест (source.extension.vsixmanifest) является ключевым файлом, определяющим поведение вашего расширения в Visual Studio. Если расширение установлено, но не отображается в меню или разделе About, начните проверку именно с этого файла.
Структура манифеста для меню:
<Extension>
<DisplayName>Название вашего расширения</DisplayName>
<Description>Описание расширения</Description>
<Tags>теги, расширение</Tags>
<Version>1.0.0</Version>
<Property Id="DisplayName" Value="Отображаемое имя" />
<Property Id="ProductLanguage" Value="1049" />
<Property Id="CompanyName" Value="Ваша компания" />
<Property Id="ExtensionGuid" Value="{ваш-уникальный-guid}" />
<!-- Настройки меню -->
<MefComponent>
<Export Type="Microsoft.VisualStudio.ComponentModelHost.IComponentModelExport" />
</MefComponent>
<!-- Команды меню -->
<CustomExtension>
<FilePath>MyExtensionPackage.cs</FilePath>
</CustomExtension>
</Extension>
Ключевые элементы для интеграции в меню:
<Assets>
<Asset Type="Microsoft.VisualStudio.Menus.CommandSet"
Path="Menus.ctmenu" />
<Asset Type="Microsoft.VisualStudio.Menus.Menu"
Path="Menus.ctmenu" />
</Assets>
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2004/10/CommandTable">
<Commands>
<CommandFlag>DefaultDisabled</CommandFlag>
<CommandFlag>DynamicVisibility</CommandFlag>
<Menus>
<Menu guid="guidMyExtensionPackageCmdSet"
id="MyExtensionMenu"
priority="0x4000">
<CommandFlag>DefaultInvisible</CommandFlag>
<Strings>
<ButtonText>Моё расширение</ButtonText>
<CommandName>guidMyExtensionPackageCmdSet.MyExtensionMenu</CommandName>
</Strings>
</Menu>
</Menus>
<Buttons>
<Button guid="guidMyExtensionPackageCmdSet"
id="cmdidMyCommand"
priority="0x0100"
type="Button">
<Parent guid="guidMyExtensionPackageCmdSet"
id="MyExtensionMenu" />
<CommandFlag>DefaultDisabled</CommandFlag>
<CommandFlag>DefaultInvisible</CommandFlag>
<CommandFlag>DynamicVisibility</CommandFlag>
<Strings>
<ButtonText>Моя команда</ButtonText>
<CommandName>guidMyExtensionPackageCmdSet.cmdidMyCommand</CommandName>
<ToolTip>Описание команды</ToolTip>
</Strings>
</Button>
</Buttons>
</Commands>
</CommandTable>
Важные моменты:
- Убедитесь, что GUID уникальны для вашего расширения
- Проверьте правильность путей к файлам ресурсов
- Убедитесь, что все необходимые ресурсы включены в проект
- Проверьте приоритеты меню и команд
Настройка меню в Visual Studio 2019
В Visual Studio 2019 изменилась политика размещения меню расширений. Теперь все верхнеуровневые меню от расширений размещаются под меню “Extensions”. Это важное изменение, которое часто упускают разработчики.
Создание меню верхнего уровня:
Чтобы создать меню верхнего уровня, которое будет отображаться под меню “Extensions”, используйте следующий подход:
- Создайте файл меню (
Menus.ctmenu):
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2004/10/CommandTable">
<Externals>
<External guid="guidMyExtensionPackageCmdSet"
id="MyExtensionMenu"
name="MyExtensionMenu" />
</Externals>
<Commands>
<CommandFlag>DefaultDisabled</CommandFlag>
<CommandFlag>DynamicVisibility</CommandFlag>
<Menus>
<Menu guid="guidMyExtensionPackageCmdSet"
id="MyExtensionMenu"
priority="0x4000">
<CommandFlag>DefaultInvisible</CommandFlag>
<Strings>
<ButtonText>Моё расширение</ButtonText>
<CommandName>guidMyExtensionPackageCmdSet.MyExtensionMenu</CommandName>
</Strings>
</Menu>
</Menus>
<Buttons>
<Button guid="guidMyExtensionPackageCmdSet"
id="cmdidMyCommand"
priority="0x0100"
type="Button">
<Parent guid="guidMyExtensionPackageCmdSet"
id="MyExtensionMenu" />
<CommandFlag>DefaultDisabled</CommandFlag>
<CommandFlag>DefaultInvisible</CommandFlag>
<CommandFlag>DynamicVisibility</CommandFlag>
<Strings>
<ButtonText>Моя команда</ButtonText>
<CommandName>guidMyExtensionPackageCmdSet.cmdidMyCommand</CommandName>
<ToolTip>Описание команды</ToolTip>
</Strings>
</Button>
</Buttons>
</Commands>
</CommandTable>
- Настройте класс Package:
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[Guid("ваш-guid-package")]
public sealed class MyExtensionPackage : Package
{
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await this.RegisterCommandsAsync(cancellationToken);
}
private async Task RegisterCommandsAsync(CancellationToken cancellationToken)
{
OleMenuCommandService commandService = await this.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService != null)
{
var menuCommandID = new CommandID(GuidList.guidMyExtensionPackageCmdSet, (int)PkgCmdIDList.cmdidMyCommand);
var menuItem = new OleMenuCommand(ExecuteCommand, menuCommandID);
menuItem.BeforeQueryStatus += OnBeforeQueryStatus;
commandService.AddCommand(menuItem);
}
}
private void ExecuteCommand(object sender, EventArgs e)
{
// Ваш код выполнения команды
}
private void OnBeforeQueryStatus(object sender, EventArgs e)
{
var menuCommand = (OleMenuCommand)sender;
menuCommand.Visible = true;
menuCommand.Enabled = true;
}
}
Важные настройки для Visual Studio 2019:
- Поддержка меню Extensions:
<Asset Type="Microsoft.VisualStudio.Menus.Menu"
Path="Menus.ctmenu" />
- Правильные приоритеты:
- Для верхнеуровневого меню используйте приоритет
0x4000 - Для подменю используйте
0x4001,0x4002и т.д. - Для команд используйте
0x0100,0x0101и т.д.
- Динамическая видимость:
private void OnBeforeQueryStatus(object sender, EventArgs e)
{
var menuCommand = (OleMenuCommand)sender;
menuCommand.Visible = true;
menuCommand.Enabled = true;
}
Проверка работы меню:
После настройки меню выполните следующие шаги:
- Скомпилируйте расширение
- Разверните его через Visual Studio (Debug > Start Without Debugging)
- Проверьте, появилось ли меню под “Extensions”
- Если меню не появилось, проверьте консоль расширений на наличие ошибок
Интеграция в раздел About
Интеграция расширения в раздел About Visual Studio - это важный аспект, который обеспечивает профессиональный вид и узнаваемость вашего расширения. Если ваше расширение установлено, но не отображается в разделе About, это обычно связано с неправильной настройкой атрибутов расширения.
Настройка раздела About:
Для отображения информации о расширении в разделе About используйте следующие атрибуты:
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[Guid("ваш-guid-package")]
[ProvideAutoLoad("ADFC7BDB-F0FE-4B17-913E-BA87E5D0B6E2")] // UIContextGuids.ExtensionManager
public sealed class MyExtensionPackage : Package
{
// Ваш код
}
Ключевые моменты:
- Атрибут InstalledProductRegistration:
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
#110- название расширения (строка в ресурсах)#112- описание расширения (строка в ресурсах)1.0- версия расширенияIconResourceID = 400- ID иконки в ресурсах
- Автозагрузка при запуске:
[ProvideAutoLoad("ADFC7BDB-F0FE-4B17-913E-BA87E5D0B6E2")] // UIContextGuids.ExtensionManager
Этот GUID обеспечивает загрузку расширения при открытии менеджера расширений.
- Настройка ресурсов:
[assembly: AssemblyTitle("MyExtension")]
[assembly: AssemblyDescription("Описание моего расширения")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Моя компания")]
[assembly: AssemblyProduct("MyExtension")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Решение проблем с отображением в About:
Если расширение не отображается в разделе About, выполните следующие проверки:
- Проверьте ресурсы:
- Убедитесь, что файл ресурсов (.resx) содержит нужные строки
- Проверьте правильность ID ресурсов в атрибуте
InstalledProductRegistration
- Проверьте GUID:
- Убедитесь, что GUID уникален и правильно указан
- Проверьте, что GUID используется во всех необходимых местах
- Проверьте конфигурацию проекта:
- Убедитесь, что проект настроен как VSIX проект
- Проверьте, что файл манифеста включен в проект
- Проверьте автозагрузку:
[ProvideAutoLoad(UIContextGuids80.SolutionExists)]
[ProvideAutoLoad(UIContextGuids80.NoSolution)]
[ProvideAutoLoad(UIContextGuids80.SolutionHasSingleProject)]
[ProvideAutoLoad(UIContextGuids80.SolutionHasMultipleProjects)]
Пример корректной настройки:
[InstalledProductRegistration("#110", "#112", "1.0.0.0", IconResourceID = 400)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[Guid("ваш-guid-package")]
[ProvideAutoLoad("ADFC7BDB-F0FE-4B17-913E-BA87E5D0B6E2")]
[ProvideAutoLoad(UIContextGuids80.SolutionExists)]
[ProvideAutoLoad(UIContextGuids80.NoSolution)]
public sealed class MyExtensionPackage : Package
{
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await base.InitializeAsync(cancellationToken, progress);
// Регистрация команд
OleMenuCommandService commandService = await this.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService != null)
{
var menuCommandID = new CommandID(GuidList.guidMyExtensionPackageCmdSet, (int)PkgCmdIDList.cmdidMyCommand);
var menuItem = new OleMenuCommand(ExecuteCommand, menuCommandID);
menuItem.BeforeQueryStatus += OnBeforeQueryStatus;
commandService.AddCommand(menuItem);
}
}
private void ExecuteCommand(object sender, EventArgs e)
{
// Ваш код выполнения команды
}
private void OnBeforeQueryStatus(object sender, EventArgs e)
{
var menuCommand = (OleMenuCommand)sender;
menuCommand.Visible = true;
menuCommand.Enabled = true;
}
}
Отладка и тестирование расширения
Когда VSIX расширение установлено, но не отображается в меню или разделе About, правильная отладка помогает быстро выявить и устранить проблему. Visual Studio предоставляет несколько инструментов для отладки расширений.
Сброс экспериментального экземпляра:
Экспериментальный экземпляр Visual Studio используется для отладки расширений. Если он поврежден или имеет проблемы, расширения могут не отображаться правильно. Сброс экспериментального экземпляра часто решает такие проблемы.
Способы сброса экспериментального экземпляра:
- Через Visual Studio:
- Откройте командную строку разработчика (Developer Command Prompt)
- Выполните команду:
devenv.exe /ResetSettings - Затем:
devenv.exe /ResetSkipPkgs
- Через реестр:
- Откройте редактор реестра (regedit)
- Перейдите к разделу:
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\16.0*Exp - Удалите ключ экспериментального экземпляра
- Через командную строку:
cd "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE"
devenv.exe /RootSuffix Exp /ResetSettings
Отладка расширения:
- Настройка отладки:
- В Visual Studio выберите Debug > Start Without Debugging
- Или нажмите Ctrl+F5
- Это запустит экспериментальный экземпляр Visual Studio
- Проверка ошибок:
- Откройте окно вывода (Output Window)
- Выберите “Extension Manager” в выпадающем списке
- Проверьте сообщения об ошибках
- Использование журналов расширений:
cd "C:\Users\%USERNAME%\AppData\Local\Microsoft\VisualStudio\16.0_*\Extensions"
Проверьте журналы расширений на наличие ошибок.
Команды для диагностики:
- Проверка состояния экспериментального экземпляра:
devenv.exe /RootSuffix Exp /Log "C:\Temp\vs_exp_log.txt"
- Сброс экспериментального экземпляра:
devenv.exe /RootSuffix Exp /ResetSettings devenv.exe /RootSuffix Exp /ResetSkipPkgs
- Полный сброс:
devenv.exe /ResetSettings devenv.exe /ResetSkipPkgs
Решение распространенных проблем:
- Расширение не отображается в меню:
- Проверьте файл
Menus.ctmenuна синтаксические ошибки - Убедитесь, что все GUID уникальны
- Проверьте приоритеты меню
- Расширение не отображается в About:
- Проверьте атрибут
InstalledProductRegistration - Убедитесь, что ресурсы правильно настроены
- Проверьте GUID в атрибуте
Guid
- Расширение устанавливается, но не работает:
- Сбросьте экспериментальный экземпляр
- Проверьте зависимости расширения
- Убедитесь, что все необходимые файлы включены в проект
Пример процедуры диагностики:
- Сбросьте экспериментальный экземпляр:
devenv.exe /RootSuffix Exp /ResetSettings
- Скомпилируйте и разверните расширение:
- В Visual Studio выберите Build > Rebuild Solution
- Затем Debug > Start Without Debugging
- Проверьте журналы:
- Откройте окно вывода
- Выберите “Extension Manager”
- Проверьте сообщения об ошибках
- Если проблема осталась:
- Проверьте синтаксис файла
Menus.ctmenu - Убедитесь, что все ресурсы включены в проект
- Проверьте правильность GUID
Создание корректной структуры проекта
Правильная структура проекта VSIX расширения - это фундамент успешной интеграции в интерфейс Visual Studio. Если расширение установлено, но не отображается в меню или разделе About, проблема часто кроется в неправильной структуре проекта.
Базовая структура VSIX проекта:
MyExtension/
├── MyExtension/
│ ├── MyExtensionPackage.cs
│ ├── MyExtensionCommands.cs
│ ├── PkgCmdID.cs
│ ├── GuidList.cs
│ ├── Resources/
│ │ ├── Resources.resx
│ │ └── Resources.ru-RU.resx
│ └── Templates/
│ └── MyTemplate.vstemplate
├── MyExtension.vsixmanifest
└── Packages/
└── MyExtension.vsix
Ключевые файлы проекта:
- source.extension.vsixmanifest:
<?xml version="1.0" encoding="utf-8"?>
<Extension xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
<Properties>
<Property Id="DisplayName" Value="My Extension" />
<Property Id="Description" Value="Description of my extension" />
<Property Id="Icon" Value="Resources.ico" />
<Property Id="ProductLanguage" Value="1049" />
<Property Id="CompanyName" Value="My Company" />
<Property Id="ExtensionGuid" Value="{ваш-guid}" />
</Properties>
<Assets>
<Asset Type="Microsoft.VisualStudio.Menus.Menu" Path="Menus.ctmenu" />
<Asset Type="Microsoft.VisualStudio.Menus.CommandSet" Path="Menus.ctmenu" />
<Asset Type="Microsoft.VisualStudio.VsPackage" Path="MyExtensionPackage.cs" />
<Asset Type="Microsoft.VisualStudio.ToolWindow" Path="MyToolWindow.cs" />
</Assets>
<Dependencies>
<Dependency Id="Microsoft.VisualStudio.Monitoring.16" />
<Dependency Id="Microsoft.VisualStudio.TextManager.16" />
</Dependencies>
</Extension>
- GuidList.cs:
public static class GuidList
{
public const string guidMyExtensionPackageCmdSet = "ваш-guid-package-cmdset";
public const int cmdidMyCommand = 0x0100;
public const string guidMyExtensionPackage = "ваш-guid-package";
public static string guidMyExtensionPackageCmdSetString = "ваш-guid-package-cmdset";
public static string guidMyExtensionPackageString = "ваш-guid-package";
}
- PkgCmdID.cs:
public static class PkgCmdIDList
{
public const uint cmdidMyCommand = 0x0100;
}
- MyExtensionPackage.cs:
[InstalledProductRegistration("#110", "#112", "1.0.0.0", IconResourceID = 400)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[Guid(GuidList.guidMyExtensionPackage)]
[ProvideAutoLoad("ADFC7BDB-F0FE-4B17-913E-BA87E5D0B6E2")]
[ProvideAutoLoad(UIContextGuids80.SolutionExists)]
[ProvideAutoLoad(UIContextGuids80.NoSolution)]
public sealed class MyExtensionPackage : Package
{
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await base.InitializeAsync(cancellationToken, progress);
// Регистрация команд
OleMenuCommandService commandService = await this.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService != null)
{
var menuCommandID = new CommandID(GuidList.guidMyExtensionPackageCmdSet, (int)PkgCmdIDList.cmdidMyCommand);
var menuItem = new OleMenuCommand(ExecuteCommand, menuCommandID);
menuItem.BeforeQueryStatus += OnBeforeQueryStatus;
commandService.AddCommand(menuItem);
}
}
private void ExecuteCommand(object sender, EventArgs e)
{
// Ваш код выполнения команды
}
private void OnBeforeQueryStatus(object sender, EventArgs e)
{
var menuCommand = (OleMenuCommand)sender;
menuCommand.Visible = true;
menuCommand.Enabled = true;
}
}
Настройка проекта:
- Свойства проекта:
- Убедитесь, что проект настроен как VSIX проект
- Проверьте, что выходной путь правильный
- Убедитесь, что файл манифеста включен в проект
- Включение файлов в проект:
- Щелкните правой кнопкой мыши по проекту
- Выберите Add > Existing Item
- Добавьте файлы меню, ресурсы и другие необходимые файлы
- Настройка сборки:
- Проверьте, что конфигурация сборки правильная
- Убедитесь, что все зависимости включены
Проверка интеграции:
После настройки структуры проекта выполните следующие шаги:
- Скомпилируйте проект:
- Выберите Build > Rebuild Solution
- Убедитесь, что ошибок нет
- Разверните расширение:
- Выберите Debug > Start Without Debugging
- Это запустит экспериментальный экземпляр
- Проверьте интеграцию:
- Проверьте, отображается ли меню в Visual Studio
- Проверьте, отображается ли расширение в разделе About
- Проверьте сообщения об ошибках в окне вывода
Решение проблем структуры проекта:
Если расширение не интегрируется правильно, выполните следующие проверки:
- Проверьте файл манифеста:
- Убедитесь, что все необходимые ресурсы включены
- Проверьте правильность путей к файлам
- Убедитесь, что все GUID уникальны
- Проверьте файлы ресурсов:
- Убедитесь, что файлы ресурсов включены в проект
- Проверьте правильность ID ресурсов
- Убедитесь, что ресурсы компилируются
- Проверьте конфигурацию сборки:
- Убедитесь, что проект правильно настроен
- Проверьте зависимости проекта
- Убедитесь, что все необходимые файлы включены в сборку
Источники
- Adding a Menu to the Visual Studio Menu Bar — Официальная документация по добавлению меню в Visual Studio 2019: https://learn.microsoft.com/en-us/visualstudio/extensibility/adding-a-menu-to-the-visual-studio-menu-bar?view=vs-2022
- Getting Started with the VSIX Project Template — Руководство по началу работы с шаблоном проекта VSIX: https://learn.microsoft.com/en-us/visualstudio/extensibility/getting-started-with-the-vsix-project-template?view=vs-2019
- Explore experimental space in Visual Studio SDK — Информация об экспериментальном экземпляре Visual Studio: https://learn.microsoft.com/en-us/visualstudio/extensibility/the-experimental-instance?view=visualstudio
- Visual Studio VSIX Extension not showing in Tools menu — Решение проблем с отображением расширений на Stack Overflow: https://stackoverflow.com/questions/58311920/visual-studio-vsix-extension-not-showing-in-tools-menu
Заключение
VSIX расширение для Visual Studio 2019 может быть установлено и отображаться в списке расширений, но не появляться в меню и разделе About по нескольким причинам. Основные решения включают правильную настройку VSIX манифеста, корректную структуру меню, настройку экспериментального экземпляра и правильную структуру проекта.
Для успешной интеграции расширения в интерфейс Visual Studio необходимо:
- Проверить и настроить VSIX манифест с правильными атрибутами меню и команд
- Создать корректную структуру меню в Visual Studio 2019 с правильными приоритетами
- Настроить отображение в разделе About с помощью атрибута
InstalledProductRegistration - Сбросить экспериментальный экземпляр Visual Studio для устранения проблем отладки
- Создать правильную структуру проекта с необходимыми файлами и ресурсами
Следуя этим шагам, вы сможете заставить ваше VSIX расширение правильно интегрироваться в интерфейс Visual Studio 2019 и отображаться в меню и разделе About.