Serve up Debug Symbols for your NuGet packages? Heck yeah!

By | January 12, 2015

While playing around with NuGet as much as I have been, I noticed something in the ‘nuget pack’ command that I thought was pretty interesting. A ‘-symbols’ flag.

“What’s this do?” I thought. So, naturally, I gave it a shot.

What NuGet spat out for me was a <my module>.<version>.symbols.nupkg file along with the normal <my module>.<version>.nupkg package I know and love. I cracked this thing open and saw under \lib my DLL and my PDB, and under \src all the source code for my module.

Pretty cool, right? Well, only if you want to make your source code available. So keep that in mind as we move forward. If you want your module to be used, but not debugged or reverse-engineered, this is not for you.

Anyway, I looked in to the purpose of this at NuGet’s documentation area. Now, by default NuGet – being the “give it all to the world” kind of system it is – will take a symbol package and automatically publish it to the public SymbolSource.org feed. This is another reason to really take note of what you’re doing as you walk through this post. If you do this wrong, your symbols could end up on a public symbol server.

If you read through the doco, you can see how to build a symbol package, what it means, and how to use those symbols from within Visual Studio. But, given my earlier post, you can imagine that’s not what I’m here to show you.

How can you publish symbols for the packages you’ve posted to your own NuGet server, without putting them on SymbolSource.org’s public feed? With Azure, of course!

Turns out, SymbolSource released their technology as open source, and even as a NuGet-Server-like NuGet package. So, much like you create a NuGet server of your own by simply creating a website and adding a NuGet package to it, you can create your own Symbol server in the same manner. The only difference, here, is that SymbolSource depends on the Windows SDK’s ability to parse PDBs in order to do its job. What this means, then, is that you can’t simply create an Azure website and publish the site created with the SymbolSource NuGet package to it because you need this external dependency. What we do, then, is use an Azure VM to run the server.

This is where Azure, once again, flexes its awesomeness. When you create a website in Visual Studio, the Publish dialog gives you the option not only to publish to a New Azure Website, but if you expand out the other options, there’s the possibility to publish to a New Azure VM! Yeah, for real. It will create a VM for you and then push the site to it!

But first thing’s first, let’s get this site created.

Fire up Visual Studio, create a new MVC web application:

image

Set up the web application project as shown:

image

Notice that super-awesome part in the bottom right. Yup, set this bad boy up for hosting in the cloud on an Azure VM straight away – then the scripts that run to make that business happen can be doing their job while we set up the project and get it ready to be published.

The next prompt will be the specifics of the VM to create. I’ve highlighted the two important parts of this dialog:

image

At first I thought I would set up the Visual Studio variant of the VM, but that ended up being a wash. Instead, just choose one of the plain Windows OS VMs. 2012 R2 works just fine. As you can see, I even put this thing on quite a small VM. Works just fine. Since we’ll be publishing via Web Deploy, make sure this is enabled.

Once you click ‘OK’ the solution & project will be created, but a cool little VS window will show up:

image

Yup, so while we’re doing the rest of the blog post, Microsoft’s VS and Azure magic is hard at work for us :)

The next step, much like with our private NuGet server, is to add the necessary NuGet package to the web site project:

image

image

image

Clicking ‘Install’ here will result in an absolute crapload of NuGet packages being pulled and references being added to your Website. Prepare to wait :)

If prompted to overwrite current files, click ‘Yes’ or ‘Yes to All’

Once that’s all done, build the Solution (sanity check)

At this point, I checked on my Azure Provisioning and it wasn’t yet done. So… go do some other cool stuff and come back later… It is worth mentioning that on more than one occasion, the automatic Azure VM setup didn’t complete successfully. In this instance I had to delete the VM and all related services in Azure and start over. It looked to be something related to timing out. Like the VM didn’t boot/provision in time for the rest of the script to execute. So if that happens, that’s all you have to do (try again).

If do end up needing to re-create the VM from within VS, you do it like this:

Right click the project & choose Publish…
image

image

image

