locked
Enable commands in Isolated Shell RRS feed

  • Question

  • Hi,

    I have a custom language service in VS Isolated Shell (VS 2013) in MPF. I want to enable the "Exclude from Project" command, and the "Rename" (for refactorization) command.

    To this end, I added those lines to my vstc file:

      <UsedCommands>
        <UsedCommand guid="guidVsCommands97" id="cmdRename" />
        <UsedCommand guid="guidVsCommands2k" id="cmdExcludeFromProject" />
      </UsedCommands>
    
      <Symbols>
        <GuidSymbol name="guidVsCommands97" value="{5efc7975-14bc-11cf-9b2b-00aa00573819}">
          <IDSymbol name="cmdRename" value="150"/>
        </GuidSymbol>
        <GuidSymbol name="guidVsCommands2k" value="{1496A755-94DE-11D0-8C3F-00C04FC2AAE2}">
          <IDSymbol name="cmdExcludeFromProject" value="1110"/>
        </GuidSymbol>
      </Symbols>

    However, no matter what I do, HierarchyNode.QueryStatusOnNode() or ViewFilter.QueryCommandStatus() are never called with those respective GUID-CMD pairs. What do I have to do to "activate" those two standard Visual Studio commands?

    Thanks & regards,
    Max




    Thursday, October 30, 2014 3:04 PM

