72

I am using MSBuild to generate my nuget packages.

Is there any command I need to set, to allow it to include my .pdb files, for stepping into the source while debugging?

I do not want the source files to be included into the project that is pulling in the nuget package.

monstertjie_za
  • 7,277
  • 8
  • 42
  • 73

8 Answers8

62

NET 7

Copying the symbol files is now incorporated in the NET 7.0 SDK/VS2022 17.4+ as an opt-in approach. Add the following fragment to your project file...

<PropertyGroup>
  ...
  <CopyDebugSymbolFilesFromPackages>true</CopyDebugSymbolFilesFromPackages>
  <CopyDocumentationFilesFromPackages>true</CopyDocumentationFilesFromPackages>
</PropertyGroup>

This will copy all symbols and documentation files into your output directory; if you only want a subset, e.g. your files, you will have to implement a filtering mechanism on top of this

Earlier

If you are using VS2017 15.4 or later, you can define a MSBuild property in your project file

<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>

This is discussed in NuGet #4142

However, there is still an issue as the new project system does not copy the pdbs from packages to the bin/publish folder for .NET Core 3.0+, a good summary is also at sourcelink/#628

As the fix is only supported in the .NET 7 SDK+, you will need a work-around which is to include the following fragment into API and test projects to ensure you have the appropriate pdbs to allow you to step into the remote source code.

<!-- https://github.com/dotnet/sdk/issues/1458#issuecomment-1063915490 -->
<Target Name="IncludeSymbolFiles" AfterTargets="ResolveAssemblyReferences" Condition="@(ReferenceCopyLocalPaths) != ''">
  <ItemGroup>
    <ReferenceCopyLocalPaths Include="%(ReferenceCopyLocalPaths.RelativeDir)%(ReferenceCopyLocalPaths.Filename).pdb;                                %(ReferenceCopyLocalPaths.RelativeDir)%(ReferenceCopyLocalPaths.Filename).xml" />
    <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" Condition="!Exists('%(FullPath)')" />
  </ItemGroup>
</Target>
Paul Hatcher
  • 7,342
  • 1
  • 54
  • 51
  • Useful for when I need to do this again, while using Visual Studio 2017. Thanks for your input – monstertjie_za Jan 23 '18 at 04:05
  • I'm just updating a bunch of my open source projects to VS2017 so I needed it as well :-) – Paul Hatcher Jan 23 '18 at 08:45
  • What element does this go under? Project, PropertyGroup, or something else? Intellisense isn't picking it up anywhere. – LarryBud Apr 16 '18 at 16:59
  • 2
    I've got in my main PropertyGroup - have a look at https://github.com/phatcher/CsvReader for a full example – Paul Hatcher Apr 16 '18 at 17:15
  • 2
    For the life of me I cannot get this to work. I'm using VS 2017 15.5.6. no nuspec file and the following post build event `nuget pack $(ProjectPath) -Prop Configuration=$(ConfigurationName)` – Craig May 18 '18 at 00:52
  • 1
    @kraeg this is for use with the new Pack MSBuild target; I'm not 100% certain how the various tools use each other in this process, but it might be that you're required to use "msbuild /t:Pack" or right click the project and choose "Create NuGet Package" - the old style post-build events should not be required any longer. – TheXenocide Aug 01 '18 at 17:52
  • Packaging works this way (my package has the pdb files included now), but how do I use this? When I consume the package, only the DLL file is copied to the target applications bin folder, and if I want to debug into the library, I have to locate the matching pdb under users\username\.nuget\packages... which is not very comfortable. – PMF Nov 20 '19 at 15:17
  • @PMF If this is working correctly your nuget package should contain the pdb file as well as the dll. The other thing to do is to use SourceLink (https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/sourcelink) to ensure the build process references the repository code files. You will also have to disable the "Just my code" option in VS – Paul Hatcher Nov 21 '19 at 17:02
  • @PaulHatcher Yea, the package contains both PDB and DLL, but the PDB is not copied to the application folder of the consuming application automatically. If I really want to debug into the code, I need to manually locate the PDB for the DLL. I think I can't use SourceLink, as these are private repositories (and a private nuget server as well). – PMF Nov 21 '19 at 18:43
  • @PMF That's odd, could be version of VS? BTW There are different SourceLink libraries for Git, BitBucket, Azure DevOps plus others; check on NuGet – Paul Hatcher Nov 21 '19 at 22:28
  • @PaulHatcher I'm still using VS2017 (soon to be upgraded, but not towards the end of a project...) I have found a workaround using a targets file for now, but will retest with 2019 later. – PMF Nov 22 '19 at 07:43
  • @PMF I think it's only supported from 15.3+, so check you are on at least that – Paul Hatcher Nov 22 '19 at 08:49
  • Yea, it's 15.9.15, so almost the latest version for VS2017. – PMF Nov 22 '19 at 09:08
  • I ran into this too, with .NET Core 3. Appears that .NET Core 3 has a bug where PDBs in NuGet packages aren't copied to the bin/publish folder: https://github.com/dotnet/core/issues/3587 – IGx89 Dec 31 '19 at 18:52
  • 1
    @IGx89 https://github.com/dotnet/sdk/issues/1458#issuecomment-695119194 – Ian Kemp Oct 22 '20 at 11:24
  • Running VS2019 with ASP.NET Core 3.2 does not have this property – JWP Apr 23 '21 at 20:48
42