Fill out the subsequent dialog as shown earlier in this post.

Eventually you’ll see this lovely message:

image

And now you’re cookin’ with gas.

Right click the WebApplication project and choose Publish…

You should be able to just click the Publish button, nothing really needs changed.

If you’re lucky, you’ll get this beautiful note:

image

Your site will then automatically be launched in the browser. And you’ll likely get this:

image

Well shit. Setting up CustomErrors Off led me to find out that the template HomeController.cs that got put in my Project didn’t need to be there after I put all the SymbolSource stuff in, so I just deleted it and problem solved! You know the site’s running when you get something that resembles this:

image

Note these specifications. But before we move on, let’s utilize that ‘Run Diagnostics’ page:

image

Ah yes, remember the Win SDK’s PDB parsing that SymbolSource utilizes? We haven’t added that to our VM yet. Fortunately, doing this is straightforward.

Remote in to your new Azure VM

Once in, head to http://msdn.microsoft.com/en-US/windows/desktop/aa904949.aspx – the Windows SDK download page. On this page, download the (at the time of this writing) Windows 8.1 SDK.

Run this on the server, electing to install the SDK. Make note of the installation path to save yourself some guessing later. On the features page, choose only ‘Debugging Tools for Windows’ as this contains the PDB parser we’re after:

image

Once this completes, head back to Visual Studio where you have the source for your SymbolSource website.

Crack open the web.config, and fix up the value shown here:

        <add key="SrcSrvPath" value="C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\srcsrv" />

In the case of a default installation location on the server of the SDK linked to in this post, this will end up being

        <add key="SrcSrvPath" value="C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x64\srcsrv" />

Publish, and re-run the diagnostics page to see what we get:

image

One last thing to solve, that “InternalServerError” in the 3rd item.

After some web searches I found that we have to enable x86 processed on our x64 site’s application pool in order for the PDB parser to execute successfully. Best/easiest way to do this is to create a new App Pool for our site, set it up properly, then have the site use it.

image

image

image

Once all this is done, try submission again and you should notice it takes quite a bit longer than it was in the previous attempts. Obviously the site is re-spinning up, but it’s not able to execute the PDB parsing and do its real work.

You’ll still be met with some errors. Turns out we have to add some OS-level permissions to even more folders before this all works, because it takes the symbol package and blows it out in to some additional folders when it’s pushed to the server. By the time it’s said and done, you need to have set permissions to ‘Modify’ for the ‘IIS_IUSRS’ server group on these folders:

  • Data
  • Index

Fire off a push now and you’ll happily see

image

BOO-YAH!

When you want to push to the symbol servers you need to use the command shown here. When you want to use the Symbol Server in Visual Studio, you need to use the debugging URL shown here in your Visual Studio’s Source Symbol Server setup like so:

image

Now, test this bad boy out by:

  1. Upload a NuGet package to your own symbol server (as outlined in my previous post)
  2. Push its corresponding Symbols package (created by packaging with symbols via ‘-symbols’ switch) using the push command shown on your new symbol server’s page
  3. Create a new project to use the NuGet package published in #1
  4. Add NuGet package to project
  5. Run Project
  6. F11 in to code that utilizes the NuGet project
  7. Watch the magic. You should step in to source, but see that the “file” is coming from a super wacky temp location.

That’s it, you’re all set! Since you’re using this for your own NuGet packages, I can’t really see a reason *not* to publish symbol packages with your binary ones. Enjoy!

  • Francois

    Very nice post Brandon, thanks.
    I’m going to try this, but I’m a little baffled as to how the authentication works to access your symserver feed? How is the public prevented to get access to your symbol packages?

    Thanks

    • Mostly it’s security by obfuscation (eg: nobody knows the URL so they don’t know it’s there)
      But if you upload your symbols to a public symbol server, you WANT devs to get the symbols. If they’re consuming your nuget pkg, the reason you’re providing symbols is so they can debug in or at least get meaningful stack traces. In either case, it’s actually desired for the symbols to be publicly available.