How to debug into my nuget package deployed from TeamCity?
Asked Answered
A

10

71

I have put a library that my team uses into a nuget package that is deployed from TeamCity into a network folder. I cannot debug into this code though! SymbolSource is one solution I have read about but I would much rather find some way to have access to the .pdb/source files directly from TeamCity. Does anyone know how to do this?

Edit. When I check 'Include Symbols and Source' in the Nuget Pack build step, TeamCity creates a .Symbol.nupkg in addition to the .nupkg file in the network folder. The .Symbol.nupkg contains the src and the .pdb file.

Edit. I unchecked 'Include Symbols and Source' on TeamCity and added the following to my nuspec file:

  <files>
    <file src="..\MyLibrary\bin\release\MyLibrary.dll" target="lib\net40" />
    <file src="..\MyLibrary\bin\release\MyLibrary.pdb" target="lib\net40" />
    <file src="..\MyLibrary\*.cs" target="src" />
    <file src="..\MyLibrary\**\*.cs" target="src" />
  </files>

This added the dll, the pdb, and the source files for my library in the nuget package and didn't generate a .Symbols file which I think is only needed for symbol servers.

Aquarelle answered 18/2, 2014 at 15:10 Comment(0)
T
73

Traditional method

  1. Put the pdb in the NuGet package alongside the dll.
  2. Add the source code to the Debug Source Files for the solution that references the package.

This means you'll be able to step through code and view exceptions, but you might have to find a file on disk and open it before you can set a breakpoint. Obviously you need to be careful that the source is at the right revision.

More detail on step

If you're currently packaging without a Nuspec, you'll need to create a Nuspec, then add the pdb to the list of files in the lib folder "NuGet spec" may be a useful command for generating the initial spec as defined in NuGet docs. Then ensure the Team City Nuget Pack step is referencing your new nuspec.

More detail on step 2

When you have a solution open, right click on Solution, select Properties...Common Properties...Debug Source Files, and add the root source directory for the relevant binary reference. Or see MSDN. Note, you can't open the solution properties while debugging.

Still not hitting breakpoints?

Try disabling this from Tools->Options: Disable exact source match


Modern way for public or private repos

To ensure the exact version of the source is available, embed it at build time.

From Visual Studio 2017 15.5+ you can add the EmbedAllSources property:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <EmbedAllSources>true</EmbedAllSources>

Modern way for public repos

To keep your nuget and library size small, you can use the sourcelink package.

It generates a pdb that directs the debugger to the correct version of the file from your VCS provider (e.g. GitHub, BitBucket).

Tale answered 21/2, 2014 at 0:5 Comment(3)
Not sure if it is a bug but anyone trying this in VS2015 clicking "Debug Source Files" doesn't show the correct window, it seems to show the configuration manager.Zymolysis
@Choco Smith I have the same problem. Right click on solution file and Common Properties->Debug Source Files show Configuration Manager Window in VS 2015. Do you know how show Debug Source Files window in VS2015?Imminence
Has always worked fine for me in VS2015. I used this today on VS Enterprise 2015, version 14.0.24720.00. If it's not just a rogue extension messing up your menus, perhaps create a Microsoft Connect issue? connect.microsoft.com/VisualStudio/MSNetNativeTale
A
31

The latest version of dotPeek (free!) can act as a symbol server and generate pdb files on the fly. This has allowed me to debug into the dlls that are served via teamcity.

Download it here:

http://blog.jetbrains.com/dotnet/2014/04/09/introducing-dotpeek-1-2-early-access-program/

Instructions on how to set it up here.

https://web.archive.org/web/20160220163146/http://confluence.jetbrains.com/display/NETCOM/dotPeek+Symbol+Server+and+PDB+Generation

Aquarelle answered 27/5, 2014 at 16:10 Comment(2)
I wish i could up vote you again.. I got here earlier in the year and forgot about this, now I need to do the same and. viola.. your answer rocks!Alcoran
You used an archive link. Fantastic answer.Bultman
P
8

