VS扩展开发:无法将自定义按钮放入ProjectNode/Add子菜单
VS扩展按钮位置问题及解决方案
背景
开发一款VS扩展,包含一个按钮,点击后打开配置视图,用于创建带文件夹、子文件夹且继承自定义类的自定义Azure Function。
问题
按钮无法放置到预期位置,微软官方文档未覆盖该场景。
预期位置
操作路径如下:
- 打开解决方案资源管理器
- 右键点击Azure Function项目
- 点击“Add”子菜单
- 在“Add new Azure Function”之后显示“Add new Custom Azure Function”按钮
实际位置
按钮出现在右键Azure Function项目菜单的第6个独立组中,不在Add子菜单内。
当前代码
使用的VSCommandTable.vsct代码:
<?xml version="1.0" encoding="utf-8"?> <CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <Extern href="stdidcmd.h"/> <Extern href="vsshlids.h"/> <Include href="KnownImageIds.vsct"/> <Include href="VSGlobals.vsct"/> <Commands package="AzureFunctionScaffoldingPOCExtension"> <Groups> <Group guid="AzureFunctionScaffoldingPOCExtension" id="MyMenuGroup" priority="0x0400"> <!--This one should be the "Add" submenu I am looking for, but actually just goes into the righ-click on project in Solution Explorer--> <Parent guid="guidSHLMainMenu" id="IDG_VS_PROJ_ADD"/> </Group> </Groups> <Buttons> <Button guid="AzureFunctionScaffoldingPOCExtension" id="MyCommand" priority="0x0100" type="Button"> <!--This one should reference the Custom Group, right? Or since it is just a button the Group element is not necessary and this should provide the actual parent element?--> <Parent guid="AzureFunctionScaffoldingPOCExtension" id="MyMenuGroup"/> <Icon guid="ImageCatalogGuid" id="AddModule" /> <CommandFlag>IconIsMoniker</CommandFlag> <CommandFlag>DynamicVisibility</CommandFlag> <Strings> <ButtonText>Add Custom Azure Function</ButtonText> <LocCanonicalName>.AzureFunctionScaffoldingPOCExtension.MyCommand</LocCanonicalName> </Strings> </Button> </Buttons> </Commands> <VisibilityConstraints> <VisibilityItem guid="AzureFunctionScaffoldingPOCExtension" id="MyCommand" context="UICONTEXT_SolutionExists"/> </VisibilityConstraints> <Symbols> <GuidSymbol name="AzureFunctionScaffoldingPOCExtension" value="{4cb051a6-eb41-455d-80e2-433571ee2b43}"> <IDSymbol name="MyMenuGroup" value="0x0001" /> <IDSymbol name="MyCommand" value="0x0100" /> </GuidSymbol> <GuidSymbol name="guidSHLMainMenu" value="{D309F791-903F-11D0-9EFC-00A0C911004F}"> <IDSymbol name="IDG_VS_PROJ_ADD" value="0x0402"/> </GuidSymbol> </Symbols> </CommandTable>
解决方案
核心修改点
- 修正父级菜单目标:原来的
IDG_VS_PROJ_ADD是右键项目菜单中的Add分组,而非点击后展开的Add子菜单。需要将组的父级改为IDM_VS_PROJ_ADD_SUBMENU(VS标准项目Add子菜单的ID)。 - 调整优先级:设置按钮优先级略高于默认的“Add new Azure Function”(默认优先级通常为0x0000),确保按钮出现在它之后。
- 限制可见范围:仅在Azure Function项目中显示按钮,避免在其他项目类型中出现。
修改后的VSCommandTable.vsct代码
<?xml version="1.0" encoding="utf-8"?> <CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <Extern href="stdidcmd.h"/> <Extern href="vsshlids.h"/> <Include href="KnownImageIds.vsct"/> <Include href="VSGlobals.vsct"/> <Commands package="AzureFunctionScaffoldingPOCExtension"> <Groups> <Group guid="AzureFunctionScaffoldingPOCExtension" id="MyMenuGroup" priority="0x0001"> <!-- 改为Add子菜单作为父级 --> <Parent guid="guidSHLMainMenu" id="IDM_VS_PROJ_ADD_SUBMENU"/> </Group> </Groups> <Buttons> <Button guid="AzureFunctionScaffoldingPOCExtension" id="MyCommand" priority="0x0001" type="Button"> <Parent guid="AzureFunctionScaffoldingPOCExtension" id="MyMenuGroup"/> <Icon guid="ImageCatalogGuid" id="AddModule" /> <CommandFlag>IconIsMoniker</CommandFlag> <CommandFlag>DynamicVisibility</CommandFlag> <Strings> <ButtonText>Add Custom Azure Function</ButtonText> <LocCanonicalName>.AzureFunctionScaffoldingPOCExtension.MyCommand</LocCanonicalName> </Strings> </Button> </Buttons> </Commands> <VisibilityConstraints> <!-- 保留解决方案存在的约束,添加Azure Function项目上下文 --> <VisibilityItem guid="AzureFunctionScaffoldingPOCExtension" id="MyCommand" context="UICONTEXT_SolutionExists"/> <VisibilityItem guid="AzureFunctionScaffoldingPOCExtension" id="MyCommand" context="UICONTEXT_AzureFunctionsProject"/> </VisibilityConstraints> <Symbols> <GuidSymbol name="AzureFunctionScaffoldingPOCExtension" value="{4cb051a6-eb41-455d-80e2-433571ee2b43}"> <IDSymbol name="MyMenuGroup" value="0x0001" /> <IDSymbol name="MyCommand" value="0x0100" /> </GuidSymbol> <GuidSymbol name="guidSHLMainMenu" value="{D309F791-903F-11D0-9EFC-00A0C911004F}"> <IDSymbol name="IDM_VS_PROJ_ADD_SUBMENU" value="0x002D"/> <IDSymbol name="IDG_VS_PROJ_ADD" value="0x0402"/> </GuidSymbol> <!-- 定义Azure Function项目的上下文GUID --> <GuidSymbol name="guidAzureFunctionsPackage" value="{8A2F8E03-9C4C-4D86-8A5B-6457933B8D75}"> <IDSymbol name="UICONTEXT_AzureFunctionsProject" value="0x0001"/> </GuidSymbol> </Symbols> </CommandTable>
补充说明
- 如果
UICONTEXT_AzureFunctionsProject的GUID或ID不正确,可以通过下面的方法自行获取。 - 若按钮仍未出现在预期位置,可以进一步提高按钮的优先级数值(比如0x0002),确保排在默认按钮之后。
科学定位VS菜单元素的GUID和ID
- 使用VS命令窗口:
- 打开命令窗口(Ctrl+Alt+A),输入
Tools.LogCommands 1开启命令日志。 - 点击目标菜单(比如Azure Function项目右键的Add子菜单、“Add new Azure Function”按钮),命令窗口会输出对应的GUID和ID。
- 完成后输入
Tools.LogCommands 0关闭日志。
- 打开命令窗口(Ctrl+Alt+A),输入
- 使用MenuCommandSpy工具:
- VS SDK自带的MenuCommandSpy扩展可以实时显示菜单元素的GUID、ID和优先级,安装后通过
View->Other Windows->Menu Command Spy打开。
- VS SDK自带的MenuCommandSpy扩展可以实时显示菜单元素的GUID、ID和优先级,安装后通过
- 查看VS头文件:
- 查看VS安装目录下的
vsshlids.h、stdidcmd.h等头文件,里面包含了标准菜单、命令的GUID和ID定义。
- 查看VS安装目录下的
内容的提问来源于stack exchange,提问作者FrankOfTheScience
相关产品推荐
相关产品推荐

