8

I have a solution with multiple start-up projects, and I am trying to relaunch one of them automatically on a nightly basis, while keeping the new process attached to the same debugger.

I was able to restart the process (using Process.Start) and attach the current debugger to it, but it has not been highly reliable so far, and by design, clicking on the Stop button only detaches from the process rather than terminating it.

I am aware the Visual Studio team has released a Visual Studio extension that allows automatically attaching child processes to the current debugger, which may work better than my code, but it would not be portable as it requires a local configuration.

The easiest way to achieve what I need seems to programmatically relaunch the project using the IDE itself, as I would do manually by right clicking on the project and selecting Debug > Start New Instance. I have access to the relevant DTE object in my code (when in development).

Hence, is there any way to make the following pseudo-code work, asking Visual Studio to start debugging a specific project/exe by passing it as a command argument?

DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance", "ProjectToBeRestarted");

DTE.ExecuteCommand("Debug.Start", "ProjectToBeRestarted");

DTE.ExecuteCommand("Debug.Start", "ProjectToBeRestarted.exe");

I would like to avoid as much as possible manipulating the UI (like storing the original start-up projects, setting an new one, and restoring the start-up projects).

Cœur
  • 37,241
  • 25
  • 195
  • 267
Erwin Mayer
  • 18,076
  • 9
  • 88
  • 126
  • See also: http://stackoverflow.com/questions/96250/can-i-create-a-visual-studio-macro-to-launch-a-specific-project-in-the-debugger/32282888#32282888 – Erwin Mayer Aug 29 '15 at 05:04

1 Answers1

5

The problem you are facing is there are very few Visual Studio commands that accept arguments as input. This makes sense considering commands typically use the current IDE context (e.g. selection, caret position, etc.) to infer what should actually be done. For instance, the ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance command relies on the currently selected item in the Solution Explorer to know which project to start debugging, and it does not accept an argument.

For reference, you can find the full list of Visual Studio commands accepting arguments here: https://msdn.microsoft.com/en-us/library/c338aexd.aspx

To solve your issue, you will need to use the DTE object to set the current project selection first, and then execute the Startnewinstance command.

DTE.ToolWindows.SolutionExplorer.GetItem("SolutionNameHere\\ProjectNameHere").Select(vsUISelectionType.vsUISelectionTypeSelect)
DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance")

Note: Depending on your programming language, the double backslash escape may or may not be needed. The final string should only have a single backslash.

jgg99
  • 336
  • 1
  • 6
  • Thanks for the workaround, it is not perfect as trouble could arise if the user messes up with the selection at the same time the code kicks in, but it could well be the best possible answer with standard IDE commands (I wish the Visual Studio API was more comprehensive). – Erwin Mayer Aug 27 '15 at 17:01
  • 1
    If the code is executed synchronously, there should not be any time window for the user to interfere. This was a standard usage pattern for macros back in VS2010. The alternative is to go through the DTE.Debugger route instead, which gives you access to the lower-level Debugger5 interface from which you can get a Process4 interface to attach the debugger to after starting the process. But this goes beyond the scope of your original question (i.e. VS commands). – jgg99 Aug 27 '15 at 17:28
  • Good to know indeed. I am very interested in the alternate solution with the Debugger5 interface you mention. Is it possible to start debugging the program (exe or project) from the debugger object itself rather than attaching to it? Here is the code I am using to attach to an existing process https://gist.github.com/mayerwin/82301024371e9c555d24. My code works but I would prefer the project to be started by the debugger itself to have exactly the same behavior as if I was starting it manually (process killed rather than being detached when "stopping", and visible breakpoints interruptions). – Erwin Mayer Aug 28 '15 at 16:39
  • Your code is very similar to how I've used the Debugger interface before. As far as I know, you can only use the interface to attach to processes, it is not responsible for launching them. From my search through the documentation, there does not seem to be a way in the automation model to launch debugging for a specific project, other than what I have described in my answer. – jgg99 Aug 28 '15 at 18:08
  • 1
    However, for your surviving process problem, you could (ab)use the fact that the Managed debugging engine does not support detaching from processes, it will kill them when the debug session is over. You can use the Attach2 method from the Process4 interface to specify both Native and Managed debugging engines. This is quite a dirty hack that is not guaranteed to work in the future, however. – jgg99 Aug 28 '15 at 18:11
  • OK I'll try that with engine "Managed/Native", thanks for the suggestion. Maybe it will also solve the breakpoint issues (the fact that I was not specifying any engine before). Is there any important difference between the Process4 and Process2 interfaces, for our purpose? Should I change this in my code? – Erwin Mayer Aug 28 '15 at 19:22
  • There are a few minor differences that should not be relevant in your use case, it is just the most recent version. You can keep using the Process2 interface if you wish. – jgg99 Aug 28 '15 at 19:54
  • Specifying "Managed/Native" will indeed make the debugger kill the process upon stopping. Good to know. The only issue that remains is the breakpoints being hits but not shown (with the yellow line). I tried your initial solution with the VS Command, but an issue is that Visual Studio will sometimes try recompiling when starting a new instance, which will fail if the same exe is already running (which is the case in my scenario as I try to relaunch the process). – Erwin Mayer Aug 29 '15 at 06:21
  • Are you aware of a way to programmatically disable rebuilding before launching a new instance (just adding a breakpoint will trigger rebuilding otherwise)? – Erwin Mayer Aug 29 '15 at 11:08
  • It appears you also need to activate the `Solution Explorer` window. Otherwise the `Startnewinstance` command can execute using the open document window if it was selected last. – MikeH Nov 06 '17 at 22:52