There is this great feature in Visual Studio that lets you really dial up the quality of your code. It has been there forever it seems, but very few people use it.

The compiler spits out errors, which stop your app compiling. You fix your errors and move on. But the compiler also spits out a lot of warnings too. And many of these are to do with the quality of your code, and possible code errors you have introduced that could cause you issues later on.

Did you know you can get the builds to actually fail to compile from these warnings?

Treat Warnings As Errors

If you head to the properties dialog of a project, you will see the following under the Build menu.

Visual Studio Build Config Settings

See that radio button? Treat warnings as errors. You wanna set that baby to All. Do it now! While you are in here, set the Warning level to 4 as well.

That’s it! You are all set to start failing your builds, for this project anyway. In fact, go ahead and try to build. There is a better than normal chance that you probably already have some warnings and now have a failing build. Well done.

Actually, you probably only turned that on for Debug builds, so go repeat those steps after changing the Configuration dropdown to Release. And any others you have where this applies.

The nice thing about TreatWarningsAsErrors is that it is in the *.csproj file XML, and is actually an MSBuild command. This means that it will use the same settings when you build at command line using either devenv or MSBuild tools. So your CI server will apply this too.

As well as the TreatWarningsAsErrors command, there is this WarningLevel. Just turn it up to 4 and move on, it is the option you want, trust me.

… One weird trick

So, I mentioned one weird script right?

If you have an existing solution with lots of projects, you won’t want to turn these all on one by one manually. You also don’t want to fuss around making sure that if you or someone else has added a bunch of new projects, that these rules are turned on correctly.

To solve these issues, I have a PowerShell script that runs over a directory, finds all the *.csproj files, and updates their Debug and Release configurations with TreatWarningsAsErrors set to true, and WarningLevel to `4'.

get-childitem . -include *.csproj -recurse -ErrorAction SilentlyContinue | %{
    [xml]$proj = get-content $_.FullName
    $modified = 0
    $proj.Project.PropertyGroup | 
    where-object { $_.Condition -match 'Configuration.*Platform.*(Debug|Release)' } | %{
        if (-not $_.TreatWarningsAsErrors) {
            $node = $proj.CreateElement('TreatWarningsAsErrors', $proj.Project.NamespaceURI)
            $node.InnerText = 'true'
            $node = $_.AppendChild($node)
            $modified = 1
        if ($_.TreatWarningsAsErrors -ne 'true') {
            $_.TreatWarningsAsErrors = 'true'
            $modified = 1
        if (-not $_.WarningLevel) {
            $node = $proj.CreateElement('WarningLevel', $proj.Project.NamespaceURI)
            $node.InnerText = "4"
            $node = $_.AppendChild($node)
            $modified = 1
        if ($_.WarningLevel -ne "4") {
            $_.WarningLevel.InnerText = "4"
            $modified = 1
    if ($modified -eq 1) {

This is also up on a gist if you prefer.

That is it. Run that in your solution directory and you should be sorted. Don’t forget to fix the compiler errors before checking your changes back in though.


There is always one project that disobeys with the strict rules. That’s ok, just leave it off and come back and fix the issues when you have a spare few moments. Perhaps in a quiet Friday afternoon, or the day after ship day while you wait for those bug reports to come in. Once the problem is fixed, run the script again and hey presto it will be turned on again.

There are other ways to filter and ignore specific issues but I will leave that as an exercise for the reader if they really want to go down that path.