Debugging MSBuild script with Visual Studio (3)

Debugging MSBuild script with Visual Studio (3)

  • Comments 9

In my last two posts (here and here) I showed how to enable the unsupported MSBuild debugger to debug a build started on the command line with MSBuild.exe. In this final post, I'll mention some other variations.

Note that this blog is rather narrow, so some of the screenshots may be hard to see – you can click on them to see the full size version.

Scenario 3: Debug a Solution file on the command line

In the previous example, I launched msbuild.exe against a project file. You well might want to start with a solution file instead. If you do, you may get an error that looks like this:

Microsoft.Build.Shared.InternalErrorException: MSB0001: Internal MSBuild Error: Mismatched leave was C:\Users\danmose\Do
cuments\visual studio 2010\Projects\WindowsFormsApplication1\WindowsFormsApplication1.sln.metaproj expected C:\Users\dan
mose\Documents\visual studio 2010\Projects\WindowsFormsApplication1\WindowsFormsApplication1.csproj (2,1)

The workaround is as follows. First, set an environment variable MSBUILDEMITSOLUTION=1. Then do a build of the solution in the regular way: if you want, you can cancel it after it starts building projects. Next to the solution file, you should see a file with the extension ".sln.metaproj". This is essentially the solution file translated into MSBuild-format. Now do the usual debugging procedure, but this time launch msbuild.exe against this sln.metaproj file instead of the original solution file.

Scenario 4: Multiprocessor build

When you're debugging your build process or tasks, it's much easier to follow if only one project is building at a time, and you'll probably do it that way whenever you can. What's more, debugging slows down the build so much that it may not help you diagnose a timing problem anyway.

If however for some reason you do need to debug a multiprocessor build, it's possible.

As you probably know, MSBuild launches child processes to build more than one project at once, and they persist for a while to be ready for another build. The /debug switch doesn't propagate to them. To get this to work, first terminate any msbuild.exe processes that are still alive. Then in a command window set an environment variable MSBUILDDEBUGGING=1. That environment variable is equivalent to the /debug switch, but unlike the switch it will get propagated to any child processes.

From this command window now start msbuild.exe with the /debug switch as usual. Everything will work much the same as before, but you'll get a new JIT prompt as each child process starts to do its work, and you'll have to use a new instance of Visual Studio for each one of them.

For example, I'm building a solution here, using the .metaproj workaround I mentioned above. Attaching at the first JIT prompt, I can see I am starting in the .metaproj itself:

image

If I hit Continue (F5) I'll get to the top of the next project, and stop there as usual. In the callstack window, I can see that the solution has invoked that project, and I can double click on the lower frame in the callstack to see where it did that – it's an MSBuild task, of course:

image

While I'm stopped here, I get a JIT prompt again. This time it's for the other project in my solution, which has already started to load in parallel in another msbuild.exe process. I'll go through the JIT prompts as I did before, and select to start a new instance of Visual Studio. That will in turn break in at the top of that other project.

Here's what I see now:

image

Visual Studio supports debugging more than one process at the same time, which would be more convenient, but I don't think the JIT launcher will let you do that. If you have a lot of child processes, it could get rather cumbersome. Remember that the "/m" switch defaults to the same number of processes as you have CPU's, so you may want to cut it down with "/m:2".

 

 

 

Scenario 5: Debugging projects while they are loaded in Visual Studio

When I wrote the prototype, it was also possible to debug the evaluation and building of projects loaded in Visual Studio.

Unfortunately in walking through this scenario to write this blog post, I was sorry to find that it's somewhat broken in the release version of Visual Studio 2010. In my experiments debugging works through the first evaluation, as the projects are loaded, but then it hits a bug and terminates. Since it's an untested feature there's always the chance something can break without detection and that's apparently what happened here.

Given that, you'll most likely have to stick with msbuild.exe. However, I'll go ahead and explain a little about how one would do this in Visual Studio, in case you have better luck than I do.

Start off by setting the registry key as described at the start of my first post and kill any lingering instances of MSBuild.exe as you did in the last scenario.

Make sure the environment variable MSBUILDDEBUGGING is not set and open your first Visual Studio to act as your debugger. You can do this from the start menu. As before make sure Just-My-Code is switched on in this instance.

Open a command prompt and set the environment variable MSBUILDDEBUGGING=1 again. Then launch Visual Studio from that command prompt -- most likely you'd start it with a command like "%ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe". This second instance is your debuggee, which you will load your projects into.

Go back to the debugger process, and attach to that debuggee, choosing the "Managed (v4.0)" engine as always. In this debugger process, open up the project or targets file you want to start debugging through. Make sure you open it with "Open File" into the XML editor, rather than loading it as an actual project.

Debugging may not start automatically on the first line this time, so set a breakpoint where you want to begin. I opened the "WindowsFormsApplication1.csproj" file I used before into the XML editor, and set a breakpoint on the first line to get hit when the project is first loaded.

Open up your project or projects in the normal way in the debuggee now and you should see your breakpoint is hit. Step a little further, and for me, Visual Studio terminates.

End of the Walkthrough

Now I've shown you all the features of the MSBuild debugger, I hope you'll try it out.

If you have feedback, do post it here. In particular, how important is it to be able to debug projects loaded inside Visual Studio? Also, as you've seen, MSBuild must be in "debugging mode" from launch -- it's not possible to walk up to a regular build that's in progress and attach to it. Is it important to be able to do that?

Most of all, how useful is this to you, and how problematic are the bugs and limitations you run into?

Thanks for reading

Dan

Visual Studio Project & Build Dev Lead

Leave a Comment
  • Please add 3 and 3 and type the answer here:
  • Post
  • Excellent post Dan.

  • Most important feature??

    100% most important feature is to keep it downwards compatible so that people who have used it does not need to learn new methods only because some i***t want to rewrite everything. Nice to have finally for example Class Wizard back after 10 years of waiting.

    First fix all old bugs before writing new ones!

  • Hi there,

    I tried to get this done:

    "The workaround is as follows. First, set an environment variable MSBUILDEMITSOLUTION=1. Then do a build of the solution in the regular way: if you want, you can cancel it after it starts building projects. Next to the solution file, you should see a file with the extension ".sln.metaproj"."

    Anyway I'm not able to get the .sln.metaproj file - how do you set the environment variable in VS2010?

    I tried to set them in cmd and launched VS2010 out of the cmd - doesn't work.

    I set them as user and system environment variables - doesn't work.

    How I supposed to set them successfully?

    I'm running VS2010 Ultimate on a Windows Server 2008 R2 x64.

    KR,

    Joe

  • If you set the environment using the system control panel, you have to restart VS before they will take effect.  An easier way to do this is to launch a Visual Studio Command Prompt, set the environment there, then run devenv.exe from that command prompt.

  • @Joe

    To get the .metaproj you must run msbuild.exe on the solution file. (You'll then go on to debug using msbuild.exe against that metaproj, too.)

    If you still don't get the metaproj, make certain you're running the 4.0 MSBuild.

    Dan

  • is there any know zte modem ? www.3gmodem.com.hk/ZTE.html

  • @Feature X -- comment about back compat.

    What are you specifically referring to? The converter that prevents projects being opened in previous versions of VS? Changes in the UI? Features that were removed? MSBuild or Visual Studio?

    Dan

  • We have our own VS integration (language service, project system, and msbuild task to generate response line commands) which in my machine I have set to run in the VS EXP hive. How do I start MSBuild so it can find my language/extension in the EXP hive? something like the /rootsuffix EXP switch for devenv?

  • Great Post Dan.  It works cool..

Page 1 of 1 (9 items)