locked
How to: Run Add-ins on the Command Line RRS feed

Answers

  • Hi,

    Sorry for the delay answering.

    I have created a C# add-in from scratch named CommandLineAddin using VS 2008 and the following statement does open Visual Studio and shows the messagebox that the command displays when executed:

    "C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe" /command CommandLineAddin.Connect.MyCommand

    The code of the Connect.cs is the following:

    using System;
    using Extensibility;
    using EnvDTE;
    using EnvDTE80;

    namespace CommandLineAddin
    {
        public class Connect : IDTExtensibility2, IDTCommandTarget
        {
          const string COMMAND_NAME = "MyCommand";

          private DTE2 _applicationObject;
          private AddIn _addInInstance;
          
          public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
            {
             object[] contextGUIDS = new object[] {};
             Commands2 commands;
             Command command = null;
             
             _applicationObject = (DTE2)application;
                _addInInstance = (AddIn)addInInst;

             commands = (Commands2)_applicationObject.Commands;

             // Try to get the command
             try
             {
                command = commands.Item(_addInInstance.ProgID + "." + COMMAND_NAME, 0);
             }
             catch
             {
             }
             
             // If the command doesn't exist, create it
             if (command == null)
             {
                try
                   {
                       command = commands.AddNamedCommand2(_addInInstance, COMMAND_NAME, "My command", "Executes my command", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
                   }
                   catch
                   {
                   }
             }
            }

            public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
            {
            }

            public void OnAddInsUpdate(ref Array custom)
            {
            }

            public void OnStartupComplete(ref Array custom)
            {
            }

            public void OnBeginShutdown(ref Array custom)
            {
            }
            
            public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText)
            {
                if(neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
                {
                    if(commandName == _addInInstance.ProgID + "." + COMMAND_NAME)
                    {
                        status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
                        return;
                    }
                }
            }

            public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
            {
                handled = false;
                if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
                {
                    if(commandName == _addInInstance.ProgID + "." + COMMAND_NAME)
                    {
                        handled = true;
                   System.Windows.Forms.MessageBox.Show("Executed: " + commandName);
                        return;
                    }
                }
            }
        }
    }


    MZ-Tools: Productivity add-ins for Visual Studio: http://www.mztools.com. My blog about developing add-ins: http://msmvps.com/blogs/carlosq/



    Thursday, March 14, 2013 2:42 PM
  • Hi,

    When I post a sample for others and in my articles I tend to use best practices to avoid hardcoded strings and make the code more portable to other wizard-generated add-in project. So I use:

    - _addInInstance.ProgID

    - A constant for the command short name

    I think only the namespace is not changed.

    About the DTE UI shown, yes, in the sample is shown because devenv.exe shows it by default and my command shows a MessageBox. I wanted to prove that add-in commands can be executed from the command-line.

    If you are executing devenv.exe with the /Build switch to build a solution, which is likely the only point for running from the command line, the UI won't be shown, but your command should do something different to showing a MessageBox (and more difficult to guess if it is doing it or not in a sample).

    Finally, see my old post:

    Frustrations with command-line add-ins for Visual Studio
    http://msmvps.com/blogs/carlosq/archive/2007/10/11/frustrations-with-command-line-add-ins-for-visual-studio.aspx


    MZ-Tools: Productivity add-ins for Visual Studio: http://www.mztools.com. My blog about developing add-ins: http://msmvps.com/blogs/carlosq/

    • Marked as answer by Ego Jiang Tuesday, March 19, 2013 1:40 AM
    Friday, March 15, 2013 7:26 AM

All replies

  • Hi,

    Please verify the following:

    1) In the Add-In Manager:

    * The add-in appears

    * It is marked command-line safe

    2) In the "Tools", "Options" window, "Environment", "Keyboard" section, "Show commands containing" list, the MyAddin.Connect.MyAddin command name appears.

    3) The add-in (or at least that command) doesn't need or show user interface elements.


    MZ-Tools: Productivity add-ins for Visual Studio: http://www.mztools.com. My blog about developing add-ins: http://msmvps.com/blogs/carlosq/


    • Edited by Carlos J. Quintero Monday, March 11, 2013 5:21 PM fix
    • Proposed as answer by Ego Jiang Tuesday, March 12, 2013 2:07 AM
    • Unproposed as answer by mplatham Wednesday, March 13, 2013 2:33 AM
    Monday, March 11, 2013 5:20 PM
  • All of the above appear correct but I am still getting the same error. I created a vanilla Addin using the wizard with the only options checked:

    • Create an Add-in using Visual C#
    • Microsoft Visual Studio
    • My Add-in will never put up modal UI

    MyAddin is in Tools>Options>Environment>Keyboard under Apply the following mappings to Visual C# 2005

    An at the command prompt (As administrator)

    • "C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe" /command MyAddin.Connect.MyAddin

    From MyAddin1 - For Testing.Addin:

    <HostApplication>
    	<Name>Microsoft Visual Studio</Name>
    	<Version>9.0</Version>
    </HostApplication>
    <Addin>
    	<FriendlyName>MyAddin1 - No Name provided.</FriendlyName>
    	<Description>MyAddin1 - No Description provided.</Description>
    <Assembly>d:\Projects\MyAddin1\MyAddin1\bin\Project1.dll</Assembly>
    	<FullClassName>MyAddin1.Connect</FullClassName>
    	<LoadBehavior>4</LoadBehavior>
    	<CommandPreload>0</CommandPreload>
    	<CommandLineSafe>1</CommandLineSafe>
    </Addin>

    I also tried changing to <LoadBehavior>0</LoadBehavior> and other combinations.


    Mark Latham

    After devenv /ResetAddin MyAddin.Connect.MyAddin

    I now have a different error:

    The following files were specified on the command line

    MyAddin1,Connect.MyAddin1

    Thes files could not be found and will not be loaded

    • Edited by mplatham Wednesday, March 13, 2013 4:57 AM
    Wednesday, March 13, 2013 2:32 AM
  • Hi,

    Sorry for the delay answering.

    I have created a C# add-in from scratch named CommandLineAddin using VS 2008 and the following statement does open Visual Studio and shows the messagebox that the command displays when executed:

    "C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe" /command CommandLineAddin.Connect.MyCommand

    The code of the Connect.cs is the following:

    using System;
    using Extensibility;
    using EnvDTE;
    using EnvDTE80;

    namespace CommandLineAddin
    {
        public class Connect : IDTExtensibility2, IDTCommandTarget
        {
          const string COMMAND_NAME = "MyCommand";

          private DTE2 _applicationObject;
          private AddIn _addInInstance;
          
          public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
            {
             object[] contextGUIDS = new object[] {};
             Commands2 commands;
             Command command = null;
             
             _applicationObject = (DTE2)application;
                _addInInstance = (AddIn)addInInst;

             commands = (Commands2)_applicationObject.Commands;

             // Try to get the command
             try
             {
                command = commands.Item(_addInInstance.ProgID + "." + COMMAND_NAME, 0);
             }
             catch
             {
             }
             
             // If the command doesn't exist, create it
             if (command == null)
             {
                try
                   {
                       command = commands.AddNamedCommand2(_addInInstance, COMMAND_NAME, "My command", "Executes my command", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
                   }
                   catch
                   {
                   }
             }
            }

            public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
            {
            }

            public void OnAddInsUpdate(ref Array custom)
            {
            }

            public void OnStartupComplete(ref Array custom)
            {
            }

            public void OnBeginShutdown(ref Array custom)
            {
            }
            
            public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText)
            {
                if(neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
                {
                    if(commandName == _addInInstance.ProgID + "." + COMMAND_NAME)
                    {
                        status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
                        return;
                    }
                }
            }

            public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
            {
                handled = false;
                if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
                {
                    if(commandName == _addInInstance.ProgID + "." + COMMAND_NAME)
                    {
                        handled = true;
                   System.Windows.Forms.MessageBox.Show("Executed: " + commandName);
                        return;
                    }
                }
            }
        }
    }


    MZ-Tools: Productivity add-ins for Visual Studio: http://www.mztools.com. My blog about developing add-ins: http://msmvps.com/blogs/carlosq/



    Thursday, March 14, 2013 2:42 PM
  • Ok that works  although I had to connect the addin via the addin manager first.

    I am a bit confused though:

    Why did you have to create the new "MyCommand"?

    Doesn't the add create a command with the addin name - in your case "CommandLineAddin"?

    If it does i couldn't see it using:

    command2 = commands.Item(_addInInstance.ProgID+"."+"CommandLineAddin", 1);
    The DTE UI is still started. I was expecting that there would be no UI or what is the point of running it at the command line?

    Mark Latham


    • Edited by mplatham Friday, March 15, 2013 6:36 AM
    Friday, March 15, 2013 6:36 AM
  • Hi,

    When I post a sample for others and in my articles I tend to use best practices to avoid hardcoded strings and make the code more portable to other wizard-generated add-in project. So I use:

    - _addInInstance.ProgID

    - A constant for the command short name

    I think only the namespace is not changed.

    About the DTE UI shown, yes, in the sample is shown because devenv.exe shows it by default and my command shows a MessageBox. I wanted to prove that add-in commands can be executed from the command-line.

    If you are executing devenv.exe with the /Build switch to build a solution, which is likely the only point for running from the command line, the UI won't be shown, but your command should do something different to showing a MessageBox (and more difficult to guess if it is doing it or not in a sample).

    Finally, see my old post:

    Frustrations with command-line add-ins for Visual Studio
    http://msmvps.com/blogs/carlosq/archive/2007/10/11/frustrations-with-command-line-add-ins-for-visual-studio.aspx


    MZ-Tools: Productivity add-ins for Visual Studio: http://www.mztools.com. My blog about developing add-ins: http://msmvps.com/blogs/carlosq/

    • Marked as answer by Ego Jiang Tuesday, March 19, 2013 1:40 AM
    Friday, March 15, 2013 7:26 AM