/// <summary> /// Get the binding strings for this Command. Digs through the various ways a /// binding string can be stored and returns a uniform result /// </summary> public static IEnumerable <string> GetBindings(this DteCommand command, out Exception ex) { if (null == command) { throw new ArgumentException("command"); } ex = null; object bindings; try { bindings = command.Bindings; } catch (Exception ex2) { // Several user reports indicate the above call can throw. Most commonly // this throws an OutOfMemoryException. Either way we don't care what the // error is. We just can't get bindings for this element ex = ex2; return(Enumerable.Empty <string>()); } if (bindings is object[] bindingsArray) { return(bindingsArray .Where(x => x is string) .Cast <string>() .Where(x => !string.IsNullOrEmpty(x))); } if (bindings is string singleBinding) { return(Enumerable.Repeat(singleBinding, 1)); } return(Enumerable.Empty <string>()); }
private void VerifyCommandStep(string Guid, int ID, DTE2 dte) { if (dte.Commands == null) { return; } EnvDTE.Command command = dte.Commands.Item(Guid, ID); if (command == null) { return; } switch (command.Name) { case "Debug.StepInto": currentCommandStep = CurrentCommandStep.StepInto; break; case "Debug.StepOver": currentCommandStep = CurrentCommandStep.StepOver; break; case "Debug.StepOut": currentCommandStep = CurrentCommandStep.StepOut; break; } }
private static void Print(XmlWriter writer, EnvDTE.Command command, object[] bindings) { foreach (object binding in bindings) { var shortcut = binding.ToString(); var scopeIndex = shortcut.IndexOf("::"); string scope = ""; if (scopeIndex >= 0) { scope = shortcut.Substring(0, scopeIndex); shortcut = shortcut.Substring(scopeIndex + 2); } writer.WriteStartElement("command"); if (scope.Length > 0) { writer.WriteAttributeString("scope", scope); } writer.WriteAttributeString("shortcut", shortcut); writer.WriteAttributeString("name", command.Name); writer.WriteEndElement(); } }
private static IEnumerable <CommandKeyBinding> GetCommandKeyBindingsHelper(DteCommand command) { CommandId commandId; if (!command.TryGetCommandId(out commandId)) { yield break; } foreach (var cur in command.GetBindings()) { KeyBinding binding; if (KeyBinding.TryParse(cur, out binding)) { var name = command.Name; if (String.IsNullOrEmpty(name)) { name = string.Format("<Unnamed> {0}", commandId.Id); } yield return(new CommandKeyBinding(commandId, name, binding)); } } }
/// <summary> /// Does the Command have the provided KeyBinding as a valid binding /// </summary> public static bool HasKeyBinding(this DteCommand command, KeyBinding binding) { return(GetCommandKeyBindings(command).Any(x => x.KeyBinding == binding)); }
public static IEnumerable <KeyBinding> GetKeyBindings(this DteCommand command) { return(GetCommandKeyBindings(command).Select(x => x.KeyBinding)); }
/// <summary> /// Get the binding strings for this Command. Digs through the various ways a /// binding string can be stored and returns a uniform result /// </summary> public static IEnumerable <string> GetBindings(this DteCommand command) { Exception unused; return(GetBindings(command, out unused)); }
/// <summary>实现 IDTExtensibility2 接口的 OnConnection 方法。接收正在加载外接程序的通知。</summary> /// <param term='application'>宿主应用程序的根对象。</param> /// <param term='connectMode'>描述外接程序的加载方式。</param> /// <param term='addInInst'>表示此外接程序的对象。</param> /// <seealso class='IDTExtensibility2' /> public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom) { _applicationObject = (DTE2)application; _addInInstance = (EnvDTE.AddIn)addInInst; bool abc = _addInInstance.Connected; //初始化工具箱 _dteHelper = new DTEHelper(_applicationObject, _addInInstance); if (!_initAlreadySetup && (ext_ConnectMode.ext_cm_UISetup == connectMode || ext_ConnectMode.ext_cm_Startup == connectMode || ext_ConnectMode.ext_cm_AfterStartup == connectMode)) { CommandBars commandBars = (CommandBars)_applicationObject.CommandBars; try { IDictionary <string, EnvDTE.Command> dicCmd = new Dictionary <string, EnvDTE.Command>(3); //注册插件命令 foreach (var command in CommandManager.GetAllCommands()) { if (!Attribute.IsDefined(command.GetType(), typeof(CommandAttribute))) { continue; } //命令基本信息 CommandAttribute cmdAttribute = Attribute.GetCustomAttribute(command.GetType(), typeof(CommandAttribute)) as CommandAttribute; if (null == cmdAttribute || dicCmd.ContainsKey(cmdAttribute.Key)) { continue; } try { //注册命令 EnvDTE.Command cmd = _dteHelper.RegisterCommand(cmdAttribute.Key, cmdAttribute.Caption, cmdAttribute.Tooltip, cmdAttribute.UseMsoButton, cmdAttribute.IconResource, CommonHelper.Convert2VsCmdStatus(cmdAttribute.InitViewStatus)); dicCmd.Add(cmdAttribute.Key, cmd); } catch { // 可能是由于同名的命令已经存在了,忽略该异常 } } foreach (IMenuBar menuBar in MenuManager.GetAddinMenu()) { if (!Attribute.IsDefined(menuBar.GetType(), typeof(MenuAttribute))) { continue; } //菜单信息 MenuAttribute menuAttribute = Attribute.GetCustomAttribute(menuBar.GetType(), typeof(MenuAttribute)) as MenuAttribute; //附加栏信息 AdditionalBarAttribute[] additionalBarAttribute = Attribute.GetCustomAttributes(menuBar.GetType(), typeof(AdditionalBarAttribute)) as AdditionalBarAttribute[]; if (null == menuAttribute || null == additionalBarAttribute) { continue; } //缓存菜单项,以便卸载 _dicMenu.Add(menuAttribute.Key, menuBar); foreach (var s in additionalBarAttribute) { CommandBar menuBarCommandBar = commandBars[s.VsCommandBar]; //添加菜单 CommandBarControl menu = menuBarCommandBar.Controls.Add(menuAttribute.ControlType, Type.Missing, Type.Missing, menuAttribute.Position <= 0 ? menuBarCommandBar.Controls.Count : menuAttribute.Position, true); //菜单名 menu.Caption = menuAttribute.Caption; //提示文本 menu.TooltipText = menuAttribute.Tooltip; foreach (ICommand command in menuBar.CommandList) { if (!Attribute.IsDefined(command.GetType(), typeof(CommandAttribute))) { continue; } //命令基本信息 CommandAttribute cmdAttribute = Attribute.GetCustomAttribute(command.GetType(), typeof(CommandAttribute)) as CommandAttribute; if (null == cmdAttribute) { continue; } string strCmdName = FormatCommandName(cmdAttribute.Key); try { //给菜单附加命令 if (dicCmd.ContainsKey(cmdAttribute.Key)) { if (menu is CommandBarPopup) { dicCmd[cmdAttribute.Key].AddControl(((CommandBarPopup)menu).CommandBar, cmdAttribute.Position); } else { dicCmd[cmdAttribute.Key].AddControl(menu, cmdAttribute.Position); } if (!_dicCommand.ContainsKey(strCmdName)) { command.DteHelper = _dteHelper; _dicCommand.Add(strCmdName, command); } } } catch { } /* * CommandBarButton cbc = MsoControlType.msoControlPopup == menuBar.CommandMenu.ControlType * ? DTEHelper.GetInstance().AddButtonToPopup( * menu as CommandBarPopup, command.CommandButton.Position, * command.CommandButton.Caption, * command.CommandButton.Tooltip) * : DTEHelper.GetInstance().AddButtonToCmdBar( * menu as CommandBar, command.CommandButton.Position, * command.CommandButton.Caption, * command.CommandButton.Tooltip); * * //参数区分命令来源 * cbc.Parameter = string.Format("{0}.{1}.{2}", kvp.Key, menuBar.CommandMenu.Key, * command.CommandButton.Key); * //添加按钮事件 * cbc.Click += (CommandBarButton ctrl, ref bool @default) => * { * //第1位是窗口名,每2位是菜单名,每3位是命令名 * string[] strPara = ctrl.Parameter.Split('.'); * //取出菜单 * IMenuBar customMenu = this._dicMenuBar[strPara[1]]; * * foreach (ICommand cmd in customMenu.CommandList) * { * if (strPara[2].Equals(cmd.CommandButton.Key)) * { * CommandResult result = cmd.Exec(ctrl.Parameter); * if (0 != result.ErrCode) * MessageBox.Show(result.ErrMsg); * break; * } * } * }; */ } } } //插件加载标识 _initAlreadySetup = true; } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } }
/// <summary> /// Does the Command have the provided KeyBinding as a valid binding /// </summary> internal static bool HasKeyBinding(this Command command, KeyBinding binding) { return(GetCommandKeyBindings(command).Any(x => x.KeyBinding == binding)); }
internal CommandData(DteCommand command, ReadOnlyCollection <CommandKeyBinding> commandKeyBindings) { Command = command; CommandKeyBindings = commandKeyBindings; }
public bool TryGetCommand(CommandId id, out EnvDTE.Command command) { return(_commandListSnapshot.TryGetCommand(id, out command)); }
public bool TryGetCommandData(CommandId id, out DteCommand command, out ReadOnlyCollection<CommandKeyBinding> bindings) { CommandData commandData; if (!_commandMap.TryGetValue(id, out commandData)) { command = null; bindings = null; return false; } command = commandData.Command; bindings = commandData.CommandKeyBindings; return true; }
public bool TryGetCommand(CommandId id, out DteCommand command) { ReadOnlyCollection<CommandKeyBinding> bindings; return TryGetCommandData(id, out command, out bindings); }
public DTE_Command(DTE_Main InMain, EnvDTE.Command InCmd) { mMain = InMain; mCmd = InCmd; }
// Collapses all regions in the current document public static void CollapseAllRegions(DTE dte, Language language, MainPackage package, bool showErrors = true) { if (IsSupportedLanguage(language)) { dte.SuppressUI = true; // Disable UI while we do this try { // Outling must be enabled. If Outlining is turned off then the rest of this method will get stuck in an infinite loop. // It can be turned off by default from the C# advanced text editor properties, or it can be turned off by running // the Edit.StopOutlining command (e.g., in the Command window or via Edit -> Outlining -> Stop Outlining). // If the Edit.StartAutomaticOutlining command is available, then that means outlining needs to be turned back on. const string StartOutliningCommand = "Edit.StartAutomaticOutlining"; EnvDTE.Command command = dte.Commands.Item(StartOutliningCommand); if (command.IsAvailable) { dte.ExecuteCommand(StartOutliningCommand); } const string ToggleOutliningExpansion = "Edit.ToggleOutliningExpansion"; command = dte.Commands.Item(ToggleOutliningExpansion); const int MaxAttempts = 3; int maxAttempts = command.IsAvailable ? MaxAttempts : 0; string regionBeginRegex = GetRegionBeginRegex(language); // Sometimes VS can't collapse some regions, so we'll try the whole operation a few times if necessary. bool failedToCollapse = true; for (int attempt = 1; attempt <= maxAttempts && failedToCollapse; attempt++) { failedToCollapse = false; ExpandAllRegions(dte, language); // Force the expansion of all regions TextSelection selection = (TextSelection)dte.ActiveDocument.Selection; // Hook up to the ActiveDocument's selection selection.EndOfDocument(); // Shoot to the end of the document // Find the first occurence of #region from the end of the document to the start of the document. int currentFindOffset = 0; int previousFindOffset = int.MaxValue; const int FindOptions = (int)vsFindOptions.vsFindOptionsBackwards + (int)vsFindOptions.vsFindOptionsMatchCase + (int)vsFindOptions.vsFindOptionsRegularExpression; while (selection.FindText(regionBeginRegex, FindOptions)) { currentFindOffset = selection.TopPoint.AbsoluteCharOffset; if (currentFindOffset >= previousFindOffset) { // I don't want to get stuck in an infinite loop. I'd rather throw if something unexpected happens. throw new InvalidOperationException(string.Format( "FindText did not go backward! Previous offset: {0}; Current offset: {1}.", previousFindOffset, currentFindOffset)); } // We can ignore matches where #region is used inside a string or single line comment. // However, this still won't detect if it's used inside a multiline comment with the opening // delimiter on another line. selection.SelectLine(); string lineText = selection.Text ?? string.Empty; // Make sure the region begin token is the first non-whitespace on the line. Match match = Regex.Match(lineText.TrimStart(), regionBeginRegex); if (match.Success && match.Index == 0) { // The SelectLine call above will leave the end anchor on the next line. If there's no blank line between // a #region line and an XML doc comment after it, then having the end anchor on the line with the // XML doc comment will cause the comment to collapse instead of the #region. So we'll avoid that // by moving back to the find offset. selection.MoveToAbsoluteOffset(currentFindOffset); // Try to increase the chances that the ToggleOutliningExpansion command will be available. selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText); // Collapse this #region. Sometimes VS reports that the Edit.ToggleOutliningExpansion command // isn't available even though it should be. Poke it and give it a little bit of time to sync up. if (!command.IsAvailable) { const int WaitMilliseconds = 20; System.Threading.Thread.Sleep(WaitMilliseconds); int tempOffset = selection.TopPoint.AbsoluteCharOffset; selection.CharRight(); selection.MoveToAbsoluteOffset(tempOffset); System.Threading.Thread.Sleep(WaitMilliseconds); } if (command.IsAvailable) { // If #region is found in a multiline comment, then this will collapse the enclosing block. dte.ExecuteCommand(ToggleOutliningExpansion); } else { // We couldn't collapse a #region. failedToCollapse = true; } } // Move to the start of the last FindText match, so we can continue searching backward from there. selection.MoveToAbsoluteOffset(currentFindOffset); previousFindOffset = currentFindOffset; } selection.StartOfDocument(); // All done, head back to the start of the doc } if (failedToCollapse && package != null && showErrors) { package.ShowMessageBox( "Some regions couldn't be collapsed because Visual Studio's Edit.ToggleOutliningExpansion command wasn't available.", true); } } finally { dte.SuppressUI = false; // Reenable the UI } } }
/// <summary> /// Safely reset the bindings on this Command to the provided KeyBinding value /// </summary> public static void SafeSetBindings(this DteCommand command, KeyBinding binding) { SafeSetBindings(command, new[] { binding.CommandString }); }
public bool TryGetCommandData(CommandId id, out EnvDTE.Command command, out ReadOnlyCollection <CommandKeyBinding> bindings) { return(_commandListSnapshot.TryGetCommandData(id, out command, out bindings)); }
private void RunUISetup() { string toolsMenuName; try { //If you would like to move the command to a different menu, change the word "Tools" to the // English version of the menu. This code will take the culture, append on the name of the menu // then add the command to that menu. You can find a list of all the top-level menus in the file // CommandBar.resx. string resourceName; ResourceManager resourceManager = new ResourceManager(StudioshellResources, Assembly.GetExecutingAssembly()); CultureInfo cultureInfo = new CultureInfo(_applicationObject.LocaleID); if (cultureInfo.TwoLetterISOLanguageName == "zh") { System.Globalization.CultureInfo parentCultureInfo = cultureInfo.Parent; resourceName = String.Concat(parentCultureInfo.Name, "View"); } else { resourceName = String.Concat(cultureInfo.TwoLetterISOLanguageName, "View"); } toolsMenuName = resourceManager.GetString(resourceName); } catch { //We tried to find a localized version of the word Tools, but one was not found. // Default to the en-US word, which may work for the current culture. toolsMenuName = "View"; } //Place the command on the tools menu. //Find the MenuBar command bar, which is the top-level command bar holding all the main menu items: CommandBar menuBarCommandBar = ((CommandBars)_applicationObject.CommandBars)["MenuBar"]; //Find the Tools command bar on the MenuBar command bar: CommandBarControl viewControl = menuBarCommandBar.Controls[toolsMenuName]; CommandBarPopup viewPopup = (CommandBarPopup)viewControl; //This try/catch block can be duplicated if you wish to add multiple commands to be handled by your Add-in, // just make sure you also update the QueryStatus/Exec method to include the new command names. try { object[] contextGUIDS = new object[] { }; Commands2 commands = (Commands2)_applicationObject.Commands; SafeDeleteCommand("CodeOwls.StudioShell.Connect.StudioShell"); Command command = commands.AddNamedCommand2(_addInInstance, "StudioShell", "StudioShell", "Opens Studio Shell", false, 1, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton); command.Bindings = new object[] { "Global::Ctrl+Shift+Enter" }; //Add a control for the command to the tools menu: if ((command != null) && (viewPopup != null)) { command.AddControl(viewPopup.CommandBar, 1); } SafeDeleteCommand("CodeOwls.StudioShell.Connect.Execute"); command = commands.AddNamedCommand2(_addInInstance, "Execute", "Exceute", "Executes PowerShell from a Macro", false, 0, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStyleText, vsCommandControlType.vsCommandControlTypeButton); SafeDeleteCommand("CodeOwls.StudioShell.Connect.Cancel"); command = commands.AddNamedCommand2(_addInInstance, "Cancel", "Cancel Executing Pipeline", "Cancels the Currently Executing Studio Shell Pipeline", false, 2, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton); command.Bindings = new object[] { "Global::Ctrl+Shift+C" }; if ((command != null) && (viewPopup != null)) { command.AddControl(viewPopup.CommandBar, 2); } SafeDeleteCommand(StudioShellRestartCommandName); command = commands.AddNamedCommand2(_addInInstance, "ResetRunspace", "Reset StudioShell", "Resets the StudioShell Runspace", false, 3, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton); if ((command != null) && (viewPopup != null)) { command.AddControl(viewPopup.CommandBar, 2); } } catch (System.ArgumentException) { //If we are here, then the exception is probably because a command with that name // already exists. If so there is no need to recreate the command and we can // safely ignore the exception. } }
public bool TryGetCommand(CommandId id, out DteCommand command) { return(TryGetCommandData(id, out command, out ReadOnlyCollection <CommandKeyBinding> bindings)); }
internal static IEnumerable <KeyBinding> GetKeyBindings(this Command command) { return(GetCommandKeyBindings(command).Select(x => x.KeyBinding)); }