I've created a menu item for the extension I'm working on; however, it is showing up 4 times in the Tools menu instead of just once. Below is what I have, but I have been unable to figure out why the menu item is showing up more than once.
VSCT File
<?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"/>
<Commands package="guidTemplatePackPkg">
<Groups>
<Group guid="guidTemplatePackCmdSet" id="MyMenuGroup" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/>
</Group>
</Groups>
<Buttons>
<Button guid="guidTemplatePackCmdSet" id="cmdidMyCommand" priority="0x2000" type="Button">
<Parent guid="guidSHLMainMenu" id="IDG_VS_CTXT_PROJECT_ADD_REFERENCES" />
<CommandFlag>DynamicVisibility</CommandFlag>
<CommandFlag>DefaultInvisible</CommandFlag>
<Strings>
<CommandName>AddSideWaffleProject</CommandName>
<ButtonText>Add Template Reference (SideWaffle project)</ButtonText>
</Strings>
</Button>
</Buttons>
</Commands>
<!-- SideWaffle Menu Options -->
<Commands package="guidMenuOptionsPkg">
<Groups>
<Group guid="guidMenuOptionsCmdSet" id="SWMenuGroup" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/>
</Group>
</Groups>
<Buttons>
<Button guid="guidMenuOptionsCmdSet" id="cmdidOpenSWMenu" priority="0x0100" type="Button">
<Parent guid="guidMenuOptionsCmdSet" id="SWMenuGroup" />
<Icon guid="guidImages" id="bmpPic1" />
<Strings>
<ButtonText>SideWaffle Settings</ButtonText>
</Strings>
</Button>
</Buttons>
<Bitmaps>
<Bitmap guid="guidImages" href="Resources\Images.png" usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows"/>
</Bitmaps>
</Commands>
<!-- End SideWaffle Menu Options -->
<Symbols>
<GuidSymbol name="guidTemplatePackPkg" value="{e6e2a48e-387d-4af2-9072-86a5276da6d4}" />
<GuidSymbol name="guidTemplatePackCmdSet" value="{a94bef1a-053e-4066-a851-16e5f6c915f1}">
<IDSymbol name="MyMenuGroup" value="0x1020" />
<IDSymbol name="cmdidMyCommand" value="0x0100" />
</GuidSymbol>
<!-- SideWaffle Menu Options -->
<GuidSymbol name="guidMenuOptionsPkg" value="{ee0cf212-810b-45a1-8c62-e10041913c94}" />
<GuidSymbol name="guidMenuOptionsCmdSet" value="{c75eac28-63cd-4766-adb1-e655471525ea}">
<IDSymbol name="SWMenuGroup" value="0x1020" />
<IDSymbol name="cmdidOpenSWMenu" value="0x0100" />
</GuidSymbol>
<GuidSymbol name="guidImages" value="{e2bf6a31-afea-46fb-9397-0c2add3a59d8}" >
<IDSymbol name="bmpPic1" value="1" />
<IDSymbol name="bmpPic2" value="2" />
<IDSymbol name="bmpPicSearch" value="3" />
<IDSymbol name="bmpPicX" value="4" />
<IDSymbol name="bmpPicArrows" value="5" />
<IDSymbol name="bmpPicStrikethrough" value="6" />
</GuidSymbol>
<!-- End SideWaffle Menu Options -->
</Symbols>
</CommandTable>
TemplatePackPackage.cs
using System;
using System.Linq;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.ComponentModel.Design;
using Microsoft.Win32;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using System.Collections.Generic;
using EnvDTE;
using EnvDTE80;
using LigerShark.Templates.DynamicBuilder;
using TemplatePack.Tooling;
namespace TemplatePack
{
[PackageRegistration(UseManagedResourcesOnly = true)]
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[Guid(GuidList.guidTemplatePackPkgString)]
[ProvideAutoLoad(UIContextGuids80.SolutionExists)]
public sealed class TemplatePackPackage : Package
{
private DTE2 _dte;
protected override void Initialize()
{
base.Initialize();
_dte = GetService(typeof(DTE)) as DTE2;
OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (null != mcs)
{
CommandID cmdId = new CommandID(GuidList.guidTemplatePackCmdSet, (int)PkgCmdIDList.cmdidMyCommand);
OleMenuCommand button = new OleMenuCommand(ButtonClicked, cmdId);
button.BeforeQueryStatus += button_BeforeQueryStatus;
mcs.AddCommand(button);
}
/*if(Environment.GetEnvironmentVariable("SideWaffleEnableDynamicTemplates") != null)*/{
try {
new DynamicTemplateBuilder().ProcessTemplates();
}
catch (Exception ex) {
// todo: replace with logging or something
System.Windows.MessageBox.Show(ex.ToString());
}
}
}
void button_BeforeQueryStatus(object sender, EventArgs e)
{
var button = (OleMenuCommand)sender;
var project = GetSelectedProjects().ElementAt(0);
// TODO: We should only show this if the target project has the TemplateBuilder NuGet pkg installed
// or something similar to that.
button.Visible = true;
// button.Visible = project.IsWebProject();
}
private void ButtonClicked(object sender, EventArgs e)
{
Project currentProject = GetSelectedProjects().ElementAt(0);
var projects = _dte.Solution.GetAllProjects();
var names = from p in projects
where p != currentProject
select p.Name;
ProjectSelector selector = new ProjectSelector(names);
bool? isSelected = selector.ShowDialog();
if (isSelected.HasValue && isSelected.Value)
{
// need to save everything because we will directly write to the project file in the creator
_dte.ExecuteCommand("File.SaveAll");
TemplateReferenceCreator creator = new TemplateReferenceCreator();
var selectedProject = projects.First(p => p.Name == selector.SelectedProjectName);
creator.AddTemplateReference(currentProject, selectedProject);
}
}
public IEnumerable<Project> GetSelectedProjects()
{
var items = (Array)_dte.ToolWindows.SolutionExplorer.SelectedItems;
foreach (UIHierarchyItem selItem in items)
{
var item = selItem.Object as Project;
if (item != null)
{
yield return item;
}
}
}
}
[PackageRegistration(UseManagedResourcesOnly = true)]
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[Guid(GuidList.guidMenuOptionsPkgString)]
public sealed class MenuOptionsPackage : Package
{
// Overridden Package Implementation
#region Package Members
protected override void Initialize()
{
base.Initialize();
// Add our command handlers for menu (commands must exist in the .vsct file)
OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if ( null != mcs )
{
// Create the command for the menu item.
CommandID menuCommandID = new CommandID(GuidList.guidMenuOptionsCmdSet, (int)PkgCmdIDList.cmdidMyCommand);
MenuCommand menuItem = new MenuCommand(MenuItemCallback, menuCommandID );
mcs.AddCommand( menuItem );
}
}
#endregion
private void MenuItemCallback(object sender, EventArgs e)
{
// Here is where our UI (i.e. user control) will go to do all the settings.
var window = new SettingsForm();
window.Show();
}
}
}
PackageConstants.cs
using System;
namespace TemplatePack
{
static class GuidList
{
public const string guidTemplatePackPkgString = "e6e2a48e-387d-4af2-9072-86a5276da6d4";
public const string guidTemplatePackCmdSetString = "a94bef1a-053e-4066-a851-16e5f6c915f1";
public static readonly Guid guidTemplatePackCmdSet = new Guid(guidTemplatePackCmdSetString);
// SideWaffle Remote Source Settings
public const string guidMenuOptionsPkgString = "ee0cf212-810b-45a1-8c62-e10041913c94";
public const string guidMenuOptionsCmdSetString = "c75eac28-63cd-4766-adb1-e655471525ea";
public static readonly Guid guidMenuOptionsCmdSet = new Guid(guidMenuOptionsCmdSetString);
}
static class PkgCmdIDList
{
public const uint cmdidMyCommand = 0x100;
public const uint SWMenuGroup = 0x100;
};
}
I just can't seem to figure out what I might be doing wrong. Any suggestions?
...what I might be doing wrong.
You're essentially trying to bundle two packages (TemplatePackPackage
& MenuOptionsPackage
) into a single package, which messes up your .pkgdef
file, which I believe is the cause of your issue.
If you comment out the MenuOptionsPackage
class, then you should see only one menu item - as intended.
Any suggestions?
Package
class.Package
. If you need to access one through the other you can provide and consume services.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With