How to convert a ruleset file into a FXCop rules dll? - msbuild

Am trying to configure the static code analysis(FxCop) in my Continuous integration system.But my developers are using a rule set file for static analysis with Visual Studio.
Is there a way that i can re-use the same rule-set file and convert it into a FxCop rule-set dll and perform the static code analysis while build?
Thanks in advance,
Ravi

If you have Visual Studio installed on the CI server, then simply specifying /p:RunCodeAnalysis=[True|False|Always|Default|Never] on the MsBuild command line should run Code Analysis as it was configured on the developer's configuration. The rules files are automatically included in the Visual Studio project file, so they should resolve on their own.
To run FxCop after the build you can specify the ruleset as a commandline parameter:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Team Tools\Static Analysis Tools\FxCop>fxcopcmd /?
Microsoft (R) FxCop Command-Line Tool, Version 12.0 (12.0.21005.1) X86
Copyright (C) Microsoft Corporation, All Rights Reserved.
/ruleset:<<+|-|=>file> [Short form: /rs:<<+|-|=>file>]
Rule set to be used for the analysis. It can be a file path to the rule set
file or the file name of a built-in rule set. '+' enables all rules in the
rule set; '-' disables all rules in the rule set; '=' sets rules to match the
rule set and disables all rules that are not enabled in the rule set.
/rulesetdirectory:<directory> [Short form: /rsd:<directory>]
Directory to search for rule set files that are specified by the /ruleset
switch or are included by one of the specified rule sets.
The difficult part of running FxCop from the commandline is that you will want to pass all references and that it can only process files targeting the same .NET system libraries (it can only hold one of those in memory). You can specify these references using the following parameters:
/platform:<directory> [Short form: /plat:<directory>]
Location of platform assemblies.
/directory:<directory> [Short form: /d:<directory>]
Location to search for assembly dependencies.
/reference:<file> [Short form: /ref:<file>]
Reference assemblies required for analysis.

If you want to run code analysis only without having to call fxcop directly and specify all that extra information, do the following:
<MSBuild Projects="#(CodeAnalysisProjects)" Properties="RunCodeAnalysis=True;Configuration=Release;BuildProjectReferences=False;WarningsAsErrors=False;RunCodeAnalysisDependsOn=;" Targets="RunCodeAnalysis" StopOnFirstFailure="false" />
You send in the list of projects in the itemgroup CodeAnalysisProjects. You run the target RunCodeAnalysis and you set the property RunCodeAnalysis=True. You also set the property RunCodeAnalysisDependsOn=; so that nothing else runs besides code analysis.
This is the same solution we use for our CI. We build all day and then run code analysis only at night.

Related

TFS Build 2013 avoid code analysis

How can I avoid code analysis running on TFS Builds at a solution level?
I understand I can do this at a project level, but there are over 200 projects in my C# solution and I'd like to switch off Code Analysis at solution level if its possible.
I still need to run code analysis on developers machines.
I want to save time by not running code analysis on a specific TFS Build (we use SonarQube for CodeAnalysis on a separate build pipeline and so we don't need TFS Build to do it's own Code Analysis)
I have tried the following in my MSBuild arguments :
/p:RunCodeAnalysis=false
/p:RunCodeAnalysis=Never
(This is using the default TfcvTemplate.12.xaml)
But even with these changes I can still see from the build logs that Code Analysis is still occuring:
csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:TRACE /highentropyva+
/debug:pdbonly /optimize+ /out:obj\Release\xyx.dll
/ruleset:"..\Rule Sets\MinimumRecommendedRules.ruleset"
/subsystemversion:6.00 /target:library /utf8output
xyz.cs
The full MSBuild arguments I use are:
/m /tv:14.0 /p:RunCodeAnalysis=false /p:GenerateProjectSpecificOutputFolder=True
I'm using Tools Version 14 coupled with Microsoft.Compilers NuGet package to allow C#6 on our TFS 2013 Build Server.
Is there a way to avoid running code analysis at solution level, using just the MSBuild args in a TFS2013 build definition?
The RunCodeAnalysis property is used by the old style FxCop static binary analyzers. The new Roslyn Analyzers do not follow this setting.
There are two options...
You can create a Directory.Build.targets1 file in the root folder of your solution (you can create it during build if needed) and remove the analyzers just before the compiler is invoked:
<Target Name="DisableAnalyzersForBuild"
BeforeTargets="CoreCompile"
Condition="'$(TF_BUILD)'=='True'">
<ItemGroup>
<Analyzer Remove="#(Analyzer)"/>
</ItemGroup>
</Target>
You can include the TF_BUILD check to detect that you're inside a Team Build run.
You can also create a ruleset file that disables all rules and override that as part of the build:
/p:CodeAnalysisRuleSet=AllDisabled.ruleset
1) Not sure if this works with the Nuget compiler extensions.

