├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── dependabot.yml ├── stale.yml └── workflows │ ├── merge-dependabot.yml │ └── on-push-do-docs.yml ├── .gitignore ├── License.txt ├── code_of_conduct.md ├── readme.md └── src ├── .config └── dotnet-tools.json ├── .editorconfig ├── AssemblyWithEmbeddedSymbols ├── AssemblyWithEmbeddedSymbols.csproj ├── AssemblyWithEmbeddedSymbolsClass.cs └── Class1.cs ├── AssemblyWithNoSymbols ├── AssemblyWithNoSymbols.csproj └── AssemblyWithNoSymbolsClass.cs ├── AssemblyWithPdb ├── AssemblyWithPdb.csproj └── AssemblyWithPdbClass.cs ├── Cymbal.sln ├── Cymbal.sln.DotSettings ├── Cymbal ├── Cymbal.csproj ├── CymbalTask.cs ├── Dotnet.cs ├── Error.cs ├── Extensions.cs ├── SymbolChecker.cs ├── SymbolDownloader.cs └── build │ └── Cymbal.targets ├── Directory.Build.props ├── Directory.Packages.props ├── SampleApp ├── Program.cs ├── SampleApp.csproj └── msbuild.binlog ├── SampleWithSymbolServer ├── Program.cs └── SampleWithSymbolServer.csproj ├── Shared.sln.DotSettings ├── Tests ├── ModuleInitializer.cs ├── Tests.RunTask_environmentCache=False_propertyCache=False.DotNet.verified.txt ├── Tests.RunTask_environmentCache=False_propertyCache=True.DotNet.verified.txt ├── Tests.RunTask_environmentCache=True_propertyCache=False.DotNet.verified.txt ├── Tests.RunTask_environmentCache=True_propertyCache=True.DotNet.verified.txt ├── Tests.Should_Parse_SymbolServer.verified.txt ├── Tests.cs └── Tests.csproj ├── appveyor.yml ├── global.json ├── icon.png ├── key.snk ├── mdsnippets.json └── nuget.config /.gitattributes: -------------------------------------------------------------------------------- 1 | * text 2 | *.snk binary 3 | *.png binary 4 | *.bmp binary 5 | *.tif binary 6 | 7 | src/Verify/EmptyFiles/* binary 8 | 9 | *.verified.txt text eol=lf working-tree-encoding=UTF-8 10 | *.verified.xml text eol=lf working-tree-encoding=UTF-8 11 | *.verified.json text eol=lf working-tree-encoding=UTF-8 12 | 13 | .editorconfig text eol=lf working-tree-encoding=UTF-8 14 | Shared.sln.DotSettings text eol=lf working-tree-encoding=UTF-8 -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: SimonCropp -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug fix 3 | about: Create a bug fix to help us improve 4 | --- 5 | 6 | Note: New issues raised, where it is clear the submitter has not read the issue template, are likely to be closed with "please read the issue template". Please don't take offense at this. It is simply a time management decision. If someone raises an issue, and can't be bothered to spend the time to read the issue template, then the project maintainers should not be expected to spend the time to read the submitted issue. Often too much time is spent going back and forth in issue comments asking for information that is outlined in the issue template. 7 | 8 | 9 | #### Preamble 10 | 11 | General questions may be better placed [StackOveflow](https://stackoverflow.com/). 12 | 13 | Where relevant, ensure you are using the current stable versions on your development stack. For example: 14 | 15 | * Visual Studio 16 | * [.NET SDK or .NET Core SDK](https://www.microsoft.com/net/download) 17 | * Any related NuGet packages 18 | 19 | Any code or stack traces must be properly formatted with [GitHub markdown](https://guides.github.com/features/mastering-markdown/). 20 | 21 | 22 | #### Describe the bug 23 | 24 | A clear and concise description of what the bug is. Include any relevant version information. 25 | 26 | A clear and concise description of what you expected to happen. 27 | 28 | Add any other context about the problem here. 29 | 30 | 31 | #### Minimal Repro 32 | 33 | Ensure you have replicated the bug in a minimal solution with the fewest moving parts. Often this will help point to the true cause of the problem. Upload this repro as part of the issue, preferably a public GitHub repository or a downloadable zip. The repro will allow the maintainers of this project to smoke test the any fix. 34 | 35 | #### Submit a PR that fixes the bug 36 | 37 | Submit a [Pull Request (PR)](https://help.github.com/articles/about-pull-requests/) that fixes the bug. Include in this PR a test that verifies the fix. If you were not able to fix the bug, a PR that illustrates your partial progress will suffice. 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: How to raise feature requests 4 | --- 5 | 6 | 7 | Note: New issues raised, where it is clear the submitter has not read the issue template, are likely to be closed with "please read the issue template". Please don't take offense at this. It is simply a time management decision. If someone raises an issue, and can't be bothered to spend the time to read the issue template, then the project maintainers should not be expected to spend the time to read the submitted issue. Often too much time is spent going back and forth in issue comments asking for information that is outlined in the issue template. 8 | 9 | If you are certain the feature will be accepted, it is better to raise a [Pull Request (PR)](https://help.github.com/articles/about-pull-requests/). 10 | 11 | If you are uncertain if the feature will be accepted, outline the proposal below to confirm it is viable, prior to raising a PR that implements the feature. 12 | 13 | Note that even if the feature is a good idea and viable, it may not be accepted since the ongoing effort in maintaining the feature may outweigh the benefit it delivers. 14 | 15 | 16 | #### Is the feature request related to a problem 17 | 18 | A clear and concise description of what the problem is. 19 | 20 | 21 | #### Describe the solution 22 | 23 | A clear and concise proposal of how you intend to implement the feature. 24 | 25 | 26 | #### Describe alternatives considered 27 | 28 | A clear and concise description of any alternative solutions or features you've considered. 29 | 30 | 31 | #### Additional context 32 | 33 | Add any other context about the feature request here. 34 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: nuget 4 | directory: "/src" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 7 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Set to true to ignore issues in a milestone (defaults to false) 6 | exemptMilestones: true 7 | # Comment to post when marking an issue as stale. Set to `false` to disable 8 | markComment: > 9 | This issue has been automatically marked as stale because it has not had 10 | recent activity. It will be closed if no further activity occurs. Thank you 11 | for your contributions. 12 | # Comment to post when closing a stale issue. Set to `false` to disable 13 | closeComment: false 14 | # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': 15 | pulls: 16 | daysUntilStale: 30 17 | exemptLabels: 18 | - Question 19 | - Bug 20 | - Feature 21 | - Improvement -------------------------------------------------------------------------------- /.github/workflows/merge-dependabot.yml: -------------------------------------------------------------------------------- 1 | name: merge-dependabot 2 | on: 3 | pull_request: 4 | jobs: 5 | automerge: 6 | runs-on: ubuntu-latest 7 | if: github.actor == 'dependabot[bot]' 8 | steps: 9 | - name: Dependabot Auto Merge 10 | uses: ahmadnassri/action-dependabot-auto-merge@v2.6.6 11 | with: 12 | target: minor 13 | github-token: ${{ secrets.dependabot }} 14 | command: squash and merge -------------------------------------------------------------------------------- /.github/workflows/on-push-do-docs.yml: -------------------------------------------------------------------------------- 1 | name: on-push-do-docs 2 | on: 3 | push: 4 | jobs: 5 | docs: 6 | runs-on: windows-latest 7 | steps: 8 | - uses: actions/checkout@v4 9 | - name: Run MarkdownSnippets 10 | run: | 11 | dotnet tool install --global MarkdownSnippets.Tool 12 | mdsnippets ${GITHUB_WORKSPACE} 13 | shell: bash 14 | - name: Push changes 15 | run: | 16 | git config --local user.email "action@github.com" 17 | git config --local user.name "GitHub Action" 18 | git commit -m "Docs changes" -a || echo "nothing to commit" 19 | remote="https://${GITHUB_ACTOR}:${{secrets.GITHUB_TOKEN}}@github.com/${GITHUB_REPOSITORY}.git" 20 | branch="${GITHUB_REF:11}" 21 | git push "${remote}" ${branch} || echo "nothing to push" 22 | shell: bash -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.user 3 | bin/ 4 | obj/ 5 | .vs/ 6 | *.DotSettings.user 7 | .idea/ 8 | *.received.* 9 | nugets/ 10 | src/Verify.Tests/Tests.StreamNegative.verified.bin 11 | src/Verify.Tests/Tests.StreamMultipleNegative.00.verified.bin 12 | src/Verify.Tests/Tests.StreamMultipleNegative.01.verified.bin 13 | src/Verify.Tests/Tests.TextNegative.verified.tmp 14 | src/Cache/ 15 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) .NET Foundation and Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /code_of_conduct.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This project has adopted the code of conduct defined by the Contributor Covenant 4 | to clarify expected behavior in our community. 5 | For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/about/code-of-conduct). 6 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Cymbal 2 | 3 | [![Build status](https://ci.appveyor.com/api/projects/status/gd7jvcs0nv8pawc8/branch/main?svg=true)](https://ci.appveyor.com/project/SimonCropp/cymbal) 4 | [![NuGet Status](https://img.shields.io/nuget/v/Cymbal.svg)](https://www.nuget.org/packages/Cymbal/) 5 | 6 | Cymbal is an MSBuild task that enables bundling dotnet symbols for references with a deployed app. The goal being to enable line numbers for exceptions in a production system. 7 | 8 | **See [Milestones](../../milestones?state=closed) for release notes.** 9 | 10 | 11 | ## How symbols work in .net 12 | 13 | When an exception occurs, the runtime uses the symbols to correlate the each code point in the stack trace with a line number and file path that the code was built from. Without symbols no line numbers or file paths exist in the stack trace. This make working out what was the cause of the exception 14 | 15 | There are three approaches to managing symbols in .net: 16 | 17 | 18 | ### 1. [Embedded inside the assembly](https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview?tabs=cli#include-pdb-files-inside-the-bundle). 19 | 20 | This works in the same way development time and in the deployed app. With the side effect of an assemblies size increases by 20-30%. It does not effect startup time of apps as the symbols are only loaded interrogated when an exception occurs. 21 | 22 | 23 | ### 2. Shipping a pdb file 24 | 25 | This works by having a pdb named the same as an assembly and co-located in the same directory. When an exception occurs the runtime will use that convention to look for the symbols. 26 | 27 | There are some known problems with this approach: [1458](https://github.com/dotnet/sdk/issues/1458) and [38322](https://github.com/dotnet/sdk/issues/38322). 28 | 29 | 30 | ### 3. [Shipping a symbols nuget package](https://learn.microsoft.com/en-us/nuget/create-packages/symbol-packages-snupkg) 31 | 32 | This is a specialized nuget package that is shipped to a symbol server. When an exception occurs, the symbols package can download to augment the stack trace. At development time this is handled by the IDE and debugger. In a deployed app this is problematic since the app would need to download the symbols package. Instead the debug experience is usually done by a developer getting the stack trace (with no symbol information) and then, using the known assembly versions of the deployed app, augment the stack trace. 33 | 34 | 35 | ## Cymbal performs two operations 36 | 37 | Cymbal targets last two scenarios (pdb files, and symbol packages) to ensure that symbol information is available to a deployed app. 38 | 39 | 40 | ### 1. Copies symbols from references 41 | 42 | Works around the following bugs that cause pdb not to be copied to the output directory: 43 | 44 | * [New project system doesn't copy PDBs from packages](https://github.com/dotnet/sdk/issues/1458) 45 | * [CopyDebugSymbolFilesFromPackages does not copy pdbs from runtime dir](https://github.com/dotnet/sdk/issues/38322) 46 | 47 | This is done via manipulating `ReferenceCopyLocalPaths`: 48 | 49 | 50 | 51 | ```targets 52 | 55 | 56 | 59 | 61 | 62 | 63 | 64 | ``` 65 | snippet source | anchor 66 | 67 | 68 | This is done at Build time. 69 | 70 | 71 | ### 2. Runs dotnet-symbol 72 | 73 | On a [dotnet-publish](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish) any missing symbols are attempted to be downloaded via the [dotnet-symbol tool](https://www.nuget.org/packages/dotnet-symbol) ([Source](https://github.com/dotnet/symstore)). 74 | 75 | This is done at Publish time. 76 | 77 | 78 | ## Usage 79 | 80 | Install the NuGet package in the top level project. i.e. the project that 'dotnet publish' is called on 81 | 82 | https://nuget.org/packages/Cymbal/ 83 | 84 | ``` 85 | Install-Package Cymbal 86 | ``` 87 | 88 | 89 | ## Outcome 90 | 91 | Given an exe project with a single package reference to `Microsoft.Data.SqlClient`, the output on disk is 39 files: 92 | 93 | ``` 94 | │ Azure.Core.dll 95 | │ Azure.Identity.dll 96 | │ Microsoft.Bcl.AsyncInterfaces.dll 97 | │ Microsoft.Data.SqlClient.dll 98 | │ Microsoft.Identity.Client.dll 99 | │ Microsoft.Identity.Client.Extensions.Msal.dll 100 | │ Microsoft.IdentityModel.Abstractions.dll 101 | │ Microsoft.IdentityModel.JsonWebTokens.dll 102 | │ Microsoft.IdentityModel.Logging.dll 103 | │ Microsoft.IdentityModel.Protocols.dll 104 | │ Microsoft.IdentityModel.Protocols.OpenIdConnect.dll 105 | │ Microsoft.IdentityModel.Tokens.dll 106 | │ Microsoft.SqlServer.Server.dll 107 | │ Microsoft.Win32.SystemEvents.dll 108 | │ SampleApp.deps.json 109 | │ SampleApp.dll 110 | │ SampleApp.exe 111 | │ SampleApp.pdb 112 | │ SampleApp.runtimeconfig.json 113 | │ System.Configuration.ConfigurationManager.dll 114 | │ System.Drawing.Common.dll 115 | │ System.IdentityModel.Tokens.Jwt.dll 116 | │ System.Memory.Data.dll 117 | │ System.Runtime.Caching.dll 118 | │ System.Security.Cryptography.ProtectedData.dll 119 | │ System.Security.Permissions.dll 120 | │ System.Windows.Extensions.dll 121 | └───runtimes 122 | ├───unix/lib/net6.0 123 | │ Microsoft.Data.SqlClient.dll 124 | │ System.Drawing.Common.dll 125 | ├───win/lib/net6.0 126 | │ Microsoft.Data.SqlClient.dll 127 | │ Microsoft.Win32.SystemEvents.dll 128 | │ System.Drawing.Common.dll 129 | │ System.Runtime.Caching.dll 130 | │ System.Security.Cryptography.ProtectedData.dll 131 | │ System.Windows.Extensions.dll 132 | ├───win-arm/native 133 | │ Microsoft.Data.SqlClient.SNI.dll 134 | ├───win-arm64/native 135 | │ Microsoft.Data.SqlClient.SNI.dll 136 | ├───win-x64/native 137 | │ Microsoft.Data.SqlClient.SNI.dll 138 | └───win-x86/native 139 | Microsoft.Data.SqlClient.SNI.dll 140 | ``` 141 | 142 | With the addition of Cymbal, the output on disk is 73 files with the pdb files included: 143 | 144 | ``` 145 | │ Azure.Core.dll 146 | │ Azure.Core.pdb 147 | │ Azure.Identity.dll 148 | │ Azure.Identity.pdb 149 | │ Microsoft.Bcl.AsyncInterfaces.dll 150 | │ Microsoft.Bcl.AsyncInterfaces.pdb 151 | │ Microsoft.Data.SqlClient.dll 152 | │ Microsoft.Data.SqlClient.pdb 153 | │ Microsoft.Identity.Client.dll 154 | │ Microsoft.Identity.Client.Extensions.Msal.dll 155 | │ Microsoft.Identity.Client.Extensions.Msal.pdb 156 | │ Microsoft.Identity.Client.pdb 157 | │ Microsoft.IdentityModel.Abstractions.dll 158 | │ Microsoft.IdentityModel.Abstractions.pdb 159 | │ Microsoft.IdentityModel.JsonWebTokens.dll 160 | │ Microsoft.IdentityModel.JsonWebTokens.pdb 161 | │ Microsoft.IdentityModel.Logging.dll 162 | │ Microsoft.IdentityModel.Logging.pdb 163 | │ Microsoft.IdentityModel.Protocols.dll 164 | │ Microsoft.IdentityModel.Protocols.OpenIdConnect.dll 165 | │ Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb 166 | │ Microsoft.IdentityModel.Protocols.pdb 167 | │ Microsoft.IdentityModel.Tokens.dll 168 | │ Microsoft.IdentityModel.Tokens.pdb 169 | │ Microsoft.SqlServer.Server.dll 170 | │ Microsoft.SqlServer.Server.pdb 171 | │ Microsoft.Win32.SystemEvents.dll 172 | │ Microsoft.Win32.SystemEvents.pdb 173 | │ SampleApp.deps.json 174 | │ SampleApp.dll 175 | │ SampleApp.exe 176 | │ SampleApp.pdb 177 | │ SampleApp.runtimeconfig.json 178 | │ System.Configuration.ConfigurationManager.dll 179 | │ System.Configuration.ConfigurationManager.pdb 180 | │ System.Drawing.Common.dll 181 | │ System.Drawing.Common.pdb 182 | │ System.IdentityModel.Tokens.Jwt.dll 183 | │ System.IdentityModel.Tokens.Jwt.pdb 184 | │ System.Memory.Data.dll 185 | │ System.Memory.Data.pdb 186 | │ System.Runtime.Caching.dll 187 | │ System.Runtime.Caching.pdb 188 | │ System.Security.Cryptography.ProtectedData.dll 189 | │ System.Security.Cryptography.ProtectedData.pdb 190 | │ System.Security.Permissions.dll 191 | │ System.Security.Permissions.pdb 192 | │ System.Windows.Extensions.dll 193 | │ System.Windows.Extensions.pdb 194 | └───runtimes 195 | ├───unix/lib/net6.0 196 | │ Microsoft.Data.SqlClient.dll 197 | │ Microsoft.Data.SqlClient.pdb 198 | │ System.Drawing.Common.dll 199 | │ System.Drawing.Common.pdb 200 | ├───win/lib/net6.0 201 | │ Microsoft.Data.SqlClient.dll 202 | │ Microsoft.Data.SqlClient.pdb 203 | │ Microsoft.Win32.SystemEvents.dll 204 | │ Microsoft.Win32.SystemEvents.pdb 205 | │ System.Drawing.Common.dll 206 | │ System.Drawing.Common.pdb 207 | │ System.Runtime.Caching.dll 208 | │ System.Runtime.Caching.pdb 209 | │ System.Security.Cryptography.ProtectedData.dll 210 | │ System.Security.Cryptography.ProtectedData.pdb 211 | │ System.Windows.Extensions.dll 212 | │ System.Windows.Extensions.pdb 213 | ├───win-arm/native 214 | │ Microsoft.Data.SqlClient.SNI.dll 215 | │ Microsoft.Data.SqlClient.SNI.pdb 216 | ├───win-arm64/native 217 | │ Microsoft.Data.SqlClient.SNI.dll 218 | │ Microsoft.Data.SqlClient.SNI.pdb 219 | ├───win-x64/native 220 | │ Microsoft.Data.SqlClient.SNI.dll 221 | │ Microsoft.Data.SqlClient.SNI.pdb 222 | └───win-x86/native 223 | Microsoft.Data.SqlClient.SNI.dll 224 | Microsoft.Data.SqlClient.SNI.pdb 225 | ``` 226 | 227 | 228 | ## dotnet-symbol required 229 | 230 | To install the [dotnet-symbol tool](https://www.nuget.org/packages/dotnet-symbol), the recommended approach is to [install it as a local tool](https://docs.microsoft.com/en-us/dotnet/core/tools/local-tools-how-to-use). 231 | 232 | In the root of a repository execute: 233 | 234 | ``` 235 | dotnet new tool-manifest 236 | dotnet tool install dotnet-symbol 237 | ``` 238 | 239 | This will result in a `.config/dotnet-tools.json` file: 240 | 241 | 242 | 243 | ```json 244 | { 245 | "version": 1, 246 | "isRoot": true, 247 | "tools": { 248 | "dotnet-symbol": { 249 | "version": "9.0.621003", 250 | "commands": [ 251 | "dotnet-symbol" 252 | ] 253 | } 254 | } 255 | } 256 | ``` 257 | anchor 258 | 259 | 260 | [dotnet tool restore](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-tool-restore) can then be run locally or in a build environment: 261 | 262 | ``` 263 | dotnet tool restore 264 | ``` 265 | 266 | Or to point to a nested directory: 267 | 268 | ``` 269 | dotnet tool restore --tool-manifest src/.config/dotnet-tools.json 270 | ``` 271 | 272 | 273 | ### Scanned symbol servers 274 | 275 | * https://symbols.nuget.org/download/symbols 276 | * https://msdl.microsoft.com/download/symbols/ 277 | 278 | ### Overriding symbol servers 279 | 280 | Add the following to the project or `Directory.Build.props`: 281 | 282 | 283 | 284 | ```csproj 285 | 286 | 287 | 288 | 289 | ``` 290 | snippet source | anchor 291 | 292 | 293 | 294 | ## Cache Directory 295 | 296 | The cache directory can be controlled via either: 297 | 298 | * An environment variable `CymbalCacheDirectory`. Must contain a full path. Or: 299 | * An MSBuild property `CymbalCacheDirectory`. This can be passed into a `dotnet publish` using `-p:CymbalCacheDirectory=FullOrRelativePath`. `Path.GetFullPath()` will be used on the value. 300 | 301 | The resolved directory will be created if it doesn't exist. 302 | 303 | The MSBuild property take priority over the environment variable. 304 | 305 | 306 | ## Icon 307 | 308 | [Cymbals](https://thenounproject.com/term/cymbals/4920970/) designed by [Eucalyp](https://thenounproject.com/eucalyp) from [The Noun Project](https://thenounproject.com). 309 | 310 | 311 | -------------------------------------------------------------------------------- /src/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-symbol": { 6 | "version": "9.0.621003", 7 | "commands": [ 8 | "dotnet-symbol" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | 6 | [*.cs] 7 | indent_size = 4 8 | charset = utf-8 9 | 10 | # Redundant accessor body 11 | resharper_redundant_accessor_body_highlighting = error 12 | 13 | # Replace with field keyword 14 | resharper_replace_with_field_keyword_highlighting = error 15 | 16 | # Replace with single call to Single(..) 17 | resharper_replace_with_single_call_to_single_highlighting = error 18 | 19 | # Replace with single call to SingleOrDefault(..) 20 | resharper_replace_with_single_call_to_single_or_default_highlighting = error 21 | 22 | # Replace with single call to LastOrDefault(..) 23 | resharper_replace_with_single_call_to_last_or_default_highlighting = error 24 | 25 | # Replace with single call to Last(..) 26 | resharper_replace_with_single_call_to_last_highlighting = error 27 | 28 | # Replace with single call to First(..) 29 | resharper_replace_with_single_call_to_first_highlighting = error 30 | 31 | # Replace with single call to FirstOrDefault(..) 32 | resharper_replace_with_single_call_to_first_or_default_highlighting = error 33 | 34 | # Replace with single call to Any(..) 35 | resharper_replace_with_single_call_to_any_highlighting = error 36 | 37 | # Replace with single call to Count(..) 38 | resharper_replace_with_single_call_to_count_highlighting = error 39 | 40 | # Declare types in namespaces 41 | dotnet_diagnostic.CA1050.severity = none 42 | 43 | # Use Literals Where Appropriate 44 | dotnet_diagnostic.CA1802.severity = error 45 | 46 | # Template should be a static expression 47 | dotnet_diagnostic.CA2254.severity = error 48 | 49 | # Potentially misleading parameter name in lambda or local function 50 | resharper_all_underscore_local_parameter_name_highlighting = none 51 | 52 | # Redundant explicit collection creation in argument of 'params' parameter 53 | resharper_redundant_explicit_params_array_creation_highlighting = error 54 | 55 | # Do not initialize unnecessarily 56 | dotnet_diagnostic.CA1805.severity = error 57 | 58 | # Avoid unsealed attributes 59 | dotnet_diagnostic.CA1813.severity = error 60 | 61 | # Test for empty strings using string length 62 | dotnet_diagnostic.CA1820.severity = none 63 | 64 | # Remove empty finalizers 65 | dotnet_diagnostic.CA1821.severity = error 66 | 67 | # Mark members as static 68 | dotnet_diagnostic.CA1822.severity = error 69 | 70 | # Avoid unused private fields 71 | dotnet_diagnostic.CA1823.severity = error 72 | 73 | # Avoid zero-length array allocations 74 | dotnet_diagnostic.CA1825.severity = error 75 | 76 | # Use property instead of Linq Enumerable method 77 | dotnet_diagnostic.CA1826.severity = error 78 | 79 | # Do not use Count()/LongCount() when Any() can be used 80 | dotnet_diagnostic.CA1827.severity = error 81 | dotnet_diagnostic.CA1828.severity = error 82 | 83 | # Use Length/Count property instead of Enumerable.Count method 84 | dotnet_diagnostic.CA1829.severity = error 85 | 86 | # Prefer strongly-typed Append and Insert method overloads on StringBuilder 87 | dotnet_diagnostic.CA1830.severity = error 88 | 89 | # Use AsSpan instead of Range-based indexers for string when appropriate 90 | dotnet_diagnostic.CA1831.severity = error 91 | 92 | # Use AsSpan instead of Range-based indexers for string when appropriate 93 | dotnet_diagnostic.CA1831.severity = error 94 | dotnet_diagnostic.CA1832.severity = error 95 | dotnet_diagnostic.CA1833.severity = error 96 | 97 | # Use StringBuilder.Append(char) for single character strings 98 | dotnet_diagnostic.CA1834.severity = error 99 | 100 | # Prefer IsEmpty over Count when available 101 | dotnet_diagnostic.CA1836.severity = error 102 | 103 | # Prefer IsEmpty over Count when available 104 | dotnet_diagnostic.CA1836.severity = error 105 | 106 | # Use Environment.ProcessId instead of Process.GetCurrentProcess().Id 107 | dotnet_diagnostic.CA1837.severity = error 108 | 109 | # Use Environment.ProcessPath instead of Process.GetCurrentProcess().MainModule.FileName 110 | dotnet_diagnostic.CA1839.severity = error 111 | 112 | # Use Environment.CurrentManagedThreadId instead of Thread.CurrentThread.ManagedThreadId 113 | dotnet_diagnostic.CA1840.severity = error 114 | 115 | # Prefer Dictionary Contains methods 116 | dotnet_diagnostic.CA1841.severity = error 117 | 118 | # Do not use WhenAll with a single task 119 | dotnet_diagnostic.CA1842.severity = error 120 | 121 | # Do not use WhenAll/WaitAll with a single task 122 | dotnet_diagnostic.CA1842.severity = error 123 | dotnet_diagnostic.CA1843.severity = error 124 | 125 | # Use span-based 'string.Concat' 126 | dotnet_diagnostic.CA1845.severity = error 127 | 128 | # Prefer AsSpan over Substring 129 | dotnet_diagnostic.CA1846.severity = error 130 | 131 | # Use string.Contains(char) instead of string.Contains(string) with single characters 132 | dotnet_diagnostic.CA1847.severity = error 133 | 134 | # Prefer static HashData method over ComputeHash 135 | dotnet_diagnostic.CA1850.severity = error 136 | 137 | # Possible multiple enumerations of IEnumerable collection 138 | dotnet_diagnostic.CA1851.severity = error 139 | 140 | # Unnecessary call to Dictionary.ContainsKey(key) 141 | dotnet_diagnostic.CA1853.severity = error 142 | 143 | # Prefer the IDictionary.TryGetValue(TKey, out TValue) method 144 | dotnet_diagnostic.CA1854.severity = error 145 | 146 | # Use Span.Clear() instead of Span.Fill() 147 | dotnet_diagnostic.CA1855.severity = error 148 | 149 | # Incorrect usage of ConstantExpected attribute 150 | dotnet_diagnostic.CA1856.severity = error 151 | 152 | # The parameter expects a constant for optimal performance 153 | dotnet_diagnostic.CA1857.severity = error 154 | 155 | # Use StartsWith instead of IndexOf 156 | dotnet_diagnostic.CA1858.severity = error 157 | 158 | # Avoid using Enumerable.Any() extension method 159 | dotnet_diagnostic.CA1860.severity = error 160 | 161 | # Avoid constant arrays as arguments 162 | dotnet_diagnostic.CA1861.severity = error 163 | 164 | # Use the StringComparison method overloads to perform case-insensitive string comparisons 165 | dotnet_diagnostic.CA1862.severity = error 166 | 167 | # Prefer the IDictionary.TryAdd(TKey, TValue) method 168 | dotnet_diagnostic.CA1864.severity = error 169 | 170 | # Use string.Method(char) instead of string.Method(string) for string with single char 171 | dotnet_diagnostic.CA1865.severity = error 172 | dotnet_diagnostic.CA1866.severity = error 173 | dotnet_diagnostic.CA1867.severity = error 174 | 175 | # Unnecessary call to 'Contains' for sets 176 | dotnet_diagnostic.CA1868.severity = error 177 | 178 | # Cache and reuse 'JsonSerializerOptions' instances 179 | dotnet_diagnostic.CA1869.severity = error 180 | 181 | # Use a cached 'SearchValues' instance 182 | dotnet_diagnostic.CA1870.severity = error 183 | 184 | # Microsoft .NET properties 185 | trim_trailing_whitespace = true 186 | csharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:suggestion 187 | resharper_namespace_body = file_scoped 188 | dotnet_naming_rule.private_constants_rule.severity = warning 189 | dotnet_naming_rule.private_constants_rule.style = lower_camel_case_style 190 | dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols 191 | dotnet_naming_rule.private_instance_fields_rule.severity = warning 192 | dotnet_naming_rule.private_instance_fields_rule.style = lower_camel_case_style 193 | dotnet_naming_rule.private_instance_fields_rule.symbols = private_instance_fields_symbols 194 | dotnet_naming_rule.private_static_fields_rule.severity = warning 195 | dotnet_naming_rule.private_static_fields_rule.style = lower_camel_case_style 196 | dotnet_naming_rule.private_static_fields_rule.symbols = private_static_fields_symbols 197 | dotnet_naming_rule.private_static_readonly_rule.severity = warning 198 | dotnet_naming_rule.private_static_readonly_rule.style = lower_camel_case_style 199 | dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols 200 | dotnet_naming_style.lower_camel_case_style.capitalization = camel_case 201 | dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case 202 | dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private 203 | dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field 204 | dotnet_naming_symbols.private_constants_symbols.required_modifiers = const 205 | dotnet_naming_symbols.private_instance_fields_symbols.applicable_accessibilities = private 206 | dotnet_naming_symbols.private_instance_fields_symbols.applicable_kinds = field 207 | dotnet_naming_symbols.private_static_fields_symbols.applicable_accessibilities = private 208 | dotnet_naming_symbols.private_static_fields_symbols.applicable_kinds = field 209 | dotnet_naming_symbols.private_static_fields_symbols.required_modifiers = static 210 | dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private 211 | dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field 212 | dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = static, readonly 213 | dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none 214 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none 215 | dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none 216 | 217 | # ReSharper properties 218 | resharper_object_creation_when_type_not_evident = target_typed 219 | 220 | # ReSharper inspection severities 221 | resharper_arrange_object_creation_when_type_evident_highlighting = error 222 | resharper_arrange_object_creation_when_type_not_evident_highlighting = error 223 | resharper_arrange_redundant_parentheses_highlighting = error 224 | resharper_arrange_static_member_qualifier_highlighting = error 225 | resharper_arrange_this_qualifier_highlighting = error 226 | resharper_arrange_type_member_modifiers_highlighting = none 227 | resharper_built_in_type_reference_style_for_member_access_highlighting = hint 228 | resharper_built_in_type_reference_style_highlighting = hint 229 | resharper_check_namespace_highlighting = none 230 | resharper_convert_to_using_declaration_highlighting = error 231 | resharper_css_not_resolved_highlighting = warning 232 | resharper_field_can_be_made_read_only_local_highlighting = none 233 | resharper_merge_into_logical_pattern_highlighting = warning 234 | resharper_merge_into_pattern_highlighting = error 235 | resharper_method_has_async_overload_highlighting = warning 236 | # because stop rider giving errors before source generators have run 237 | resharper_partial_type_with_single_part_highlighting = warning 238 | resharper_redundant_base_qualifier_highlighting = warning 239 | resharper_redundant_cast_highlighting = error 240 | resharper_redundant_empty_object_creation_argument_list_highlighting = error 241 | resharper_redundant_empty_object_or_collection_initializer_highlighting = error 242 | resharper_redundant_name_qualifier_highlighting = error 243 | resharper_redundant_suppress_nullable_warning_expression_highlighting = error 244 | resharper_redundant_using_directive_highlighting = error 245 | resharper_redundant_verbatim_string_prefix_highlighting = error 246 | resharper_redundant_lambda_signature_parentheses_highlighting = error 247 | resharper_replace_substring_with_range_indexer_highlighting = warning 248 | resharper_suggest_var_or_type_built_in_types_highlighting = error 249 | resharper_suggest_var_or_type_elsewhere_highlighting = error 250 | resharper_suggest_var_or_type_simple_types_highlighting = error 251 | resharper_unnecessary_whitespace_highlighting = error 252 | resharper_use_await_using_highlighting = warning 253 | resharper_use_deconstruction_highlighting = warning 254 | 255 | # Sort using and Import directives with System.* appearing first 256 | dotnet_sort_system_directives_first = true 257 | 258 | # Avoid "this." and "Me." if not necessary 259 | dotnet_style_qualification_for_field = false:error 260 | dotnet_style_qualification_for_property = false:error 261 | dotnet_style_qualification_for_method = false:error 262 | dotnet_style_qualification_for_event = false:error 263 | 264 | # Use language keywords instead of framework type names for type references 265 | dotnet_style_predefined_type_for_locals_parameters_members = true:error 266 | dotnet_style_predefined_type_for_member_access = true:error 267 | 268 | # Suggest more modern language features when available 269 | dotnet_style_object_initializer = true:error 270 | dotnet_style_collection_initializer = true:error 271 | dotnet_style_coalesce_expression = false:error 272 | dotnet_style_null_propagation = true:error 273 | dotnet_style_explicit_tuple_names = true:error 274 | 275 | # Use collection expression syntax 276 | resharper_use_collection_expression_highlighting = error 277 | 278 | # Prefer "var" everywhere 279 | csharp_style_var_for_built_in_types = true:error 280 | csharp_style_var_when_type_is_apparent = true:error 281 | csharp_style_var_elsewhere = true:error 282 | 283 | # Prefer method-like constructs to have a block body 284 | csharp_style_expression_bodied_methods = true:error 285 | csharp_style_expression_bodied_local_functions = true:error 286 | csharp_style_expression_bodied_constructors = true:error 287 | csharp_style_expression_bodied_operators = true:error 288 | resharper_place_expr_method_on_single_line = false 289 | 290 | # Prefer property-like constructs to have an expression-body 291 | csharp_style_expression_bodied_properties = true:error 292 | csharp_style_expression_bodied_indexers = true:error 293 | csharp_style_expression_bodied_accessors = true:error 294 | 295 | # Suggest more modern language features when available 296 | csharp_style_pattern_matching_over_is_with_cast_check = true:error 297 | csharp_style_pattern_matching_over_as_with_null_check = true:error 298 | csharp_style_inlined_variable_declaration = true:suggestion 299 | csharp_style_throw_expression = true:suggestion 300 | csharp_style_conditional_delegate_call = true:suggestion 301 | 302 | # Newline settings 303 | #csharp_new_line_before_open_brace = all:error 304 | resharper_max_array_initializer_elements_on_line = 1 305 | csharp_new_line_before_else = true 306 | csharp_new_line_before_catch = true 307 | csharp_new_line_before_finally = true 308 | csharp_new_line_before_members_in_object_initializers = true 309 | csharp_new_line_before_members_in_anonymous_types = true 310 | resharper_wrap_before_first_type_parameter_constraint = true 311 | resharper_wrap_extends_list_style = chop_always 312 | resharper_wrap_after_dot_in_method_calls = false 313 | resharper_wrap_before_binary_pattern_op = false 314 | resharper_wrap_object_and_collection_initializer_style = chop_always 315 | resharper_place_simple_initializer_on_single_line = false 316 | 317 | # space 318 | resharper_space_around_lambda_arrow = true 319 | 320 | dotnet_style_require_accessibility_modifiers = never:error 321 | resharper_place_type_constraints_on_same_line = false 322 | resharper_blank_lines_inside_namespace = 0 323 | resharper_blank_lines_after_file_scoped_namespace_directive = 1 324 | resharper_blank_lines_inside_type = 0 325 | 326 | insert_final_newline = false 327 | resharper_place_attribute_on_same_line = false 328 | resharper_space_around_lambda_arrow = true 329 | resharper_place_constructor_initializer_on_same_line = false 330 | 331 | #braces https://www.jetbrains.com/help/resharper/EditorConfig_CSHARP_CSharpCodeStylePageImplSchema.html#Braces 332 | resharper_braces_for_ifelse = required 333 | resharper_braces_for_foreach = required 334 | resharper_braces_for_while = required 335 | resharper_braces_for_dowhile = required 336 | resharper_braces_for_lock = required 337 | resharper_braces_for_fixed = required 338 | resharper_braces_for_for = required 339 | 340 | resharper_return_value_of_pure_method_is_not_used_highlighting = error 341 | 342 | resharper_all_underscore_local_parameter_name_highlighting = none 343 | 344 | resharper_misleading_body_like_statement_highlighting = error 345 | 346 | resharper_redundant_record_class_keyword_highlighting = error 347 | 348 | resharper_redundant_extends_list_entry_highlighting = error 349 | 350 | # Xml files 351 | [*.{xml,config,nuspec,resx,vsixmanifest,csproj,targets,props,fsproj}] 352 | indent_size = 2 353 | # https://www.jetbrains.com/help/resharper/EditorConfig_XML_XmlCodeStylePageSchema.html#resharper_xml_blank_line_after_pi 354 | resharper_blank_line_after_pi = false 355 | resharper_space_before_self_closing = true 356 | ij_xml_space_inside_empty_tag = true 357 | 358 | [*.json] 359 | indent_size = 2 360 | 361 | # Verify settings 362 | [*.{received,verified}.{txt,xml,json,md,sql,csv,html,htm,md}] 363 | charset = utf-8-bom 364 | end_of_line = lf 365 | indent_size = unset 366 | indent_style = unset 367 | insert_final_newline = false 368 | tab_width = unset 369 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /src/AssemblyWithEmbeddedSymbols/AssemblyWithEmbeddedSymbols.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 1.0.0 4 | net9.0 5 | embedded 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/AssemblyWithEmbeddedSymbols/AssemblyWithEmbeddedSymbolsClass.cs: -------------------------------------------------------------------------------- 1 | public static class AssemblyWithEmbeddedSymbolsClass 2 | { 3 | public static string Method() => 4 | "AssemblyWithEmbeddedSymbols"; 5 | } -------------------------------------------------------------------------------- /src/AssemblyWithEmbeddedSymbols/Class1.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithNoSymbols; 2 | 3 | public class Class1 4 | { 5 | int field; 6 | 7 | public void Method(int param) 8 | { 9 | field = param; 10 | param += 1; 11 | if (param == field) 12 | { 13 | field -= 1; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/AssemblyWithNoSymbols/AssemblyWithNoSymbols.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 1.0.0 4 | net9.0 5 | none 6 | false 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/AssemblyWithNoSymbols/AssemblyWithNoSymbolsClass.cs: -------------------------------------------------------------------------------- 1 | public static class AssemblyWithNoSymbolsClass 2 | { 3 | public static string Method() => 4 | "AssemblyWithNoSymbols"; 5 | } -------------------------------------------------------------------------------- /src/AssemblyWithPdb/AssemblyWithPdb.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 1.0.0 4 | net9.0 5 | portable 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/AssemblyWithPdb/AssemblyWithPdbClass.cs: -------------------------------------------------------------------------------- 1 | public static class AssemblyWithPdbClass 2 | { 3 | public static string Method() => 4 | "AssemblyWithPdb"; 5 | } -------------------------------------------------------------------------------- /src/Cymbal.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31815.197 5 | MinimumVisualStudioVersion = 16.0.29201.188 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CDCDDCD6-6958-4352-AF0C-C589ECD51C0D}" 7 | ProjectSection(SolutionItems) = preProject 8 | appveyor.yml = appveyor.yml 9 | Directory.Build.props = Directory.Build.props 10 | Directory.Packages.props = Directory.Packages.props 11 | mdsnippets.json = mdsnippets.json 12 | ..\readme.md = ..\readme.md 13 | .config\dotnet-tools.json = .config\dotnet-tools.json 14 | global.json = global.json 15 | nuget.config = nuget.config 16 | EndProjectSection 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cymbal", "Cymbal\Cymbal.csproj", "{23FA87B2-180C-4940-8225-B979CEF08312}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApp", "SampleApp\SampleApp.csproj", "{402E22F6-0A79-4600-9202-8B89D6B87C3A}" 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{E49A9CD5-5427-42F4-AA20-A8356A2B782E}" 23 | ProjectSection(ProjectDependencies) = postProject 24 | {402E22F6-0A79-4600-9202-8B89D6B87C3A} = {402E22F6-0A79-4600-9202-8B89D6B87C3A} 25 | EndProjectSection 26 | EndProject 27 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssemblyWithPdb", "AssemblyWithPdb\AssemblyWithPdb.csproj", "{58B685C4-5A68-49A6-8567-6A85A3C592AE}" 28 | EndProject 29 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssemblyWithNoSymbols", "AssemblyWithNoSymbols\AssemblyWithNoSymbols.csproj", "{C0720E69-F712-43B3-92D8-9E7133422208}" 30 | EndProject 31 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssemblyWithEmbeddedSymbols", "AssemblyWithEmbeddedSymbols\AssemblyWithEmbeddedSymbols.csproj", "{F82D5FF7-862A-4A4A-B50F-EB340D796A49}" 32 | EndProject 33 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleWithSymbolServer", "SampleWithSymbolServer\SampleWithSymbolServer.csproj", "{CC9579A9-318E-48B2-B189-BB74CEC279C3}" 34 | EndProject 35 | Global 36 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 37 | Debug|Any CPU = Debug|Any CPU 38 | IncludeTask|Any CPU = IncludeTask|Any CPU 39 | Release|Any CPU = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 42 | {23FA87B2-180C-4940-8225-B979CEF08312}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {23FA87B2-180C-4940-8225-B979CEF08312}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {23FA87B2-180C-4940-8225-B979CEF08312}.IncludeTask|Any CPU.ActiveCfg = IncludeTask|Any CPU 45 | {23FA87B2-180C-4940-8225-B979CEF08312}.IncludeTask|Any CPU.Build.0 = IncludeTask|Any CPU 46 | {23FA87B2-180C-4940-8225-B979CEF08312}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {23FA87B2-180C-4940-8225-B979CEF08312}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {402E22F6-0A79-4600-9202-8B89D6B87C3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {402E22F6-0A79-4600-9202-8B89D6B87C3A}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {402E22F6-0A79-4600-9202-8B89D6B87C3A}.IncludeTask|Any CPU.ActiveCfg = IncludeTask|Any CPU 51 | {402E22F6-0A79-4600-9202-8B89D6B87C3A}.IncludeTask|Any CPU.Build.0 = IncludeTask|Any CPU 52 | {402E22F6-0A79-4600-9202-8B89D6B87C3A}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {402E22F6-0A79-4600-9202-8B89D6B87C3A}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {E49A9CD5-5427-42F4-AA20-A8356A2B782E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {E49A9CD5-5427-42F4-AA20-A8356A2B782E}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {E49A9CD5-5427-42F4-AA20-A8356A2B782E}.IncludeTask|Any CPU.ActiveCfg = IncludeTask|Any CPU 57 | {E49A9CD5-5427-42F4-AA20-A8356A2B782E}.IncludeTask|Any CPU.Build.0 = IncludeTask|Any CPU 58 | {E49A9CD5-5427-42F4-AA20-A8356A2B782E}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {E49A9CD5-5427-42F4-AA20-A8356A2B782E}.Release|Any CPU.Build.0 = Release|Any CPU 60 | {58B685C4-5A68-49A6-8567-6A85A3C592AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 61 | {58B685C4-5A68-49A6-8567-6A85A3C592AE}.Debug|Any CPU.Build.0 = Debug|Any CPU 62 | {58B685C4-5A68-49A6-8567-6A85A3C592AE}.IncludeTask|Any CPU.ActiveCfg = IncludeTask|Any CPU 63 | {58B685C4-5A68-49A6-8567-6A85A3C592AE}.IncludeTask|Any CPU.Build.0 = IncludeTask|Any CPU 64 | {58B685C4-5A68-49A6-8567-6A85A3C592AE}.Release|Any CPU.ActiveCfg = Release|Any CPU 65 | {58B685C4-5A68-49A6-8567-6A85A3C592AE}.Release|Any CPU.Build.0 = Release|Any CPU 66 | {C0720E69-F712-43B3-92D8-9E7133422208}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {C0720E69-F712-43B3-92D8-9E7133422208}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {C0720E69-F712-43B3-92D8-9E7133422208}.IncludeTask|Any CPU.ActiveCfg = IncludeTask|Any CPU 69 | {C0720E69-F712-43B3-92D8-9E7133422208}.IncludeTask|Any CPU.Build.0 = IncludeTask|Any CPU 70 | {C0720E69-F712-43B3-92D8-9E7133422208}.Release|Any CPU.ActiveCfg = Release|Any CPU 71 | {C0720E69-F712-43B3-92D8-9E7133422208}.Release|Any CPU.Build.0 = Release|Any CPU 72 | {F82D5FF7-862A-4A4A-B50F-EB340D796A49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 73 | {F82D5FF7-862A-4A4A-B50F-EB340D796A49}.Debug|Any CPU.Build.0 = Debug|Any CPU 74 | {F82D5FF7-862A-4A4A-B50F-EB340D796A49}.IncludeTask|Any CPU.ActiveCfg = IncludeTask|Any CPU 75 | {F82D5FF7-862A-4A4A-B50F-EB340D796A49}.IncludeTask|Any CPU.Build.0 = IncludeTask|Any CPU 76 | {F82D5FF7-862A-4A4A-B50F-EB340D796A49}.Release|Any CPU.ActiveCfg = Release|Any CPU 77 | {F82D5FF7-862A-4A4A-B50F-EB340D796A49}.Release|Any CPU.Build.0 = Release|Any CPU 78 | {CC9579A9-318E-48B2-B189-BB74CEC279C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 79 | {CC9579A9-318E-48B2-B189-BB74CEC279C3}.Debug|Any CPU.Build.0 = Debug|Any CPU 80 | {CC9579A9-318E-48B2-B189-BB74CEC279C3}.IncludeTask|Any CPU.ActiveCfg = IncludeTask|Any CPU 81 | {CC9579A9-318E-48B2-B189-BB74CEC279C3}.IncludeTask|Any CPU.Build.0 = IncludeTask|Any CPU 82 | {CC9579A9-318E-48B2-B189-BB74CEC279C3}.Release|Any CPU.ActiveCfg = Release|Any CPU 83 | {CC9579A9-318E-48B2-B189-BB74CEC279C3}.Release|Any CPU.Build.0 = Release|Any CPU 84 | EndGlobalSection 85 | GlobalSection(SolutionProperties) = preSolution 86 | HideSolutionNode = FALSE 87 | EndGlobalSection 88 | GlobalSection(ExtensibilityGlobals) = postSolution 89 | SolutionGuid = {0FE54436-4FAF-48C4-BE04-48D08110A1FD} 90 | EndGlobalSection 91 | EndGlobal 92 | -------------------------------------------------------------------------------- /src/Cymbal.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | ..\Shared.sln.DotSettings 3 | True 4 | True 5 | 1 6 | -------------------------------------------------------------------------------- /src/Cymbal/Cymbal.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | NU5118 5 | netstandard2.0 6 | true 7 | false 8 | true 9 | false 10 | true 11 | true 12 | false 13 | Enable line numbers for exceptions in a deployed app via downloading and bundling symbols during a dotnet publish. 14 | 15 | 16 | 17 | true 18 | task 19 | 20 | 21 | true 22 | build 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/Cymbal/CymbalTask.cs: -------------------------------------------------------------------------------- 1 | using Task = Microsoft.Build.Utilities.Task; 2 | 3 | public class CymbalTask : 4 | Task, 5 | ICancelableTask 6 | { 7 | const string msdlSymbolServer = "https://msdl.microsoft.com/download/symbols/"; 8 | const string nugetSymbolServer = "https://symbols.nuget.org/download/symbols"; 9 | 10 | [Required] 11 | public string PublishDirectory { get; set; } = null!; 12 | 13 | public string? CacheDirectory { get; set; } 14 | 15 | public string[]? SymbolServers { get; set; } 16 | 17 | public override bool Execute() 18 | { 19 | var stopwatch = Stopwatch.StartNew(); 20 | try 21 | { 22 | InnerExecute(); 23 | return true; 24 | } 25 | catch (Error exception) 26 | { 27 | Log.LogError($"Cymbal: {exception.Message}"); 28 | return false; 29 | } 30 | finally 31 | { 32 | Log.LogMessageFromText($"Finished Cymbal {stopwatch.ElapsedMilliseconds}ms", MessageImportance.High); 33 | } 34 | } 35 | 36 | void InnerExecute() 37 | { 38 | string? cacheDirectory; 39 | var environmentCacheDirectory = Environment.GetEnvironmentVariable("CymbalCacheDirectory"); 40 | if (CacheDirectory == null) 41 | { 42 | cacheDirectory = environmentCacheDirectory; 43 | } 44 | else 45 | { 46 | cacheDirectory = Path.GetFullPath(CacheDirectory); 47 | } 48 | 49 | if (cacheDirectory != null) 50 | { 51 | Directory.CreateDirectory(cacheDirectory); 52 | } 53 | 54 | var fullPublishPath = Path.GetFullPath(PublishDirectory); 55 | var inputs = 56 | $""" 57 | PublishDir: {fullPublishPath} 58 | CymbalCacheDirectory environment variable: {environmentCacheDirectory} 59 | CymbalCacheDirectory MsBuild property: {CacheDirectory} 60 | Resolved CacheDirectory: {cacheDirectory} 61 | """; 62 | Log.LogMessageFromText(inputs, MessageImportance.High); 63 | 64 | var (hasPdb, isEmbedded, toDownload) = GetFiles(fullPublishPath); 65 | 66 | if (hasPdb.Count != 0) 67 | { 68 | Log.LogMessageFromText($"Skipped assemblies with existing pdbs:{ListToIndented(hasPdb)}", MessageImportance.Normal); 69 | } 70 | 71 | if (isEmbedded.Count != 0) 72 | { 73 | Log.LogMessageFromText($"Skipped assemblies with embedded symbols:{ListToIndented(isEmbedded)}", MessageImportance.Normal); 74 | } 75 | 76 | if (toDownload.Count == 0) 77 | { 78 | Log.LogMessageFromText("No assemblies found to process", MessageImportance.Normal); 79 | return; 80 | } 81 | 82 | Log.LogMessageFromText($"Assemblies to process:{ListToIndented(toDownload)}", MessageImportance.Normal); 83 | 84 | var symbolServers = SymbolServers ?? defaultSymbolServers; 85 | Log.LogMessageFromText($"Symbol servers used:{ListToIndented(symbolServers)}", MessageImportance.Normal); 86 | 87 | var (missingSymbols, foundSymbols) = SymbolDownloader.Run(cacheDirectory, toDownload, symbolServers); 88 | 89 | if (foundSymbols.Count != 0) 90 | { 91 | Log.LogMessageFromText($"Symbols written:{ListToIndented(foundSymbols)}", MessageImportance.High); 92 | } 93 | 94 | if (missingSymbols.Count != 0) 95 | { 96 | Log.LogMessageFromText($"Missing Symbols:{ListToIndented(missingSymbols)}", MessageImportance.High); 97 | } 98 | } 99 | 100 | static string[] defaultSymbolServers = 101 | [ 102 | nugetSymbolServer, 103 | msdlSymbolServer 104 | ]; 105 | 106 | static string ListToIndented(IEnumerable toDownload) => 107 | $"{Environment.NewLine}\t{string.Join($"{Environment.NewLine}\t", toDownload)}"; 108 | 109 | static (List hasPdb, List isEmbedded, List toDownload) GetFiles(string fullPublishPath) 110 | { 111 | var toDownload = new List(); 112 | var isEmbedded = new List(); 113 | var hasPdb = new List(); 114 | foreach (var assemblyPath in Directory.EnumerateFiles(fullPublishPath, "*.dll", SearchOption.AllDirectories)) 115 | { 116 | var symbolPath = Path.ChangeExtension(assemblyPath, ".pdb"); 117 | if (File.Exists(symbolPath)) 118 | { 119 | hasPdb.Add(assemblyPath); 120 | continue; 121 | } 122 | 123 | if (SymbolChecker.HasEmbedded(assemblyPath)) 124 | { 125 | isEmbedded.Add(assemblyPath); 126 | continue; 127 | } 128 | 129 | toDownload.Add(assemblyPath); 130 | } 131 | 132 | return (hasPdb, isEmbedded, toDownload); 133 | } 134 | 135 | public void Cancel() 136 | { 137 | } 138 | } -------------------------------------------------------------------------------- /src/Cymbal/Dotnet.cs: -------------------------------------------------------------------------------- 1 | public static class ProcessRunner 2 | { 3 | public static List Execute(string command, string arguments) 4 | { 5 | using var process = new Process 6 | { 7 | StartInfo = new() 8 | { 9 | FileName = command, 10 | Arguments = arguments, 11 | UseShellExecute = false, 12 | RedirectStandardOutput = true, 13 | RedirectStandardError = true, 14 | CreateNoWindow = true 15 | } 16 | }; 17 | 18 | process.Start(); 19 | 20 | var errorBuilder = new StringBuilder(); 21 | var output = new List(); 22 | process.OutputDataReceived += (_, args) => 23 | { 24 | if (args.Data != null) 25 | { 26 | output.Add(args.Data); 27 | } 28 | }; 29 | process.BeginOutputReadLine(); 30 | process.ErrorDataReceived += (_, args) => 31 | { 32 | if (args.Data != null) 33 | { 34 | errorBuilder.AppendLine(args.Data); 35 | } 36 | }; 37 | process.BeginErrorReadLine(); 38 | 39 | if (!process.DoubleWaitForExit()) 40 | { 41 | var timeoutError = 42 | $""" 43 | Process timed out. 44 | Command line: {command} {arguments}. 45 | Output: {string.Join(Environment.NewLine, output)} 46 | Error: {errorBuilder} 47 | """; 48 | throw new Error(timeoutError); 49 | } 50 | 51 | if (process.ExitCode == 0) 52 | { 53 | return output; 54 | } 55 | 56 | var errors = errorBuilder.ToString(); 57 | if (errors.Contains("Cannot find a tool in the manifest file that has a command named")) 58 | { 59 | var message = 60 | $""" 61 | The dotnet tool `dotnet-symbol` was not found. 62 | Command line: {command} {arguments} 63 | To install, run in the root of the repository 64 | dotnet new tool-manifest 65 | dotnet tool install dotnet-symbol 66 | """; 67 | throw new Error(message); 68 | } 69 | 70 | var error = 71 | $""" 72 | Could not execute process. 73 | Command line: {command} {arguments}. 74 | Output: {string.Join(Environment.NewLine, output)} 75 | Error: {errors} 76 | """; 77 | throw new Error(error); 78 | } 79 | } -------------------------------------------------------------------------------- /src/Cymbal/Error.cs: -------------------------------------------------------------------------------- 1 | public class Error(string message) : 2 | Exception(message); -------------------------------------------------------------------------------- /src/Cymbal/Extensions.cs: -------------------------------------------------------------------------------- 1 | static class Extensions 2 | { 3 | //To work around https://github.com/dotnet/runtime/issues/27128 4 | public static bool DoubleWaitForExit(this Process process) 5 | { 6 | //4min30sec 7 | const int timeout = 270000; 8 | var result = process.WaitForExit(timeout); 9 | if (result) 10 | { 11 | process.WaitForExit(); 12 | } 13 | 14 | return result; 15 | } 16 | } -------------------------------------------------------------------------------- /src/Cymbal/SymbolChecker.cs: -------------------------------------------------------------------------------- 1 | public static class SymbolChecker 2 | { 3 | public static bool HasEmbedded(string path) 4 | { 5 | using var stream = OpenRead(path); 6 | using var reader = new PEReader(stream); 7 | var entries = reader.ReadDebugDirectory(); 8 | return entries.Any(_ => _.Type == DebugDirectoryEntryType.EmbeddedPortablePdb); 9 | } 10 | 11 | static FileStream OpenRead(string path) => 12 | new(path, FileMode.Open, FileAccess.Read, FileShare.Read); 13 | } -------------------------------------------------------------------------------- /src/Cymbal/SymbolDownloader.cs: -------------------------------------------------------------------------------- 1 | public static class SymbolDownloader 2 | { 3 | public static (List missingSymbols, List foundSymbols) Run(string? cacheDirectory, List toDownload, string[] symbolServers) 4 | { 5 | var arguments = BuildArguments(cacheDirectory, toDownload, symbolServers); 6 | 7 | var result = ProcessRunner.Execute("dotnet", arguments); 8 | 9 | var missingSymbols = new List(); 10 | var foundSymbols = new List(); 11 | foreach (var line in result) 12 | { 13 | ProcessLine(line, missingSymbols, foundSymbols); 14 | } 15 | 16 | foreach (var foundFileName in foundSymbols.Select(Path.GetFileName)) 17 | { 18 | missingSymbols.Remove(foundFileName!); 19 | } 20 | 21 | return (missingSymbols, foundSymbols); 22 | } 23 | 24 | static void ProcessLine(string line, List missingSymbols, List foundSymbols) 25 | { 26 | if (line.StartsWith("ERROR: Not Found: ")) 27 | { 28 | var scrubbedLine = line.Replace("ERROR: Not Found: ", ""); 29 | var indexOfDash = scrubbedLine.IndexOf(" - "); 30 | var missing = scrubbedLine[..indexOfDash]; 31 | if (!missingSymbols.Contains(missing)) 32 | { 33 | missingSymbols.Add(missing); 34 | } 35 | } 36 | else if (line.StartsWith("Writing: ")) 37 | { 38 | var scrubbedLine = line[9..]; 39 | foundSymbols.Add(scrubbedLine); 40 | } 41 | } 42 | 43 | static string BuildArguments(string? cacheDirectory, List toDownload, string[] symbolServers) 44 | { 45 | var arguments = "tool run dotnet-symbol "; 46 | 47 | foreach (var server in symbolServers) 48 | { 49 | arguments += $"--server-path {server} "; 50 | } 51 | 52 | if (cacheDirectory != null) 53 | { 54 | arguments += $"--cache-directory {cacheDirectory} "; 55 | } 56 | 57 | arguments += string.Join(" ", toDownload); 58 | return arguments; 59 | } 60 | } -------------------------------------------------------------------------------- /src/Cymbal/build/Cymbal.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | $(MSBuildThisFileDirectory)..\task\Cymbal.dll 4 | $(MSBuildThisFileDirectory)..\bin\IncludeTask\Cymbal.dll 5 | 6 | 7 | 10 | 13 | 16 | 18 | 19 | 20 | 23 | 24 | 27 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2.0.2 4 | $(ProjectDir)..\ 5 | false 6 | enable 7 | preview 8 | Debug;Release;IncludeTask 9 | NETSDK1057;NU1608;NU1109 10 | true 11 | true 12 | true 13 | true 14 | 15 | -------------------------------------------------------------------------------- /src/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/SampleApp/Program.cs: -------------------------------------------------------------------------------- 1 | Console.WriteLine("asdas"); 2 | -------------------------------------------------------------------------------- /src/SampleApp/SampleApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net9.0 5 | false 6 | NU1902 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/SampleApp/msbuild.binlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonCropp/Cymbal/eec29b45e8fde8b0e0db7c13967e1c22de815a65/src/SampleApp/msbuild.binlog -------------------------------------------------------------------------------- /src/SampleWithSymbolServer/Program.cs: -------------------------------------------------------------------------------- 1 | // See https://aka.ms/new-console-template for more information 2 | Console.WriteLine("Hello, World!"); 3 | -------------------------------------------------------------------------------- /src/SampleWithSymbolServer/SampleWithSymbolServer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net9.0 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Shared.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | False 3 | Quiet 4 | True 5 | True 6 | True 7 | DO_NOT_SHOW 8 | ERROR 9 | ERROR 10 | ERROR 11 | WARNING 12 | ERROR 13 | ERROR 14 | ERROR 15 | ERROR 16 | ERROR 17 | ERROR 18 | ERROR 19 | ERROR 20 | ERROR 21 | ERROR 22 | ERROR 23 | ERROR 24 | ERROR 25 | ERROR 26 | ERROR 27 | ERROR 28 | ERROR 29 | ERROR 30 | ERROR 31 | ERROR 32 | ERROR 33 | ERROR 34 | ERROR 35 | ERROR 36 | ERROR 37 | ERROR 38 | ERROR 39 | ERROR 40 | ERROR 41 | ERROR 42 | ERROR 43 | DO_NOT_SHOW 44 | DO_NOT_SHOW 45 | ERROR 46 | ERROR 47 | ERROR 48 | ERROR 49 | ERROR 50 | ERROR 51 | ERROR 52 | ERROR 53 | ERROR 54 | ERROR 55 | ERROR 56 | ERROR 57 | C90+,E79+,S14+ 58 | ERROR 59 | ERROR 60 | ERROR 61 | ERROR 62 | ERROR 63 | ERROR 64 | ERROR 65 | ERROR 66 | ERROR 67 | ERROR 68 | ERROR 69 | ERROR 70 | ERROR 71 | ERROR 72 | ERROR 73 | ERROR 74 | ERROR 75 | ERROR 76 | ERROR 77 | ERROR 78 | ERROR 79 | ERROR 80 | ERROR 81 | ERROR 82 | ERROR 83 | ERROR 84 | ERROR 85 | ERROR 86 | ERROR 87 | ERROR 88 | ERROR 89 | ERROR 90 | ERROR 91 | ERROR 92 | ERROR 93 | ERROR 94 | ERROR 95 | ERROR 96 | ERROR 97 | ERROR 98 | ERROR 99 | ERROR 100 | ERROR 101 | ERROR 102 | ERROR 103 | ERROR 104 | ERROR 105 | ERROR 106 | ERROR 107 | ERROR 108 | ERROR 109 | ERROR 110 | ERROR 111 | ERROR 112 | ERROR 113 | ERROR 114 | ERROR 115 | ERROR 116 | ERROR 117 | ERROR 118 | ERROR 119 | ERROR 120 | ERROR 121 | ERROR 122 | DO_NOT_SHOW 123 | *.received.* 124 | *.verified.* 125 | ERROR 126 | ERROR 127 | DO_NOT_SHOW 128 | ECMAScript 2016 129 | <?xml version="1.0" encoding="utf-16"?><Profile name="c# Cleanup"><AspOptimizeRegisterDirectives>True</AspOptimizeRegisterDirectives><CSCodeStyleAttributes ArrangeVarStyle="True" ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="True" ArrangeBraces="True" ArrangeAttributes="True" ArrangeCodeBodyStyle="True" ArrangeTrailingCommas="True" ArrangeObjectCreation="True" ArrangeDefaultValue="True" ArrangeNamespaces="True" /><CssAlphabetizeProperties>True</CssAlphabetizeProperties><JSStringLiteralQuotesDescriptor>True</JSStringLiteralQuotesDescriptor><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><VariablesToInnerScopesDescriptor>True</VariablesToInnerScopesDescriptor><StringToTemplatesDescriptor>True</StringToTemplatesDescriptor><JsInsertSemicolon>True</JsInsertSemicolon><RemoveRedundantQualifiersTs>True</RemoveRedundantQualifiersTs><OptimizeImportsTs>True</OptimizeImportsTs><OptimizeReferenceCommentsTs>True</OptimizeReferenceCommentsTs><PublicModifierStyleTs>True</PublicModifierStyleTs><ExplicitAnyTs>True</ExplicitAnyTs><TypeAnnotationStyleTs>True</TypeAnnotationStyleTs><RelativePathStyleTs>True</RelativePathStyleTs><AsInsteadOfCastTs>True</AsInsteadOfCastTs><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CssReformatCode>True</CssReformatCode><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><HtmlReformatCode>True</HtmlReformatCode><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><IDEA_SETTINGS>&lt;profile version="1.0"&gt; 130 | &lt;option name="myName" value="c# Cleanup" /&gt; 131 | &lt;/profile&gt;</IDEA_SETTINGS><RIDER_SETTINGS>&lt;profile&gt; 132 | &lt;Language id="EditorConfig"&gt; 133 | &lt;Reformat&gt;false&lt;/Reformat&gt; 134 | &lt;/Language&gt; 135 | &lt;Language id="HTML"&gt; 136 | &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; 137 | &lt;Reformat&gt;false&lt;/Reformat&gt; 138 | &lt;Rearrange&gt;false&lt;/Rearrange&gt; 139 | &lt;/Language&gt; 140 | &lt;Language id="JSON"&gt; 141 | &lt;Reformat&gt;false&lt;/Reformat&gt; 142 | &lt;/Language&gt; 143 | &lt;Language id="RELAX-NG"&gt; 144 | &lt;Reformat&gt;false&lt;/Reformat&gt; 145 | &lt;/Language&gt; 146 | &lt;Language id="XML"&gt; 147 | &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; 148 | &lt;Reformat&gt;false&lt;/Reformat&gt; 149 | &lt;Rearrange&gt;false&lt;/Rearrange&gt; 150 | &lt;/Language&gt; 151 | &lt;/profile&gt;</RIDER_SETTINGS></Profile> 152 | ExpressionBody 153 | ExpressionBody 154 | ExpressionBody 155 | False 156 | NEVER 157 | NEVER 158 | False 159 | False 160 | False 161 | True 162 | False 163 | CHOP_ALWAYS 164 | False 165 | False 166 | RemoveIndent 167 | RemoveIndent 168 | False 169 | True 170 | True 171 | True 172 | True 173 | True 174 | ERROR 175 | DoNothing 176 | -------------------------------------------------------------------------------- /src/Tests/ModuleInitializer.cs: -------------------------------------------------------------------------------- 1 | [assembly: NonParallelizable] 2 | 3 | public static class ModuleInitializer 4 | { 5 | [ModuleInitializer] 6 | public static void Init() 7 | { 8 | VerifierSettings.InitializePlugins(); 9 | 10 | VerifierSettings.ScrubEmptyLines(); 11 | VerifierSettings.ScrubLinesWithReplace(_ => _.Replace('\\', '/')); 12 | VerifierSettings.ScrubLinesContaining( 13 | "CopyResolved", 14 | "Build started", 15 | "Time Elapsed", 16 | "Finished Cymbal", 17 | "Creating directory", 18 | "Build Engine version", 19 | "Copying file from ", 20 | "Copyright (C) Microsoft Corporation", 21 | "Workload updates are available", 22 | "MSBuild version"); 23 | } 24 | } -------------------------------------------------------------------------------- /src/Tests/Tests.RunTask_environmentCache=False_propertyCache=False.DotNet.verified.txt: -------------------------------------------------------------------------------- 1 | { 2 | buildOutput: 3 | 1>Project "{SolutionDirectory}SampleApp/SampleApp.csproj" on node 1 (Publish target(s)). 4 | 1>PrepareForPublish: 5 | Publish: 6 | SampleApp -> {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ 7 | CymbalTarget: 8 | PublishDir: {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ 9 | CymbalCacheDirectory environment variable: 10 | CymbalCacheDirectory MsBuild property: 11 | Resolved CacheDirectory: 12 | Skipped assemblies with existing pdbs: 13 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithPdb.dll 14 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.SqlServer.Server.dll 15 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/SampleApp.dll 16 | Skipped assemblies with embedded symbols: 17 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithEmbeddedSymbols.dll 18 | Assemblies to process: 19 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithNoSymbols.dll 20 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Core.dll 21 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Identity.dll 22 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Authorization.dll 23 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Components.dll 24 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Metadata.dll 25 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.AsyncInterfaces.dll 26 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.Cryptography.dll 27 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Data.SqlClient.dll 28 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Abstractions.dll 29 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Memory.dll 30 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyInjection.Abstractions.dll 31 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyModel.dll 32 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Logging.Abstractions.dll 33 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Options.dll 34 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Primitives.dll 35 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.dll 36 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.Extensions.Msal.dll 37 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Abstractions.dll 38 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.JsonWebTokens.dll 39 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Logging.dll 40 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.dll 41 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll 42 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Tokens.dll 43 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.AspNetCore.dll 44 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.dll 45 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Hosting.dll 46 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Logging.dll 47 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Formatting.Compact.dll 48 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Settings.Configuration.dll 49 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.Console.dll 50 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.Debug.dll 51 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.File.dll 52 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.ClientModel.dll 53 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Configuration.ConfigurationManager.dll 54 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Diagnostics.EventLog.dll 55 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.IdentityModel.Tokens.Jwt.dll 56 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Memory.Data.dll 57 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Security.Cryptography.Pkcs.dll 58 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Security.Cryptography.ProtectedData.dll 59 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/cs/Microsoft.Data.SqlClient.resources.dll 60 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/de/Microsoft.Data.SqlClient.resources.dll 61 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/es/Microsoft.Data.SqlClient.resources.dll 62 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/fr/Microsoft.Data.SqlClient.resources.dll 63 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/it/Microsoft.Data.SqlClient.resources.dll 64 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ja/Microsoft.Data.SqlClient.resources.dll 65 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ko/Microsoft.Data.SqlClient.resources.dll 66 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/pl/Microsoft.Data.SqlClient.resources.dll 67 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/pt-BR/Microsoft.Data.SqlClient.resources.dll 68 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ru/Microsoft.Data.SqlClient.resources.dll 69 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/tr/Microsoft.Data.SqlClient.resources.dll 70 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/zh-Hans/Microsoft.Data.SqlClient.resources.dll 71 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/zh-Hant/Microsoft.Data.SqlClient.resources.dll 72 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-arm64/native/Microsoft.Data.SqlClient.SNI.dll 73 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-x64/native/Microsoft.Data.SqlClient.SNI.dll 74 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-x86/native/Microsoft.Data.SqlClient.SNI.dll 75 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.dll 76 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.dll 77 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/System.Diagnostics.EventLog.dll 78 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/System.Security.Cryptography.Pkcs.dll 79 | Symbol servers used: 80 | https://symbols.nuget.org/download/symbols 81 | https://msdl.microsoft.com/download/symbols/ 82 | Symbols written: 83 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Core.pdb 84 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Identity.pdb 85 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Authorization.pdb 86 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Components.pdb 87 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Metadata.pdb 88 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.AsyncInterfaces.pdb 89 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.Cryptography.pdb 90 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Data.SqlClient.pdb 91 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Abstractions.pdb 92 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Memory.pdb 93 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyInjection.Abstractions.pdb 94 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyModel.pdb 95 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Logging.Abstractions.pdb 96 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.pdb 97 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.Extensions.Msal.pdb 98 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Abstractions.pdb 99 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.JsonWebTokens.pdb 100 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Logging.pdb 101 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.pdb 102 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb 103 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Tokens.pdb 104 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.AspNetCore.pdb 105 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.pdb 106 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Hosting.pdb 107 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Logging.pdb 108 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Settings.Configuration.pdb 109 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.File.pdb 110 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.IdentityModel.Tokens.Jwt.pdb 111 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.pdb 112 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.pdb 113 | Missing Symbols: 114 | Microsoft.Extensions.Options.pdb 115 | Microsoft.Extensions.Primitives.pdb 116 | Serilog.Formatting.Compact.pdb 117 | Serilog.Sinks.Console.pdb 118 | Serilog.Sinks.Debug.pdb 119 | System.ClientModel.pdb 120 | System.Configuration.ConfigurationManager.pdb 121 | System.Diagnostics.EventLog.pdb 122 | System.Memory.Data.pdb 123 | System.Security.Cryptography.Pkcs.pdb 124 | System.Security.Cryptography.ProtectedData.pdb 125 | Microsoft.Data.SqlClient.SNI.pdb 126 | 1>Done Building Project "{SolutionDirectory}SampleApp/SampleApp.csproj" (Publish target(s)). 127 | Build succeeded. 128 | 0 Warning(s) 129 | 0 Error(s), 130 | consoleOutput: asdas, 131 | consoleError: 132 | } -------------------------------------------------------------------------------- /src/Tests/Tests.RunTask_environmentCache=False_propertyCache=True.DotNet.verified.txt: -------------------------------------------------------------------------------- 1 | { 2 | buildOutput: 3 | 1>Project "{SolutionDirectory}SampleApp/SampleApp.csproj" on node 1 (Publish target(s)). 4 | 1>PrepareForPublish: 5 | Publish: 6 | SampleApp -> {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ 7 | CymbalTarget: 8 | PublishDir: {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ 9 | CymbalCacheDirectory environment variable: 10 | CymbalCacheDirectory MsBuild property: {SolutionDirectory}Cache 11 | Resolved CacheDirectory: {SolutionDirectory}Cache 12 | Skipped assemblies with existing pdbs: 13 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithPdb.dll 14 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.SqlServer.Server.dll 15 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/SampleApp.dll 16 | Skipped assemblies with embedded symbols: 17 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithEmbeddedSymbols.dll 18 | Assemblies to process: 19 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithNoSymbols.dll 20 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Core.dll 21 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Identity.dll 22 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Authorization.dll 23 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Components.dll 24 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Metadata.dll 25 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.AsyncInterfaces.dll 26 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.Cryptography.dll 27 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Data.SqlClient.dll 28 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Abstractions.dll 29 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Memory.dll 30 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyInjection.Abstractions.dll 31 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyModel.dll 32 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Logging.Abstractions.dll 33 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Options.dll 34 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Primitives.dll 35 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.dll 36 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.Extensions.Msal.dll 37 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Abstractions.dll 38 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.JsonWebTokens.dll 39 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Logging.dll 40 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.dll 41 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll 42 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Tokens.dll 43 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.AspNetCore.dll 44 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.dll 45 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Hosting.dll 46 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Logging.dll 47 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Formatting.Compact.dll 48 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Settings.Configuration.dll 49 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.Console.dll 50 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.Debug.dll 51 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.File.dll 52 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.ClientModel.dll 53 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Configuration.ConfigurationManager.dll 54 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Diagnostics.EventLog.dll 55 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.IdentityModel.Tokens.Jwt.dll 56 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Memory.Data.dll 57 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Security.Cryptography.Pkcs.dll 58 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Security.Cryptography.ProtectedData.dll 59 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/cs/Microsoft.Data.SqlClient.resources.dll 60 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/de/Microsoft.Data.SqlClient.resources.dll 61 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/es/Microsoft.Data.SqlClient.resources.dll 62 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/fr/Microsoft.Data.SqlClient.resources.dll 63 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/it/Microsoft.Data.SqlClient.resources.dll 64 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ja/Microsoft.Data.SqlClient.resources.dll 65 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ko/Microsoft.Data.SqlClient.resources.dll 66 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/pl/Microsoft.Data.SqlClient.resources.dll 67 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/pt-BR/Microsoft.Data.SqlClient.resources.dll 68 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ru/Microsoft.Data.SqlClient.resources.dll 69 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/tr/Microsoft.Data.SqlClient.resources.dll 70 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/zh-Hans/Microsoft.Data.SqlClient.resources.dll 71 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/zh-Hant/Microsoft.Data.SqlClient.resources.dll 72 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-arm64/native/Microsoft.Data.SqlClient.SNI.dll 73 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-x64/native/Microsoft.Data.SqlClient.SNI.dll 74 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-x86/native/Microsoft.Data.SqlClient.SNI.dll 75 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.dll 76 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.dll 77 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/System.Diagnostics.EventLog.dll 78 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/System.Security.Cryptography.Pkcs.dll 79 | Symbol servers used: 80 | https://symbols.nuget.org/download/symbols 81 | https://msdl.microsoft.com/download/symbols/ 82 | Symbols written: 83 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Core.pdb 84 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Identity.pdb 85 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Authorization.pdb 86 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Components.pdb 87 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Metadata.pdb 88 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.AsyncInterfaces.pdb 89 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.Cryptography.pdb 90 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Data.SqlClient.pdb 91 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Abstractions.pdb 92 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Memory.pdb 93 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyInjection.Abstractions.pdb 94 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyModel.pdb 95 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Logging.Abstractions.pdb 96 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.pdb 97 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.Extensions.Msal.pdb 98 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Abstractions.pdb 99 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.JsonWebTokens.pdb 100 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Logging.pdb 101 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.pdb 102 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb 103 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Tokens.pdb 104 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.AspNetCore.pdb 105 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.pdb 106 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Hosting.pdb 107 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Logging.pdb 108 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Settings.Configuration.pdb 109 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.File.pdb 110 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.IdentityModel.Tokens.Jwt.pdb 111 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.pdb 112 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.pdb 113 | Missing Symbols: 114 | Microsoft.Extensions.Options.pdb 115 | Microsoft.Extensions.Primitives.pdb 116 | Serilog.Formatting.Compact.pdb 117 | Serilog.Sinks.Console.pdb 118 | Serilog.Sinks.Debug.pdb 119 | System.ClientModel.pdb 120 | System.Configuration.ConfigurationManager.pdb 121 | System.Diagnostics.EventLog.pdb 122 | System.Memory.Data.pdb 123 | System.Security.Cryptography.Pkcs.pdb 124 | System.Security.Cryptography.ProtectedData.pdb 125 | Microsoft.Data.SqlClient.SNI.pdb 126 | 1>Done Building Project "{SolutionDirectory}SampleApp/SampleApp.csproj" (Publish target(s)). 127 | Build succeeded. 128 | 0 Warning(s) 129 | 0 Error(s), 130 | consoleOutput: asdas, 131 | consoleError: 132 | } -------------------------------------------------------------------------------- /src/Tests/Tests.RunTask_environmentCache=True_propertyCache=False.DotNet.verified.txt: -------------------------------------------------------------------------------- 1 | { 2 | buildOutput: 3 | 1>Project "{SolutionDirectory}SampleApp/SampleApp.csproj" on node 1 (Publish target(s)). 4 | 1>PrepareForPublish: 5 | Publish: 6 | SampleApp -> {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ 7 | CymbalTarget: 8 | PublishDir: {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ 9 | CymbalCacheDirectory environment variable: {SolutionDirectory}Cache 10 | CymbalCacheDirectory MsBuild property: {SolutionDirectory}Cache 11 | Resolved CacheDirectory: {SolutionDirectory}Cache 12 | Skipped assemblies with existing pdbs: 13 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithPdb.dll 14 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.SqlServer.Server.dll 15 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/SampleApp.dll 16 | Skipped assemblies with embedded symbols: 17 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithEmbeddedSymbols.dll 18 | Assemblies to process: 19 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithNoSymbols.dll 20 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Core.dll 21 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Identity.dll 22 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Authorization.dll 23 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Components.dll 24 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Metadata.dll 25 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.AsyncInterfaces.dll 26 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.Cryptography.dll 27 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Data.SqlClient.dll 28 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Abstractions.dll 29 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Memory.dll 30 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyInjection.Abstractions.dll 31 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyModel.dll 32 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Logging.Abstractions.dll 33 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Options.dll 34 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Primitives.dll 35 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.dll 36 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.Extensions.Msal.dll 37 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Abstractions.dll 38 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.JsonWebTokens.dll 39 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Logging.dll 40 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.dll 41 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll 42 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Tokens.dll 43 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.AspNetCore.dll 44 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.dll 45 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Hosting.dll 46 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Logging.dll 47 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Formatting.Compact.dll 48 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Settings.Configuration.dll 49 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.Console.dll 50 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.Debug.dll 51 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.File.dll 52 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.ClientModel.dll 53 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Configuration.ConfigurationManager.dll 54 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Diagnostics.EventLog.dll 55 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.IdentityModel.Tokens.Jwt.dll 56 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Memory.Data.dll 57 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Security.Cryptography.Pkcs.dll 58 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Security.Cryptography.ProtectedData.dll 59 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/cs/Microsoft.Data.SqlClient.resources.dll 60 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/de/Microsoft.Data.SqlClient.resources.dll 61 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/es/Microsoft.Data.SqlClient.resources.dll 62 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/fr/Microsoft.Data.SqlClient.resources.dll 63 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/it/Microsoft.Data.SqlClient.resources.dll 64 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ja/Microsoft.Data.SqlClient.resources.dll 65 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ko/Microsoft.Data.SqlClient.resources.dll 66 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/pl/Microsoft.Data.SqlClient.resources.dll 67 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/pt-BR/Microsoft.Data.SqlClient.resources.dll 68 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ru/Microsoft.Data.SqlClient.resources.dll 69 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/tr/Microsoft.Data.SqlClient.resources.dll 70 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/zh-Hans/Microsoft.Data.SqlClient.resources.dll 71 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/zh-Hant/Microsoft.Data.SqlClient.resources.dll 72 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-arm64/native/Microsoft.Data.SqlClient.SNI.dll 73 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-x64/native/Microsoft.Data.SqlClient.SNI.dll 74 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-x86/native/Microsoft.Data.SqlClient.SNI.dll 75 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.dll 76 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.dll 77 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/System.Diagnostics.EventLog.dll 78 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/System.Security.Cryptography.Pkcs.dll 79 | Symbol servers used: 80 | https://symbols.nuget.org/download/symbols 81 | https://msdl.microsoft.com/download/symbols/ 82 | Symbols written: 83 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Core.pdb 84 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Identity.pdb 85 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Authorization.pdb 86 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Components.pdb 87 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Metadata.pdb 88 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.AsyncInterfaces.pdb 89 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.Cryptography.pdb 90 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Data.SqlClient.pdb 91 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Abstractions.pdb 92 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Memory.pdb 93 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyInjection.Abstractions.pdb 94 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyModel.pdb 95 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Logging.Abstractions.pdb 96 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.pdb 97 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.Extensions.Msal.pdb 98 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Abstractions.pdb 99 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.JsonWebTokens.pdb 100 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Logging.pdb 101 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.pdb 102 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb 103 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Tokens.pdb 104 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.AspNetCore.pdb 105 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.pdb 106 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Hosting.pdb 107 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Logging.pdb 108 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Settings.Configuration.pdb 109 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.File.pdb 110 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.IdentityModel.Tokens.Jwt.pdb 111 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.pdb 112 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.pdb 113 | Missing Symbols: 114 | Microsoft.Extensions.Options.pdb 115 | Microsoft.Extensions.Primitives.pdb 116 | Serilog.Formatting.Compact.pdb 117 | Serilog.Sinks.Console.pdb 118 | Serilog.Sinks.Debug.pdb 119 | System.ClientModel.pdb 120 | System.Configuration.ConfigurationManager.pdb 121 | System.Diagnostics.EventLog.pdb 122 | System.Memory.Data.pdb 123 | System.Security.Cryptography.Pkcs.pdb 124 | System.Security.Cryptography.ProtectedData.pdb 125 | Microsoft.Data.SqlClient.SNI.pdb 126 | 1>Done Building Project "{SolutionDirectory}SampleApp/SampleApp.csproj" (Publish target(s)). 127 | Build succeeded. 128 | 0 Warning(s) 129 | 0 Error(s), 130 | consoleOutput: asdas, 131 | consoleError: 132 | } -------------------------------------------------------------------------------- /src/Tests/Tests.RunTask_environmentCache=True_propertyCache=True.DotNet.verified.txt: -------------------------------------------------------------------------------- 1 | { 2 | buildOutput: 3 | 1>Project "{SolutionDirectory}SampleApp/SampleApp.csproj" on node 1 (Publish target(s)). 4 | 1>PrepareForPublish: 5 | Publish: 6 | SampleApp -> {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ 7 | CymbalTarget: 8 | PublishDir: {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ 9 | CymbalCacheDirectory environment variable: {SolutionDirectory}Cache 10 | CymbalCacheDirectory MsBuild property: {SolutionDirectory}Cache 11 | Resolved CacheDirectory: {SolutionDirectory}Cache 12 | Skipped assemblies with existing pdbs: 13 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithPdb.dll 14 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.SqlServer.Server.dll 15 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/SampleApp.dll 16 | Skipped assemblies with embedded symbols: 17 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithEmbeddedSymbols.dll 18 | Assemblies to process: 19 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/AssemblyWithNoSymbols.dll 20 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Core.dll 21 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Identity.dll 22 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Authorization.dll 23 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Components.dll 24 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Metadata.dll 25 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.AsyncInterfaces.dll 26 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.Cryptography.dll 27 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Data.SqlClient.dll 28 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Abstractions.dll 29 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Memory.dll 30 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyInjection.Abstractions.dll 31 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyModel.dll 32 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Logging.Abstractions.dll 33 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Options.dll 34 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Primitives.dll 35 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.dll 36 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.Extensions.Msal.dll 37 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Abstractions.dll 38 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.JsonWebTokens.dll 39 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Logging.dll 40 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.dll 41 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll 42 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Tokens.dll 43 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.AspNetCore.dll 44 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.dll 45 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Hosting.dll 46 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Logging.dll 47 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Formatting.Compact.dll 48 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Settings.Configuration.dll 49 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.Console.dll 50 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.Debug.dll 51 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.File.dll 52 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.ClientModel.dll 53 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Configuration.ConfigurationManager.dll 54 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Diagnostics.EventLog.dll 55 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.IdentityModel.Tokens.Jwt.dll 56 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Memory.Data.dll 57 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Security.Cryptography.Pkcs.dll 58 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.Security.Cryptography.ProtectedData.dll 59 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/cs/Microsoft.Data.SqlClient.resources.dll 60 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/de/Microsoft.Data.SqlClient.resources.dll 61 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/es/Microsoft.Data.SqlClient.resources.dll 62 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/fr/Microsoft.Data.SqlClient.resources.dll 63 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/it/Microsoft.Data.SqlClient.resources.dll 64 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ja/Microsoft.Data.SqlClient.resources.dll 65 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ko/Microsoft.Data.SqlClient.resources.dll 66 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/pl/Microsoft.Data.SqlClient.resources.dll 67 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/pt-BR/Microsoft.Data.SqlClient.resources.dll 68 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/ru/Microsoft.Data.SqlClient.resources.dll 69 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/tr/Microsoft.Data.SqlClient.resources.dll 70 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/zh-Hans/Microsoft.Data.SqlClient.resources.dll 71 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/zh-Hant/Microsoft.Data.SqlClient.resources.dll 72 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-arm64/native/Microsoft.Data.SqlClient.SNI.dll 73 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-x64/native/Microsoft.Data.SqlClient.SNI.dll 74 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win-x86/native/Microsoft.Data.SqlClient.SNI.dll 75 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.dll 76 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.dll 77 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/System.Diagnostics.EventLog.dll 78 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/System.Security.Cryptography.Pkcs.dll 79 | Symbol servers used: 80 | https://symbols.nuget.org/download/symbols 81 | https://msdl.microsoft.com/download/symbols/ 82 | Symbols written: 83 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Core.pdb 84 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Azure.Identity.pdb 85 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Authorization.pdb 86 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Components.pdb 87 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.AspNetCore.Metadata.pdb 88 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.AsyncInterfaces.pdb 89 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Bcl.Cryptography.pdb 90 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Data.SqlClient.pdb 91 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Abstractions.pdb 92 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Caching.Memory.pdb 93 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyInjection.Abstractions.pdb 94 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.DependencyModel.pdb 95 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Extensions.Logging.Abstractions.pdb 96 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.pdb 97 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.Identity.Client.Extensions.Msal.pdb 98 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Abstractions.pdb 99 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.JsonWebTokens.pdb 100 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Logging.pdb 101 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.pdb 102 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb 103 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Microsoft.IdentityModel.Tokens.pdb 104 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.AspNetCore.pdb 105 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.pdb 106 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Hosting.pdb 107 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Extensions.Logging.pdb 108 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Settings.Configuration.pdb 109 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/Serilog.Sinks.File.pdb 110 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/System.IdentityModel.Tokens.Jwt.pdb 111 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.pdb 112 | {SolutionDirectory}SampleApp/bin/IncludeTask/publish/runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.pdb 113 | Missing Symbols: 114 | Microsoft.Extensions.Options.pdb 115 | Microsoft.Extensions.Primitives.pdb 116 | Serilog.Formatting.Compact.pdb 117 | Serilog.Sinks.Console.pdb 118 | Serilog.Sinks.Debug.pdb 119 | System.ClientModel.pdb 120 | System.Configuration.ConfigurationManager.pdb 121 | System.Diagnostics.EventLog.pdb 122 | System.Memory.Data.pdb 123 | System.Security.Cryptography.Pkcs.pdb 124 | System.Security.Cryptography.ProtectedData.pdb 125 | Microsoft.Data.SqlClient.SNI.pdb 126 | 1>Done Building Project "{SolutionDirectory}SampleApp/SampleApp.csproj" (Publish target(s)). 127 | Build succeeded. 128 | 0 Warning(s) 129 | 0 Error(s), 130 | consoleOutput: asdas, 131 | consoleError: 132 | } -------------------------------------------------------------------------------- /src/Tests/Tests.Should_Parse_SymbolServer.verified.txt: -------------------------------------------------------------------------------- 1 | { 2 | buildOutput: 3 | 1>Project "{SolutionDirectory}SampleWithSymbolServer/SampleWithSymbolServer.csproj" on node 1 (Publish target(s)). 4 | 1>PrepareForPublish: 5 | Publish: 6 | SampleWithSymbolServer -> {SolutionDirectory}SampleWithSymbolServer/bin/IncludeTask/publish/ 7 | CymbalTarget: 8 | PublishDir: {SolutionDirectory}SampleWithSymbolServer/bin/IncludeTask/publish/ 9 | CymbalCacheDirectory environment variable: 10 | CymbalCacheDirectory MsBuild property: 11 | Resolved CacheDirectory: 12 | Skipped assemblies with existing pdbs: 13 | {SolutionDirectory}SampleWithSymbolServer/bin/IncludeTask/publish/SampleWithSymbolServer.dll 14 | Assemblies to process: 15 | {SolutionDirectory}SampleWithSymbolServer/bin/IncludeTask/publish/AssemblyWithNoSymbols.dll 16 | Symbol servers used: 17 | http://localhost:88/symbols 18 | http://localhost:89/symbols 19 | 1>Done Building Project "{SolutionDirectory}SampleWithSymbolServer/SampleWithSymbolServer.csproj" (Publish target(s)). 20 | Build succeeded. 21 | 0 Warning(s) 22 | 0 Error(s), 23 | consoleOutput: Hello, World!, 24 | consoleError: 25 | } -------------------------------------------------------------------------------- /src/Tests/Tests.cs: -------------------------------------------------------------------------------- 1 | using CliWrap; 2 | using CliWrap.Buffered; 3 | using DiffEngine; 4 | 5 | public class Tests : IAsyncDisposable 6 | { 7 | static string solutionDir; 8 | static string cacheDirectory; 9 | 10 | static Tests() 11 | { 12 | solutionDir = AttributeReader.GetSolutionDirectory(); 13 | cacheDirectory = Path.Combine(solutionDir, "Cache"); 14 | if (Directory.Exists(cacheDirectory)) 15 | { 16 | Directory.Delete(cacheDirectory, true); 17 | } 18 | } 19 | 20 | [Test] 21 | public void HasEmbedded() 22 | { 23 | True(SymbolChecker.HasEmbedded(typeof(Tests).Assembly.Location)); 24 | False(SymbolChecker.HasEmbedded(typeof(object).Assembly.Location)); 25 | } 26 | 27 | [Test] 28 | public async Task RunTask([Values] bool environmentCache, [Values] bool propertyCache) 29 | { 30 | var sampleAppPath = Path.Combine(solutionDir, "SampleApp"); 31 | var includeTaskDir = Path.Combine(sampleAppPath, @"bin\IncludeTask"); 32 | if (Directory.Exists(includeTaskDir)) 33 | { 34 | Directory.Delete(includeTaskDir, true); 35 | } 36 | 37 | await RunDotnet("build --configuration IncludeTask --no-incremental"); 38 | 39 | var environmentVariables = new Dictionary(); 40 | if (environmentCache) 41 | { 42 | environmentVariables.Add("CymbalCacheDirectory", cacheDirectory); 43 | } 44 | 45 | var arguments = "publish --configuration IncludeTask --no-build --no-restore --verbosity normal"; 46 | if (propertyCache) 47 | { 48 | arguments += $" -p:CymbalCacheDirectory={cacheDirectory}"; 49 | } 50 | 51 | var publishResult = await Cli.Wrap("dotnet") 52 | .WithArguments(arguments) 53 | .WithWorkingDirectory(sampleAppPath) 54 | .WithValidation(CommandResultValidation.None) 55 | .WithEnvironmentVariables(environmentVariables) 56 | .ExecuteBufferedAsync(); 57 | 58 | var publishError = publishResult.StandardError; 59 | if (publishError.Length > 0) 60 | { 61 | throw new(publishError); 62 | } 63 | 64 | var publishOutput = publishResult.StandardOutput; 65 | if (publishOutput.Contains("error")) 66 | { 67 | throw new(publishOutput.Replace(solutionDir, "")); 68 | } 69 | 70 | var appPath = Path.Combine(solutionDir, "SampleApp/bin/IncludeTask/SampleApp.dll"); 71 | var runResult = await RunDotnet(appPath); 72 | 73 | await Verify( 74 | new 75 | { 76 | buildOutput = publishOutput, 77 | consoleOutput = runResult.StandardOutput, 78 | consoleError = runResult.StandardError 79 | }) 80 | .UseParameters(environmentCache, propertyCache) 81 | .UniqueForRuntime(); 82 | } 83 | 84 | [Test] 85 | public async Task Should_Parse_SymbolServer() 86 | { 87 | var sampleAppPath = Path.Combine(solutionDir, "SampleWithSymbolServer"); 88 | var includeTaskDir = Path.Combine(sampleAppPath, @"bin\IncludeTask"); 89 | if (Directory.Exists(includeTaskDir)) 90 | { 91 | Directory.Delete(includeTaskDir, true); 92 | } 93 | 94 | await RunDotnet("build --configuration IncludeTask --no-incremental"); 95 | 96 | var arguments = "publish --configuration IncludeTask --no-build --no-restore --verbosity normal"; 97 | 98 | var publishResult = await Cli.Wrap("dotnet") 99 | .WithArguments(arguments) 100 | .WithWorkingDirectory(sampleAppPath) 101 | .WithValidation(CommandResultValidation.None) 102 | .ExecuteBufferedAsync(); 103 | 104 | if (publishResult.StandardError.Length > 0) 105 | { 106 | throw new(publishResult.StandardError); 107 | } 108 | 109 | if (publishResult.StandardOutput.Contains("error")) 110 | { 111 | throw new(publishResult.StandardOutput.Replace(solutionDir, "")); 112 | } 113 | 114 | var appPath = Path.Combine(solutionDir, "SampleWithSymbolServer/bin/IncludeTask/SampleWithSymbolServer.dll"); 115 | var runResult = await RunDotnet(appPath); 116 | 117 | await Verify( 118 | new 119 | { 120 | buildOutput = publishResult.StandardOutput, 121 | consoleOutput = runResult.StandardOutput, 122 | consoleError = runResult.StandardError 123 | }); 124 | } 125 | 126 | static Task RunDotnet(string arguments) => 127 | Cli.Wrap("dotnet") 128 | .WithArguments(arguments) 129 | .WithWorkingDirectory(solutionDir) 130 | .WithValidation(CommandResultValidation.None) 131 | .ExecuteBufferedAsync(); 132 | 133 | public ValueTask DisposeAsync() 134 | { 135 | if (BuildServerDetector.Detected) 136 | { 137 | return ValueTask.CompletedTask; 138 | } 139 | 140 | return new(RunDotnet("build-server shutdown")); 141 | } 142 | } -------------------------------------------------------------------------------- /src/Tests/Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net9.0 4 | Exe 5 | $(NoWarn);xUnit1051 6 | testing 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/appveyor.yml: -------------------------------------------------------------------------------- 1 | image: 2 | - Visual Studio 2022 3 | #- macOS 4 | #- Ubuntu 5 | environment: 6 | DOTNET_NOLOGO: true 7 | DOTNET_CLI_TELEMETRY_OPTOUT: true 8 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 9 | before_build: 10 | - pwsh: | 11 | if ($isWindows) { 12 | Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile "./dotnet-install.ps1" 13 | ./dotnet-install.ps1 -JSonFile src/global.json -Architecture x64 -InstallDir 'C:\Program Files\dotnet' 14 | } 15 | else { 16 | Invoke-WebRequest "https://dot.net/v1/dotnet-install.sh" -OutFile "./dotnet-install.sh" 17 | sudo chmod u+x dotnet-install.sh 18 | if ($isMacOS) { 19 | sudo ./dotnet-install.sh --jsonfile src/global.json --architecture x64 --install-dir '/usr/local/share/dotnet' 20 | } else { 21 | sudo ./dotnet-install.sh --jsonfile src/global.json --architecture x64 --install-dir '/usr/share/dotnet' 22 | } 23 | } 24 | dotnet tool restore --tool-manifest src/.config/dotnet-tools.json 25 | build_script: 26 | - dotnet build src --configuration Release 27 | - dotnet test src --configuration Release --no-build --no-restore 28 | test: off 29 | artifacts: 30 | - path: nugets\*.nupkg 31 | on_finish: 32 | - ps: Get-ChildItem *.received.* -recurse | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } 33 | -------------------------------------------------------------------------------- /src/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "9.0.300", 4 | "allowPrerelease": true, 5 | "rollForward": "latestFeature" 6 | } 7 | } -------------------------------------------------------------------------------- /src/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonCropp/Cymbal/eec29b45e8fde8b0e0db7c13967e1c22de815a65/src/icon.png -------------------------------------------------------------------------------- /src/key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonCropp/Cymbal/eec29b45e8fde8b0e0db7c13967e1c22de815a65/src/key.snk -------------------------------------------------------------------------------- /src/mdsnippets.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/SimonCropp/MarkdownSnippets/master/schema.json", 3 | "TocExcludes": [ "Release Notes", "Icon" ], 4 | "MaxWidth": 120, 5 | "ValidateContent": true, 6 | "Convention": "InPlaceOverwrite" 7 | } -------------------------------------------------------------------------------- /src/nuget.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 20 | 21 | 24 | 25 | 26 | --------------------------------------------------------------------------------