c# - module documentation - XML documentation file - c#

I am studying C# in my HDN school with Visual Studio.
In Windows there is a way to generate automaticaly the technical documentation from modules by going through Project > Properties and by clicking on "XML documentation file".
On Visual Studio for Mac I do not see this functionality.
May someone help me ? Does it exist or should I write manually the /// up to the module ?

You can also add a configuration to the .csproj so the documentation file gets generated with each build. Follow this SO:
https://stackoverflow.com/a/47118584/4122889
Add this code to you .csproj file
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
Or create a Directory.Build.Props file in the root of your repo and add this:
<Project>
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
</Project>
More info on Directory.Build.Props (or .Targets):
https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2019

Related

C# Roslyn Analyzer via ProjectReference leads to not found error after opening Visual Studio

I've written an Roslyn Analyzer for a specific C# Solution and want to add the analyer to all projects in the solution via ProjectReference:
<Project>
<PropertyGroup>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="(MSBuildProjectDirectory)\..\..\..\CodeAnalyzers\CodeAnalyzers\CodeAnalyzers.csproj"
ReferenceOutputAssembly="false"
OutputItemType="Analyzer" />
</ItemGroup>
</Project>
I placed this inside the Directory.Build.props file.
The Analyzer works, as long as I manually build the analyzer project before building the solution. If I don't do that I get the following warning for each project:
Warning CS8034 Unable to load Analyzer assembly C:\Users\xxx\source\repos\XYZ\CodeAnalyzers\CodeAnalyzers\bin\Debug\netstandard1.3\CodeAnalyzers.dll: Could not find file 'C:\Users\xxx\source\repos\XYZ\CodeAnalyzers\CodeAnalyzers\bin\Debug\netstandard1.3\CodeAnalyzers.dll'.
System.IO.FileNotFoundException: Could not find file 'C:\Users\xxx\source\repos\XYZ\CodeAnalyzers\CodeAnalyzers\bin\Debug\netstandard1.3\CodeAnalyzers.dll'.
File name: 'C:\Users\xxx\source\repos\XYZ\CodeAnalyzers\CodeAnalyzers\bin\Debug\netstandard1.3\CodeAnalyzers.dll'
How do I tell Visual Studio to first build the analyzer project, before trying to load the dll? Building afterwards doesn't clear the issue, I suppose because of caching.
In the Project Build Order - dialog the analyzer project is at the top and in configuration manager the checkbox for build is set.
It seems that you have analyzer project in the same solution as your specific C# Solution.
More straightforward approach would be to create Nuget package from your separate analyzer solution (use template in VS "Analyzer with Code Fix (.NET Standard)") and then use PackageReference to include your analyzer in your solution.
For instance, put in props file or in the csproj file something like:
<ItemGroup>
<PackageReference Include="YourCustomAnalyzerId" Version="x.x.x" />
</ItemGroup>
and you will get analyzer in all you projects working just fine. Then your analyzer will be listed in Dependencies/Analyzers.

Cannot load symbols from SDK style C# library while running MVC project

I have a library that is shared between .NET Core 3.1 and .NET Framework 4.7.2. I have found that when I run the .NET Core 3.1 Azure Function I can debug the library code, but when running the MVC app I cannot. Also, if I try to use intellisense to navigate to definitions within the library it will not take me to the code, but to the meta-data.
I've added a "full" debug type specifier to the top of the Library's csproj file like this and that does not help:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<DebugType>full</DebugType>
</PropertyGroup>
I have other similar libraries that do not have this issue and have tried copying over some config attributes, but nothing seems to help. How might this be fixed?
I am using the latest version of VS 2019 and I have noticed that the PDB file size has increased since making the DebugType full. If I try to load the symbols manually using the Modules window it tells me a debug file of the correct type cannot be found.
It turns out I had to sign the assembly or give it a guid for my Framework app to navigate into it, or debug it. The csproj looks like this now at the top:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{<some guid>}</ProjectGuid>
<TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<DebugType>full</DebugType>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile><some snk file name>.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
The old options to have VS generate the strong signing stuff for you can still be accessed in VS by right-clicking on the project and selecting Properties.

Adding reference to another executable with ReferenceOutputAssembly=false doesn't copy dependencies