You could of course set-up & configure your own symbol server, but it's probably easiest to...

  1. download and install Inedo's ProGet
  2. enable symbol serving on the target feed
  3. publish packages from TeamCity to the ProGet feed
  4. use ProGet as your primary feed source (as it can aggregate multiple feeds including nuget.org)

All of this can be done with the free edition of ProGet.


disclaimer -- my day job is at Inedo

Polypary answered 18/2, 2014 at 17:27 Comment(6)
Why do I need a 'symbol server' If I already have the .Symbol.nupkg file? Can't Visual Studio just read this file directly?Aquarelle
@Aquarelle oh most definitely not! A ".symbol.nupkg" file is nothing more than a zip file. Visual Studio needs to first find a remote .pdb file (by assembly hash), and that file will then point to a hashed source file url. A symbol server like ProGet will reindex the pdb file and serve files based on that. See inedo.com/support/kb/1036/using-progets-symbol-serverPolypary
@Aquarelle according to MS documenation this should be possible but so far VS fails to load symbol packages from either network shares or local folders.Ridden
I had to modify the "Symbol Server" settings for my feed and disable the setting "Strip symbol files from packages downloaded from this feed". But uninstalling and then re-installing the package still didn't include the *.pdb file in the package.Purple
Restarting ProGet didn't help either, but I'm running an old version of Visual Studio (2012) and ProGet (3.8.6).Purple
In the end, I had to download the 'with symbols' NuGet package file from ProGet and then install it in my other project from the NuGet Package Manager Console with the download directory as the Source argument value.Purple
P
6

In your .nuspec (directly under <package>):

<files>
  <file src="bin\$configuration$\$id$.pdb" target="lib\net451\" />
</files>