Where to put Rule Sets for MSBuild 15 (Build Tools for Visual Studio 2017)

When enabling Static Code Analysis on my builds, I get the following error thrown by MSBuild:
C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\Microsoft.CSharp.CurrentVersion.targets(134,9): warning MSB3884: Could not find rule set file "AllRules.ruleset". [C:\Program Files\VSTS Agent_work\PATH_TO_MY.csproj]
To get Static Code Analysis working on build agents (only MSBuild, no Visual Studio), for older versions of the build tools one would:
Copy C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\Rule Sets\ to the build server
Add a registry entry pointing to that folder
(see also this bug report)
However, these instructions doesn't work with "Build Tools for Visual Studio 2017". I'd like to know how I resolve this, without needing to copy the rulesets into my own repository or changing anything in my csproj?
Update:
I've tried setting the following registry key, to no avail:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\15.0\Setup\EDev]
"StanDir"="C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\Team Tools\\Static Analysis Tools"
Digging through the registry, I've found that the following registry keys. On my machine I've installed both VS2017 Build Tools and Test Agent, and it seems like this points to the latter, which I have installed after installed Build Tools:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7]
"15.0"="C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\TestAgent\\"
"14.0"="C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\"
Update 2:
Both answers mention the file Microsoft.CodeAnalysis.Targets. However this file is not present on my build server. I've tried copying this folder over from my VS2017 installation:
from: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\Microsoft\VisualStudio\v15.0\CodeAnalysis
to: C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\Microsoft\VisualStudio\v15.0\CodeAnalysis
However besides the rulesets not being found, it now also throws errors about being unable to find Microsoft.WebApplication.targets:
XXX.csproj(296,11): error MSB4226: The imported project "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuil
d\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" was not found. Also, tried to find "WebApplications\Microsoft.WebApplication.targets" in the fallback search path(s) for $(VSToo
lsPath) - "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v15.0" . These search paths are defined in "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe.Config".
Confirm that the path in the declaration is correct, and that the file exists on disk in one of the search paths.
Update:
Based on my test, you don't need to change anything manually, just need to install the default components of Build Tools for VS2017, then the necessary files will be added automatically.
Old:
Regarding default folder of code analysis files, you can check Microsoft.CodeAnalysis.targets file:
<PropertyGroup>
<CodeAnalysisStaticAnalysisDirectory Condition="'$(CodeAnalysisStaticAnalysisDirectory)'=='' and Exists('$(VsInstallRoot)\Team Tools\Static Analysis Tools\')">$(VsInstallRoot)\Team Tools\Static Analysis Tools\</CodeAnalysisStaticAnalysisDirectory>
<CodeAnalysisStaticAnalysisDirectory Condition="'$(CodeAnalysisStaticAnalysisDirectory)'==''">$(Registry:HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\15.0\Setup\EDev#StanDir)</CodeAnalysisStaticAnalysisDirectory>
<!-- If we didn't find the first registry path, assume we're in a 64bit process. -->
<!-- read registry from Wow6432Node -->
<CodeAnalysisStaticAnalysisDirectory Condition="'$(CodeAnalysisStaticAnalysisDirectory)'==''">$(Registry:HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\15.0\Setup\EDev#StanDir)</CodeAnalysisStaticAnalysisDirectory>
<!-- if we didn't find the registry path yet, then try Win8 Express location -->
<CodeAnalysisStaticAnalysisDirectory Condition="'$(CodeAnalysisStaticAnalysisDirectory)'==''">$(Registry:HKEY_LOCAL_MACHINE\Software\Microsoft\VSWinExpress\15.0\Setup\EDev#StanDir)</CodeAnalysisStaticAnalysisDirectory>
<!-- If we didn't find the registry path yet, then try Win8 Express 64-bit location -->
<CodeAnalysisStaticAnalysisDirectory Condition="'$(CodeAnalysisStaticAnalysisDirectory)'==''">$(Registry:HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VSWinExpress\15.0\Setup\EDev#StanDir)</CodeAnalysisStaticAnalysisDirectory>
<!-- If we didn't find the registry path yet, try WP Express locations -->
<CodeAnalysisStaticAnalysisDirectory Condition="'$(CodeAnalysisStaticAnalysisDirectory)'==''">$(Registry:HKEY_LOCAL_MACHINE\Software\Microsoft\VPDExpress\15.0\Setup\EDev#StanDir)</CodeAnalysisStaticAnalysisDirectory>
<!-- If we didn't find the registry path yet, try WP Express 64-bit locations -->
<CodeAnalysisStaticAnalysisDirectory Condition="'$(CodeAnalysisStaticAnalysisDirectory)'==''">$(Registry:HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VPDExpress\15.0\Setup\EDev#StanDir)</CodeAnalysisStaticAnalysisDirectory>
<!-- If we didn't find the registry path yet, try WD Express locations -->
<CodeAnalysisStaticAnalysisDirectory Condition="'$(CodeAnalysisStaticAnalysisDirectory)'==''">$(Registry:HKEY_LOCAL_MACHINE\Software\Microsoft\WDExpress\15.0\Setup\EDev#StanDir)</CodeAnalysisStaticAnalysisDirectory>
<!-- If we didn't find the registry path yet, try WD Express 64-bit locations -->
<CodeAnalysisStaticAnalysisDirectory Condition="'$(CodeAnalysisStaticAnalysisDirectory)'==''">$(Registry:HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\WDExpress\15.0\Setup\EDev#StanDir)</CodeAnalysisStaticAnalysisDirectory>
<!-- Default rule set search paths -->
<CodeAnalysisRuleSetDirectories Condition=
"'$(CodeAnalysisIgnoreBuiltInRuleSets)'!='true' and
'$(CodeAnalysisStaticAnalysisDirectory)'!=''">$(CodeAnalysisRuleSetDirectories);$(CodeAnalysisStaticAnalysisDirectory)\Rule Sets</CodeAnalysisRuleSetDirectories>
<!--
In scenario where we run CA from command-line , we don't get "CodeAnalysisVSSku" variable passed by the IDE, so in case of Express-only installation
we attempt to load rule sets that are only present on Pro and above - and fail. Let's assume we're in "Express" mode if the Pro+ rule set doesn't exist.
-->
<CodeAnalysisVSSku Condition="'$(CodeAnalysisVSSku)'=='' and !Exists('$(CodeAnalysisStaticAnalysisDirectory)\Rule Sets\NativeRecommendedRules.ruleset')">Express</CodeAnalysisVSSku>
</PropertyGroup>
Based on the code, you just need to put the code analysis rule files in $(VsInstallRoot)\Team Tools\Static Analysis Tools folder and the value of $(VsInstallRoot) is C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools if you just install Build Tools for Visual Studio 2017 on the build server.
To conclude, you just need to put rule files in C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Team Tools\Static Analysis Tools folder.
Officially you'd need to install Visual Studio onto the build server, as the Code Analysis these rules come from are part of Visual Studio, not of MsBuild.
You can still copy the Static Analysis directory to your build server and supply the following parameter to MsBuild in the Additional Arguments option:
/p:CodeAnalysisStaticAnalysisDirectory=c:\analysisdirectory
Or copy just the rule files and specify this MsBuild argument, that's probably easiest when you put the rules files in source control:
/p:CodeAnalysisRuleDirectories=c:\analysisdirectory\rules
Optionally you could edit the project file and set the property in a property group.

TeamCity FxCop Selecting MinimumRecommendedRules.ruleset has no effect

I have added a Build Step in TeamCity 8.0.6 (build 27767) to execute FxCop against a specific c# project assembly.
When running FxCop from within VS 2013 with the MinimumRecommendedRules set I get no errors or warnings (I fixed them all).
Now I want to wire this up in TeamCity. To limit the rules I am specifying a command line property as follows:
/ruleSet:=MinimumRecommendedRules.ruleset /rulesetdirectory:'FxCop\Rule Sets'
(The rulesetdirectory parameter points to a location in my source tree which contains the full contents of the standard Rule Sets folder)
However this does not have the desired behaviour, the FULL rule set is run and I get an error as follows:
FxCop warning: Keyword=CA0063 Kind=Engine Type=Microsoft.FxCop.Sdk.FxCopException * Failed to load rule set file 'MinimumRecommendedRules.ruleset' or one of its dependent rule set files.
And this is the TeamCity generated command line:
[17:32:29]Starting: "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\FxCopCmd.exe" /forceoutput /ignoregeneratedcode /ruleSet:=MinimumRecommendedRules.ruleset "/rulesetdirectory:'FxCop\Rule Sets'" /f:dal\bin\release\MyDAL.dll /out:C:\TeamCity\buildAgent\temp\buildTmp\fxcop-output-1891867450083417003\fxcop-result.xml
Can anyone spot what is wrong?
I figured it out so hopefully this is helpful to someone else.
the /ruleSet: parameter needed to have the full (relative or absolute) path to the ruleset file as follows:
/ruleSet:"=%teamcity.build.workingDir%\FxCop\RuleSets\MinimumRecommendedRules.ruleset"
(Note: the double quotes are to handle the possibility that the teamcity.build.workingDir might contain spaces)
Secondly, the second command line parameter /rulesetdirectory: is no longer necessary. I suspect this second parameter does not actually work.
Please also note, my working command line parameter here points at my MinimumRecommendedRules.ruleset file in my source code. It could just as easily have been copied into the standard Rule Sets folder under "c:\Program Files (x86)\Microsoft Visual Studio 12.0\Team Tools\Static Analysis Tools\Rule Sets".
And finally, as my projects are all VS 2013 and TeamCity only recognises up as far as v10 I also set "Specifiy installation root" to "c:\Program Files (x86)\Microsoft Visual Studio 12.0\Team Tools\Static Analysis Tools\FxCop" explicitly to ensure that the latest version of FxCop was being used and would not choke on .Net 4.5 code. (Note: I have VS 2013 installed on the build server because of C++ project build requirements, I'm not happy about this but it turned out to be convenient for me in dealing with the FxCop set up. There are other ways to put the FxCop stuff on your build server without installing VS 2013)

How to avoid having (or delete) PDB files in TFS 2012 build result

When using DefaultTemplate from Visual Sturdio 2012 (and TFS 2012 server), the PDB files are included in build directory. I do not want them.
Is there a way not to generate those files during build process?
Or
How can I delete those files?
I found this thread about deletion but seems a bit strange (no delete activity?)
There also is this answer but does not involve XAML template.
Thanks in advance for your help.
PDB files hold debug information on your code and its not advised to disable them, they are valid output hence deployment shouldn't be messing with them.
You can disable their generation in Visual Studio project Properties> Build > Advanced > Debug Info = none.
If you absolutely want them gone then disable them for build specific configuration (relaese etc.)
The build server by default does whatever the Solution (sln) tells it to. That by default is to do a "Debug" build and that created the PDB's. You can tell the Build to do a "Release" build that will not by default create any PDB's...
Figure: Adding a Build Configuration
I would however recommend against it as the PDB's contain information that you need even in production systems. Consider for a moment that you have a DLL in production and the customer is encountering a problem. You get them to create an InteliTrace log so that you can debug it locally (or they let you debug on their environment) and suddenly you are trying to debug without Visual Studio understanding the relationship between the Executable and the Source Code. So no debug...
Since I was unable to find building option to disable PDB file generation, I delete them afterwards.
There is no easy way to delete files. I did:
use a FindMatchingFiles Activity with wildcard *.pdb, which returns
a full path to pdb files
use a Foreach loop
call a DotNet method in the loop for each file with the InvokeMethod Activity,
with target type System.IO.File and method being "Delete"
In the previous version (Visual Studio 2010)
When we build /release, it was not generating PDBs, the PDB files are created when we only build with /debug:full or /debug:pdbonly, we use /debug:pdbonly if we want to generate PDBs for a release build that we do not want to be debuggable.
This is not the case in Visual Studio 2012, I checked it and I found it generated PDBs in both, /debug and /release
There is no documentation for Visuals Studio 2012.

Output directory when building a WCF project in Visual Studio

I have a Visual Studio 2010 solution that is set to build in Debug x86. Visual Studio therefore sets the output path to \bin\x86\Debug, which seems logical enough.
The solution contains about 50 projects; the start-up project is a WCF project.
When I do a build, I would expect all output dlls to go to \bin\x86\Debug, as that is what is set in the project settings. But weirdly, I see dlls being created in bin\x86\Debug and in \bin. Why would Visual Studio put any dll in \bin if the output path is not set to that directory? It seems that all dlls go to \bin\x86\Debug, and all dlls except for the start-up project go into \bin. Any idea why it would do that? (We have other solutions that don't use WCF, and they don't have this problem.)
The other annoyance is if I run the service from Visual Studio and then try to access my service in a web browser, by going to http://localhost:1240/MyService.svc, it doesn't work, because the start-up project dll is missing from /bin. I therefore have to manually copy this one dll from \bin\x86\Debug to \bin, so that all dlls are found and the service runs normally. (We could of course add a custom post-build step that does the copy, but you'd think there'd be a better way!)
To those of you working on WCF projects, do you leave the output path at \bin\x86\Debug? (Perhaps there is a way to configure the service, eg in the web.config or .svc file, so that it knows the binaries are in \bin\x86\Debug instead of \bin?) Or do you change the output path to \bin so that you can run your service straight from Visual Studio?
If you open the property page of you WCF Hosting project and goto tab Build, under the Output section of this tag there is a textbox that contains the location of the output binaries.
For a WCF project the binaries should go to bin directory irrespective of the build type (suc as Debug, Release). Make sure this value has been configured correctly.
The value needs to be configured for each build type\configuration.
If you need, for whatever reason, different outputs from different build configurations in different folders you could specify them like you did first and use a post build event command line that copies from your specified output folder to bin.
Like:
- untested code -
COPY/Y "$(OutDir)\*.*" "$(SolutionDir)$(ProjectName)\bin\"
- untested code -