I have a solution with several executables in it (say, MainApp.exe and Tool.exe).
The main goal is to ensure that the tool (Tool.exe) with its dependencies is copied to the main executable directory during build.
I used the advice from here, and it seemed to work with the older Visual Studio version (at least with some version prior to 16.8).
My project structure (simplified) looks like this:
Solution.sln
├ MainApp.csproj
├ Tool.csproj
| └ App.config
└ ToolLib.csproj
Tool project contains App.config file, and references ToolLib project.
My MainApp.csproj looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../Tool/Tool.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Targets>Build;DebugSymbolsProjectOutputGroup</Targets>
</ProjectReference>
</ItemGroup>
</Project>
After upgrading to 16.8 after the compilation the file Tool.exe was indeed copied to the output directory, but neither its dependency ToolLib.dll nor Tool.config was copied to the output directory any more.
Is this a bug or intended behaviour? What is the proper way to ensure that the whole Tool with all the needed dependencies is copied to the MainApp's output dir?
Added test project reproducing the problem here: https://github.com/vladd/ReferenceOutputAssembly
What you gave is too old and it is not suitable for VS2019. And all your projects target to net core 3.1. I have tested your project both in VS2019 16.8 , VS2019 16.7, even 16.6 which all act the same behavior as you described. Only contain the Tool.dll and Tool.exe.
So I wonder why you said before that the result of the build of ToolLib will be printed in the main project.
Actually, <ReferenceOutputAssembly>false</ReferenceOutputAssembly> will prevent the most main output files of the referenced project and its dependency project being copied into the main project.
Suggestion
You have to set it as true:
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
If you want to not copy ToolLib.pdb and Tool.pdb files into the main project, you could add these node on MainApp.csproj file:
<PropertyGroup>
<AllowedReferenceRelatedFileExtensions>*.pdb;.dll.config</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>
If you also want to copy pdb files, you should add .pdb under AllowedReferenceRelatedFileExtensions.
<AllowedReferenceRelatedFileExtensions>.pdb;.dll.config</AllowedReferenceRelatedFileExtensions>
Update 1
I tried your suggestion but with it the files Tools.deps,json and
Tool.runtimeconfig.json are not copied, so running the tool fails.
Add this on MainApp.csproj file:
<PropertyGroup>
<AllowedReferenceRelatedFileExtensions>.pdb;.dll.config;.runtimeconfig.dev.json;.runtimeconfig.json</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>

Visual studio How to set output path dependant of assembly version

I want to configure my main output path to something like
C:\Company\UpdaterLauncher\Worker\Version
Where version is my AssemblyInfo.Version in string.
So a new folder each time I decide to change the assembly version.
I know I can change output all time.. But it's annoying.
Is this possible to use something like "C:\Company\UpdaterLauncher\Worker\{AssemblyVersion}" for visual output path to interprete it and build where I want?
I looked a bit in documentation and didn't found anything like this...
Which way do you build the project? By msbuild command-line or within VS IDE?
First direction: Let's read the assembly version number before the build starts, then
pass it to outputpath property.
I've written a script trying to read the version before the build starts. But not completely work:(
E.g: Using a class library project as the example.
Right-click the project and choose edit the xx.csproj, add the script (From In property to FourthNum property) into the PropertyGroup:
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DAB28A16-73AD-4EC5-9F8D-E58CE3EC84BE}</ProjectGuid>
......
<In>$([System.IO.File]::ReadAllText('$(MSBuildProjectDirectory)\properties\AssemblyInfo.cs'))</In>
<Pattern>\[assembly: AssemblyVersion\(.(\d+)\.(\d+)\.(\d+).(\d+)</Pattern>
<FirstNum>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern),System.Text.RegularExpressions.RegexOptions.Multiline).Groups[1].Value)</FirstNum>
<SecondNum>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern),System.Text.RegularExpressions.RegexOptions.Multiline).Groups[2].Value)</SecondNum>
<ThirdNum>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern),System.Text.RegularExpressions.RegexOptions.Multiline).Groups[3].Value)</ThirdNum>
<FourthNum>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern),System.Text.RegularExpressions.RegexOptions.Multiline).Groups[4].Value)</FourthNum>
</PropertyGroup>
It will read the assembly version number from AssemblyInfo.cs. If I have an assembly whose assembly version is 3.13.8.5. Then the FirstNum=3, SecondNum=13 ...
And set the outputpath as: <OutputPath>C:\Company\UpdaterLauncher\Worker\$(FirstNum).$(SecondNum).$(ThirdNum).$(FourthNum)</OutputPath>
Reload the project and build it. You can find the build output there C:\Company\UpdaterLauncher\Worker\3.13.8.5.
Note:
1.In this way, since we will build it in both debug and release mode. We need to set the outputpath value in both propertygroup for debug and release.(2 places)
2.Since we only define the output depending on version, the debug output and release will all locates in same folder. So I think the <OutputPath> would be better like:
<OutputPath>C:\Company\UpdaterLauncher\Worker\$(FirstNum).$(SecondNum).$(ThirdNum).$(FourthNum)\$(Configuration)</OutputPath>
3.This script won't work immediately after you change the version in VS IDE.
Via Command-line: It works well, every time we change the version number and build it, the output is correct.
Within VS IDE: Every time after we change the version, it needs us to unload and reload the project file by right-clicking the project, then it will work. So I say it isn't that perfect.(I would think this issue has something to do with when and how the VS loads the project file)
Second Direction: The build output actually is copy the related
assemblies to output folder. So we can copy or move the output content
to the directory after the build we want by copy or move task.
We can check this issue, using GetAssemblyIdentity to get the info after the build.
Using the way above to get version number, name it $(MyVersion). Then use a after-build target to copy the output to the specified folder.
<Target Name="CopyToSpecificFolder" AfterTargets="build">
<GetAssemblyIdentity
AssemblyFiles="$(OutputPath)$(AssemblyName).dll">
<Output
TaskParameter="Assemblies"
ItemName="MyAssemblyIdentities"/>
</GetAssemblyIdentity>
<PropertyGroup>
<MyVersion>%(MyAssemblyIdentities.Version)</MyVersion>
</PropertyGroup>
<ItemGroup>
<Out Include="$(OutputPath)*.*" />
</ItemGroup>
<Copy DestinationFolder="C:\Company\UpdaterLauncher\Worker\$(MyVersion)" SourceFiles="#(Out)"/>
</Target>
Add this script into the xx.csproj file. In the bottom of it like:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
......
<Target Name="CopyToSpecificFolder" AfterTargets="build">
......
</Target>
</Project>
It works well in whether VS IDE or by command-line. And it's for class project, if you're developing a .exe project, change the $(AssemblyName).dll to $(AssemblyName).exe.