(change net451 to the platform you're compiling for)

Peneus answered 22/1, 2016 at 15:6 Comment(0)
B
3

If you have the source code for the package, then the foolproof (but possibly laborious) method is:

  1. Add the source code for the package to your solution (right click Solution -> Add Existing Project)
  2. Go through all of your projects in the solution and remove the NuGet reference to the library (i.e. open the References folder under each project and delete the reference to the package.) Then, add a reference to the NuGet package project in your solution. (i.e. Right click References, add Reference, choose Projects and tick the box for the project)

I had to do it this way when I the method I wanted to debug inside the NuGet package was called by the framework and not by my code, thus I couldn't step into it. (In my case, the method was an ASP.NET DelegatingHandler).

Once you're done you'll want to undo all your changes via source control so that the NuGet package is referenced correctly.

Bonus answered 18/2, 2016 at 15:50 Comment(9)
the above options regarding symbol servers are better. This method is error prone and time consuming to do every time. Setting up a symbol server is a one time setupNucleotide
@Nucleotide Is it possible to set a breakpoint inside the source code of the NuGet package if you're using a symbol server? Or are you only able to set a breakpoint in your own code and then step into the NuGet package's source code?Bonus
You can do both, however, I actually found that you don't even need to run a symbol server (but in this case you can only debug one at a time). See my answer for more details. https://mcmap.net/q/174853/-how-to-debug-into-my-nuget-package-deployed-from-teamcityNucleotide
Thanks for that. Although my downvoted answer is laborious, I stand by it as it allows me to debug both my code and the NuGet package without a source serverBonus
I wouldn't like anyone in my team to do it because it is error prone and time consuming. Down voting because I think that it is not the right way to approach it. I'm sure if enough people agree with you that it is a sensible way to do it then they will up vote it and I will be thoroughly corrected.Nucleotide
If you have the source code, you can also do like this: In the project properties of the project where a nuget package is used add the bin\debug folder of the private nuget package source code to the reference path. (see mariuszrokita.com/…)Sassaby
I have a symbol server and PDB debug packages but I can't seem to find a way to place a breakpoint in the PDB code. I can't trace into the code since it is injected and it runs in a separate thread (WinForms UI). No matter what I have tried none of this works. This is the only option I have left.Detestation
@Sassaby Link is dead, use web.archive.org/web/20161207151745/http://www.mariuszrokita.com/…Charlyncharm
Upvoting because it doesn't require buying/installing some random product or server, or changing the nuspec, which you might not always want for a quick look at something. Just use source control properly to undo your changes. git co .. DoneCoincidence
B
3

I've found a super simple way to do this, which I have blogged about here:

https://mattfrear.com/2017/11/29/speed-up-development-in-a-nuget-package-centric-solution/

This only works if you're using the new .NET Core style .csproj with <PackageReference> (on either .NET Core or .NET Framework).

This again assumes you have access to the source code of the NuGet package.

  1. Build and compile the NuGet package on your local machine
  2. Copy the .dll you've just compiled into your local NuGet packages feed folder (On my machine, this is C:\Users\matt\.nuget\packages\), overwriting the existing NuGet package .dll.

That's it! You should be able to step into the package while debugging. No messing around with .pdbs or source servers. This has greatly sped up my development cycle.

Bonus answered 5/12, 2017 at 12:56 Comment(3)
This only works with the new project file format / ProjectReferencesHers
Your example location is the default global‑packages location on Windows (%userprofile%\.nuget\packages). The path from there to the dll in NuGet 3.3+ is packagename\version\lib\. Is that where you are copying it? Are you manually copying or using nuget add?Snuck
@Snuck yes, you should see the existing dll, either copy over that or I rename the original one in case you want to restore it.Bonus
H
2

Since this question was originally posted, Jetbrains have written an entire blog post on how to accomplish this. The steps can be summarised as:

  • Install Debugging Tools for Windows on the agents.
  • Install & Enable the Symbol Server plugin.
  • Add Symbol Files Indexer build feature to your build configurations.
  • Ensure PDB files are output as an artefact.
  • Configure Visual Studio to use TeamCity as source server.

If you are using Nuget Package build steps, you can check 'Include Symbols and Source' to output a .symbol.nupkg which contains the PDBs. Depending on whether the Symbol Files Indexer is smart enough to look inside this file or not, you may need to change the file extension for things to work.

The full details are given here: https://blog.jetbrains.com/teamcity/2015/02/setting-up-teamcity-as-symbol-and-source-server/

Hulk answered 11/11, 2015 at 20:15 Comment(0)
N
2

This is what I have found to work, but all the steps are probably not required...

Note: this doesn't allow you to debug both, only either the nuget package or the solution in which it is installed.

  1. Run Visual Studio as Administrator
  2. Open and Start the host application (the one in which you installed the Nuget package) without debugging (Ctrl + F5)
  3. In the Nuget package solution, ensure that Tools > Options > Debugging > General > "Require source files to exactly match the original version" is NOT checked.
  4. Ensure that "Enable just my code" is NOT checked
  5. Add a new folder in Tools > Options > Debugging > Symbols pointing to the source directory of the Nuget package. (You literally enter the folder path , see image below)
  6. Click Debug > Attach to Process...
  7. Find iisexpress (there may be multiple, it won't do any harm attaching to all)

Screenshot of Symbol Source Locations

Nucleotide answered 25/7, 2016 at 22:29 Comment(1)
@CristianE. The nuget package can be a class library. The instructions above are for exactly that. It would still need to be executed in a host application like a website or console app in which you install the nuget package.Nucleotide
B
0

If your code is in a public Git repository, or, at least in your network, is accessible without authentication, then GitLink would be an option:

https://github.com/GitTools/GitLink

GitLink makes symbol servers obsolete by changing the PDB to point to the Git server. But, as said before, this makes it necessary for the Git repository to be public - until now there's no "proper" way to authenticate when accessing a private repository.

Brookins answered 22/3, 2017 at 15:31 Comment(0)
T
0

Microsoft has now integrated the SourceLink NuGet package at https://github.com/dotnet/sourcelink/ which allows source code to be downloaded on demand while debugging if the publisher of the NuGet package sets it up.

Thermosphere answered 25/10, 2019 at 20:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.