While it may not help for debugging, it's definitely useful to include .pdb files so that stack traces have line numbers.

In the nuspec file, include a <files> element (child of <package>, sibling of <metadata>). This is what I have in one of my class libraries:

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

Make sure the target is the same folder as where your .dll file is put in the package.

Jeff Shepler
  • 2,007
  • 2
  • 22
  • 22
  • 2
    Make sure you add a `file` element for your *\*.dll* files, if you also wish to include them in the NuGet package. – Kenny Evitt Dec 13 '18 at 15:23
  • 1
    In my experience, the .dll files are already included - no need to add file elements for them. If you have extra .dll files that are not dependencies, then you might need to add file elements for those. – Jeff Shepler Dec 13 '18 at 17:26
  • It's possible that the *\*.dll* files were excluded because of the old version of Visual Studio I'm using – Visual Studio 2012. But they were excluded nonetheless, until I added a `file` element to explicitly include them. – Kenny Evitt Dec 13 '18 at 17:32
  • 1
    @KennyEvitt, i advise you to don't use *.dll in your nuspec. When you have more output than just your own dll, you'll also embed all that other stuf in your package like log4net or entityframework. – SvenL Jul 10 '19 at 09:34
  • @SvenL Thanks. I don't have ready access to the relevant project anymore but I'm pretty sure I was only explicitly including my project's DLL files and, as I mentioned, I was using an old version of Visual Studio so my experience may not have matched others. – Kenny Evitt Jul 10 '19 at 14:39
31

With the .csproj format of .NET Core NuGet creation is much easier, since MSBuild does most of the work.

In order to include your pdb files you just have to enter the tag <IncludeSymbols>true</IncludeSymbols> in a PropertyGroup in your project's .csproj file.

This will create an additional .symbols.nupkg package, which you can release to your [debug] feed.

Old .NET framework files can be easily mapped to the new csproj with open source libs, like hvanbakel's repo

Josef Ginerman
  • 1,460
  • 13
  • 24
  • 3
    This is certainly an easy solution for debugging locally. I'd suggest anyone using the old .csproj format upgrade it to use the new format. – Neo May 06 '19 at 16:52
  • 4
    The best answer ever. – Xtro Apr 19 '20 at 05:06
  • 1
    Where did you get this information? I was unable to find it in the docs. Maybe i looked the wrong place. But a link would be appreciated, so i can read more about it. – Morten Toudahl Jan 06 '21 at 00:34
  • I sincerely don't remember. I think there was an issue in the NuGet dev team Github where this was mentioned. Mostly found how it works via trial & errors. – Josef Ginerman Jan 06 '21 at 12:00
  • 1
    This should be marked as the right answer. It works on Visual Studio 2019. – Aquiles Oct 28 '21 at 14:59
9

This can also be accomplished with the dotnet CLI.

By packaging with

dotnet pack --include-symbols --include-source [path-to-project-here]

I get full debugging on the packages I generated

farlee2121
  • 2,959
  • 4
  • 29
  • 41
4

The approach that worked for me was adding the PDB as content which had the benefit it will be copied alongside the DLL. (PackageCopyToOutput was required)

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
    <EmbedAllSources>true</EmbedAllSources>
  </PropertyGroup>

  <ItemGroup>
    <Content Include="bin\$(Configuration)\$(AssemblyName).pdb" PackagePath="contentFiles\any\netstandard2.0\$(AssemblyName).pdb">
       <PackageCopyToOutput>true</PackageCopyToOutput>
    </Content>
  </ItemGroup>
</Project>

EmbedAllSources - Will include source code in the PDB for easier debugging.

You may also want to consider setting "Optimize" to false for improving debugging experience in release configuration.

Tal Aloni
  • 1,429
  • 14
  • 14
2

Refer to this link. Actually you should add -Symbols to the end of command to create a symbols package. You shouldn't add pdb files to main nuget package.

Milad
  • 539
  • 8
  • 21
  • 46
    While this is factual and accurate and better, and is indeed the route I took (at first)... I have gone through so many hours of issues with symbol servers, From the microsoft starter package being deprecated, to the github SymbolServer providing only compressed versions of pdb response files, to visual studio not properly picking the right symbol server in the list of servers, that I'm straight up DONE with symbol servers. Simply including my .pdb in the nuget right next to the dll, like many other package providers do, works perfectly every time with zero fuss. – Barry May 10 '18 at 17:49
  • 3
    "You shouldn't add pdb files to main nuget package." - Why? – Neil Barnwell Mar 27 '20 at 16:15
  • Currently I don't remember the reason now, but it seems the nuget itself does the necessary things to add corresponding files, explicitly telling nuget to add a pdb file won't generate the desired result. @NeilBarnwell – Milad Mar 31 '20 at 17:41
1

The newer approach would be to use the following .csproj properties:

<DebugType>embedded</DebugType>
<EmbedAllSources>true</EmbedAllSources>

EmbedAllSources - Will include source code in the PDB for easier debugging.

Setting DebugType to embedded will cause the PDB to be embedded in the .DLL.

So using the two options together the source code will be embedded in the DLL.

Tal Aloni
  • 1,429
  • 14
  • 14
1

In 2023, the right way to do this is using SymbolLink.

Include the following NuGet package and it will set all the necessary properties. https://github.com/dotnet/reproducible-builds

I have used it in my DLL and people are able to debug it. https://github.com/xavierjohn/FunctionalDDD

Xavier John
  • 8,474
  • 3
  • 37
  • 51