Code Analysis is not working with ruleset from nuget package (from .props)

I'm trying to use custom ruleset file form our nuget package. I've added to the build folder of the package .props file:
<Project>
<PropertyGroup>
<CodeAnalysisRuleSet>
$(MSBuildThisFileDirectory)..\My.Shared.ruleset
</CodeAnalysisRuleSet>
<RunCodeAnalysis>true</RunCodeAnalysis>
</PropertyGroup>
</Project>
Rule set file is in the package root folder, the paths are correct, it's adding import of the .props file into csproj file.
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\My.Shared.Rulesets.1.0.0.7118\build\My.Shared.Rulesets.props" Condition="Exists('..\packages\My.Shared.Rulesets.1.0.0.7118\build\My.Shared.Rulesets.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
...
But Visual Studio is not seeing correct rule set. When I open active rule set from References -> Analyzers, it's pointing to different file: MinimumRecommendedRules.ruleset and it's using rules from this file not my custom one.
Visual Studio Comunity 2017 Version 15.5.0
Project Target framework 4.6.1
Code Analysis is not working with ruleset from nuget package (from .props)
You should set the Rule set file in the content folder in the package folder, so that VS/MSBuild will add this file to your project, then VS\MSBuild could change the default MinimumRecommendedRules.ruleset to your My.Shared.ruleset.ruleset file.
For example, your NuGet source folder structure might look like this ("My.Shared.ruleset" is your package ID):
build
My.Shared.ruleset.props
content
My.Shared.ruleset.ruleset
where the contents of My.Shared.ruleset.props are something like the following:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<RunCodeAnalysis>true</RunCodeAnalysis>
<CodeAnalysisRuleSet>My.Shared.Rulesets.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
</Project>
Step to create nuget package:
Open NuGet Package Explorer, select new a package, Edit->Edit
Metadata, change Id to My.Shared.Rulesets->Save.
Content->Add->Content Folder->Add Existing file->Select your My.Shared.Rulesets.ruleset
Content->Add->Build Folder->Add Existing file->Select your My.Shared.ruleset.props->Save.
Then add this package to the test project:
Then you will find the active ruleset was changed to the one from nuget package.
Update for comment:
We were trying to avoid copying ruleset file to each project. Developers tend to change it and push to repository
If you do not want to copy ruleset file to each project, you just need to change the path in the .props file, but you should make sure the path is correct in the .props file, for example. I set the .ruleset file in the local path: D:\ShareFolder\My.Shared.Rulesets.ruleset, then move the .ruleset from the nuget package and change the path to D:\ShareFolder\My.Shared.Rulesets.ruleset in the .props.
Hope this helps.

Categories