locked
Issue Overriding F5 (VS2010) RRS feed

  • Question

  • I have written a flavored project by subclassing FlavoredProjectBase.  It is hooked up and working properly.  My project type is a .dll, and when the user hits F5 (or various other ways of running/debugging) I would like to capture this event and provide my own logic.  (Think like WinPhone 7, which launches a custom emulator that runs the app.)

    I have done this by overriding ExecCommand in my FlavoredProject like this:

    if (pguidCmdGroup == VsMenus.guidStandardCommandSet97) {
      switch ((VsCommands)nCmdID) {
        case VsCommands.Start:
        case VsCommands.StartNoDebug:
          StartEmulator ();
          return VSConstants.S_OK;
      }
    }

    This works correctly, but *only* when the Solution Explorer window has focus.  If anything else, like a code editor or the properties window has focus, my code is never called, and the user is given the usual "Cannot start Class Library project type".  This happens even if my project is the startup project and is selected in Solution Explorer, but Solution Explorer doesn't have focus.

    Am I going about this the wrong way?  Is there a more "global" place I need to capture this event so that I always get it, no matter what has focus?

    Thanks for any help!

    Friday, July 2, 2010 4:18 PM

Answers

  • In case anyone ever tries to do this again, overriding ExecCommand is not the way to do this.  It subverts the whole "startup" project pattern, so you'll get the message to start even if you aren't the startup project, etc.

    The correct way to do this is of course extremely complicated.

    - Your flavored project needs to implement IVsProjectFlavorCfgProvider.
    - In CreateProjectFlavorCfg, you need to return a class that implements IVsProjectFlavorCfg.
    - This class needs to handle get_CfgType, check if it is asking for a IVsDebuggableProjectCfg via the guid, and if so, return a class that implements IVsDebuggableProjectCfg.
    - The IVsDebuggableProjectCfg interface has QueryDebugLaunch and DebugLaunch which you can handle to be notified when your project should start.  The rest of the methods can throw NotImplementedException.

    • Marked as answer by jpobst Thursday, September 23, 2010 8:00 PM
    Thursday, September 23, 2010 8:00 PM

All replies

  • Hello Jpobst,

    Please refer to the following code:

    public override int Exec(ref Guid guidCmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
    
    if (guidCmdGroup == Microsoft.VisualStudio.Shell.VsMenus.guidStandardCommandSet97) {
    if ((VsCommands)cmd == VsCommands.StartNoDebug) {
    // ... your processing
    return (int)OleConstants.OLECMDERR_E_CANCELED;
    }
    if ((VsCommands)cmd == VsCommands.BuildSln || (VsCommands)cmd == VsCommands.RebuildSln || (VsCommands)cmd == VsCommands.CleanSln) {
    // ... more processing
    }
    }
    return base.Exec(ref guidCmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
    }
    

    Try to replace the your message handling with above code. For more information, please see trapping the f5 menu command.  And please refer to IronPython Sample in Visual Studio 2008 SDK.

    Regards,

    Nancy Shao [MSFT]
    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg @ microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Monday, July 5, 2010 6:39 AM
  • That seems to be exactly what my code is.

    The difference is that Ruby and IronPython are based on MPFProj, which google tells me is only for new project types, not for flavored projects types.

    I ran the IronPython sample, and it does indeed always call Exec, even when the Solution Explorer isn't selected.  However, I still cannot get Exec to be called in my project when Solution Explorer isn't selected.

    Is MPFProj doing some other magic to register for this event?  Or is it simply a byproduct of being a new project instead of a flavored project?

    Tuesday, July 6, 2010 9:34 PM
  • Hello Jpobst,

    Have you overrided FlavoredProjectBase::IOleCommandTarget::Exec Method in your side? I think it would be work with Flavored Project.

    Regards,

    Nancy Shao [MSFT]
    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg @ microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by jpobst Friday, July 9, 2010 4:42 PM
    • Unmarked as answer by jpobst Thursday, September 23, 2010 8:01 PM
    Friday, July 9, 2010 9:34 AM
  • Have you overrided FlavoredProjectBase:: IOleCommandTarget::Exec Method in your side? I think it would be work with Flavored Project.

    I can't override it properly, as it's a private method.

    I added the IOleCommandTarget interface to my subclass, and provided an implementation of Exec, and it now works exactly like I want.

    I can't easily chain it to FlavoredProjectBase.Exec if I don't want to handle it, so I do this which should be roughly equivalent:

    return ((IOleCommandTarget)(this as System.IServiceProvider).GetService (typeof (IOleCommandTarget))).Exec (ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
    

    Thanks for your suggestion to get me pointed in the correct direction!
    • Marked as answer by jpobst Friday, July 9, 2010 4:42 PM
    • Unmarked as answer by jpobst Thursday, September 23, 2010 8:01 PM
    Friday, July 9, 2010 4:42 PM
  • In case anyone ever tries to do this again, overriding ExecCommand is not the way to do this.  It subverts the whole "startup" project pattern, so you'll get the message to start even if you aren't the startup project, etc.

    The correct way to do this is of course extremely complicated.

    - Your flavored project needs to implement IVsProjectFlavorCfgProvider.
    - In CreateProjectFlavorCfg, you need to return a class that implements IVsProjectFlavorCfg.
    - This class needs to handle get_CfgType, check if it is asking for a IVsDebuggableProjectCfg via the guid, and if so, return a class that implements IVsDebuggableProjectCfg.
    - The IVsDebuggableProjectCfg interface has QueryDebugLaunch and DebugLaunch which you can handle to be notified when your project should start.  The rest of the methods can throw NotImplementedException.

    • Marked as answer by jpobst Thursday, September 23, 2010 8:00 PM
    Thursday, September 23, 2010 8:00 PM