Answers

  • Hi Max,

    If you aren't see it being invoked, then it's likely the command wasn't properly included via the UsedCommands section of your iso shell's ApplicationCommands.vsct.

    I built a new isolated shell project, added in the MPFProj Custom Project package, and then added the following at the end of my ApplicationCommands.vsct file, and the Exclude From Project showed up (and works). Note, you can use the predefined values below without defining them in your <Symbols> section of the .vsct.

    ....

      <UsedCommands>
        <UsedCommand guid="guidVSStd2K" id="ECMD_EXCLUDEFROMPROJECT"/>
      </UsedCommands>

    </CommandTable>

    With respect to the rename command, that's the command that renames the file (it's not a refactoring command), it's basically the rename document command.

    The refactoring rename command is defined in the SharedCmdDef.vsct as follows:

          <!-- -->
          <!--// Refactoring Commands - shared between C#, J#, and VB -->
          <!-- -->
          <Button guid="guidVSStd2K" id="ECMD_RENAME" priority="0x0000" type="Button">
            <Icon guid="guidRefactorIcon" id="IDBI_Rename"/>
            <CommandFlag>DynamicVisibility</CommandFlag>
            <CommandFlag>DefaultInvisible</CommandFlag>
            <CommandFlag>DefaultDisabled</CommandFlag>
            <Strings>
              <ButtonText>&amp;Rename...</ButtonText>
              <MenuText>&amp;Rename...</MenuText>
              <ToolTipText>Rename</ToolTipText>
              <CommandName>Rename</CommandName>
              <CanonicalName>.Refactor.Rename</CanonicalName>
              <LocCanonicalName>.Refactor.Rename</LocCanonicalName>
            </Strings>
          </Button>

    Doing a search, I see a CommandPlacement defined for this button in the SharedCmdPlace.vsct, but that is never referenced or included in an iso shell project. This isn't terribly surprising given the comment at the head of this particular command's definition.

    But if I add this to the same UsedCommands block in my iso shell's ApplicationCommands.vsct file:

      <UsedCommands>
        <UsedCommand guid="guidVSStd2K" id="ECMD_EXCLUDEFROMPROJECT"/>
        <UsedCommand guid="guidVSStd2K" id="ECMD_RENAME"/>
      </UsedCommands>

    And then enable the command from the Custom project's HierarchyNode.QueryStatusSelection

            protected virtual int QueryStatusSelection(Guid cmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText, CommandOrigin commandOrigin)
            {
                if (cmdGroup == VsMenus.guidStandardCommandSet2K && prgCmds[0].cmdID == 1550)
                {
                    System.Diagnostics.Debug.WriteLine("Found the rename command!!!");
                    prgCmds[0].cmdf = (uint)OLECMDF.OLECMDF_ENABLED | (uint)OLECMDF.OLECMDF_SUPPORTED;
                    return VSConstants.S_OK;
                }

    The Refactor popup with the enabled Rename... command does get displayed.

    It's important to point out that while I enabled command in the project hierarchy, this isn't where you'd normally do this. The guidVSStd2K::ECMD_RENAME command is typically handled in the viewfilter of the language service. I only did so here for testing purposes, and I don't have a language service plugged into the iso shell. But once you've got the menu properly added, you should see your view filter's IOleCommandTarget::QueryStatus getting invoked for guidVSStd2K::ECMD_RENAME.

    Sincerely,


    Ed Dore

    Tuesday, November 4, 2014 7:46 PM

All replies

  • Hi Max,

    Do you mean you've created a language service VSPackage for the Isolated Shell, and you add those lines to the VSPackage's vsct file?


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, October 31, 2014 7:23 AM
  • Sorry that I wasn't clear enough in the first place. But yes, that's exactly what I did.
    Friday, October 31, 2014 8:09 AM
  • I haven't tried this in the isolated shell, but I can't imagine this would be any different with the integrated shell.

    The VsCommands2K.EXCLUDEFROMPROJECT command is enabled by default, in the FileNode.QueryStatusOnNode method:

                else if(cmdGroup == VsMenus.guidStandardCommandSet2K)
                {
                    if((VsCommands2K)cmd == VsCommands2K.EXCLUDEFROMPROJECT)
                    {
                        result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
                        return VSConstants.S_OK;
                    }

    The VSStd97CmdID.Rename command is explicitly disabled in the HierarchyNode.QueryStatusCommandFromOleCommandTarget, but it looks to be explicitly enabled in both the FolderNode and FileNode QueryStatusOnNode methods:

                if(cmdGroup == VsMenus.guidStandardCommandSet97)
                {
                    switch((VsCommands)cmd)
                    {
                        case VsCommands.Copy:
                        case VsCommands.Paste:
                        case VsCommands.Cut:
                        case VsCommands.Rename:
                            result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
                            return VSConstants.S_OK;

    Did you by chance override these methods in your own class, and forget to invoke the method on the base class?

    Best recommendation I can make is to add a simple conditional you can set a breakpoint on, where these commands come into your project. Namely, the HierarchyNode.QueryStatus and HierarchyNode.QueryStatusCommand methods. For example:


                if (cmdGroup == VSConstants.GUID_VSStandardCommandSet97 && prgCmds[0].cmdID == (uint)VSConstants.VSStd97CmdID.Rename)
                {
                    System.Diagnostics.Debug.WriteLine("Rename!!!");
                }

                if (cmdGroup == VSConstants.VSStd2K && prgCmds[0].cmdID == (uint)VSConstants.VSStd2KCmdID.EXCLUDEFROMPROJECT)
                {
                    System.Diagnostics.Debug.WriteLine("ExcudeMe");
                }

    The step through the debugger to see where/why these commands are getting disabled (or not enabled).

    Sincerely,


    Ed Dore

    Friday, October 31, 2014 8:54 PM
  • Hi,

    I already did that, and those methods are not even called with the respective GUID/CMD pairs. I set a breakpoint in HierarchyNode.QueryStatus(), and it's not called with the ExcludeFromProject. The same is true for ViewFilter.QueryCommandStatus() and the Rename command (for refactorization).

    So I think the problem is located deeper: Visual Studio doesn't even check the availability of those commands using any of the Query[...]() methods.

    Regards,
    Max

    Friday, October 31, 2014 10:31 PM
  • Hi Max,

    If you aren't see it being invoked, then it's likely the command wasn't properly included via the UsedCommands section of your iso shell's ApplicationCommands.vsct.

    I built a new isolated shell project, added in the MPFProj Custom Project package, and then added the following at the end of my ApplicationCommands.vsct file, and the Exclude From Project showed up (and works). Note, you can use the predefined values below without defining them in your <Symbols> section of the .vsct.

    ....

      <UsedCommands>
        <UsedCommand guid="guidVSStd2K" id="ECMD_EXCLUDEFROMPROJECT"/>
      </UsedCommands>

    </CommandTable>

    With respect to the rename command, that's the command that renames the file (it's not a refactoring command), it's basically the rename document command.

    The refactoring rename command is defined in the SharedCmdDef.vsct as follows:

          <!-- -->
          <!--// Refactoring Commands - shared between C#, J#, and VB -->
          <!-- -->
          <Button guid="guidVSStd2K" id="ECMD_RENAME" priority="0x0000" type="Button">
            <Icon guid="guidRefactorIcon" id="IDBI_Rename"/>
            <CommandFlag>DynamicVisibility</CommandFlag>
            <CommandFlag>DefaultInvisible</CommandFlag>
            <CommandFlag>DefaultDisabled</CommandFlag>
            <Strings>
              <ButtonText>&amp;Rename...</ButtonText>
              <MenuText>&amp;Rename...</MenuText>
              <ToolTipText>Rename</ToolTipText>
              <CommandName>Rename</CommandName>
              <CanonicalName>.Refactor.Rename</CanonicalName>
              <LocCanonicalName>.Refactor.Rename</LocCanonicalName>
            </Strings>
          </Button>

    Doing a search, I see a CommandPlacement defined for this button in the SharedCmdPlace.vsct, but that is never referenced or included in an iso shell project. This isn't terribly surprising given the comment at the head of this particular command's definition.

    But if I add this to the same UsedCommands block in my iso shell's ApplicationCommands.vsct file:

      <UsedCommands>
        <UsedCommand guid="guidVSStd2K" id="ECMD_EXCLUDEFROMPROJECT"/>
        <UsedCommand guid="guidVSStd2K" id="ECMD_RENAME"/>
      </UsedCommands>

    And then enable the command from the Custom project's HierarchyNode.QueryStatusSelection

            protected virtual int QueryStatusSelection(Guid cmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText, CommandOrigin commandOrigin)
            {
                if (cmdGroup == VsMenus.guidStandardCommandSet2K && prgCmds[0].cmdID == 1550)
                {
                    System.Diagnostics.Debug.WriteLine("Found the rename command!!!");
                    prgCmds[0].cmdf = (uint)OLECMDF.OLECMDF_ENABLED | (uint)OLECMDF.OLECMDF_SUPPORTED;
                    return VSConstants.S_OK;
                }

    The Refactor popup with the enabled Rename... command does get displayed.

    It's important to point out that while I enabled command in the project hierarchy, this isn't where you'd normally do this. The guidVSStd2K::ECMD_RENAME command is typically handled in the viewfilter of the language service. I only did so here for testing purposes, and I don't have a language service plugged into the iso shell. But once you've got the menu properly added, you should see your view filter's IOleCommandTarget::QueryStatus getting invoked for guidVSStd2K::ECMD_RENAME.

    Sincerely,


    Ed Dore

    Tuesday, November 4, 2014 7:46 PM