locked
VS2012 Impacts VS2010 Code Analysis?

    Question

  • I have read a couple of MSDN posts on this topic but they appear to be different issues. We did some experiments in a VM whereby both VS2010 and VS2012 are installed side-by-side since this is the environment we will be moving to in the near future. Once we had made all of the changes to our 2012 solutiuon, there were about 250 new CA warnings. This seemed reasonable and figured improvements were made to the engine to better discover issues, etc. In fact, most of the issues that I looked at made me wonder why they hadn't been found before?

    In any event, all seemed well until we switched over to VS2010 and attempted to build, in essence, the same code but on a VS2010 branch. As far as I can tell, it's complaining about the same 250 or so warnings that we found when building in VS2012. I have found a couple of posts that suggest that 2010 is NOT using the 'right' code analysis engine and can be specified via the CodeAnalysisPath MSBuild property; however, we tried this approach to no avail. We did some experiments with ProcMon and see no evidence that building through VS2010 is using the wrong tools.

    Of course, once could back-port changes to earlier branches but this is a horrible idea. It's fine that the 2012 tools are finding more issues but why has this suddenly impacted 2010?? In theory, they should be using completely different tools.

    Short of uninstalling VS2012 or disabling CA, is there anything we can do to allow earlier builds to work the way they did before installing VS2012?


    Scott Parillo


    Tuesday, November 20, 2012 12:42 AM

Answers

  • Per request, I started a new connect report over here...

    http://connect.microsoft.com/VisualStudio/feedback/details/771851/vs2012-impacts-vs2010-code-analysis

    I have been doing some preliminary experiments and I think I have come up with a common denominator, so to speak. I created a small sample in a VM that only contains VS2010 with a single WPF user control project. From what I can tell, it seems that most of the issues are related to WPF libraries. The 'Suppress results from generated code' has never quite worked correctly in VS2010 and it got me thinking. I added a do-nothing WPF user control that only had a single button and added a code-behind click event which included only this line...

    var msg = string.Format(Strings.DoNothing, string.Empty);

    At a minimum, I expected this would yield a CA1305 because the string format doesn't include IFormatProvider; however, compiling this in the VS2010 only VM w/ didn't complain at all! I brought this solution directly into my current VS2010 + VS2012 workstation, rebuilt, and suddenly received 2 CA errors...

    Error 2 CA1305 : Microsoft.Globalization : Because the behavior of 'string.Format(string, object)' could vary based on the current user's locale settings, replace this call in 'UserControl1.button1_Click(object, RoutedEventArgs)' with a call to 'string.Format(IFormatProvider, string, params object[])'. If the result of 'string.Format(IFormatProvider, string, params object[])' will be displayed to the user, specify 'CultureInfo.CurrentCulture' as the 'IFormatProvider' parameter. Otherwise, if the result will be stored and accessed by software, such as when it is persisted to disk or to a database, specify 'CultureInfo.InvariantCulture'. E:\Shared\CodeAnalysisRepro\Projects\Sage.WpfControlLibrary\UserControl1.xaml.cs 30 Sage.WpfControlLibrary
    Error 1 CA1804 : Microsoft.Performance : 'UserControl1.button1_Click(object, RoutedEventArgs)' declares a variable, 'msg', of type 'string', which is never used or is only assigned to. Use this variable or remove it. E:\Shared\CodeAnalysisRepro\Projects\Sage.WpfControlLibrary\UserControl1.xaml.cs 30 Sage.WpfControlLibrary

    So I went back to the VM and, this time, I unticked the "Suppress results from generated code" option and I received the exact same CA warnings! I have understood that Microsoft was going to improve code analysis + generated code and I now believe that whatever has been done or changed is the root cause of this issue.


    Scott Parillo


    Thursday, November 22, 2012 3:21 AM
  • I think I might know why this happens, and I don't think it has to do with Visual Studio 2012 or its CA rules per se.

    I think it's caused by the fact that you have the .NET 4.5 sdk installed, which replaces parts of the 4.0 sdk/clr (since it's more like an addon than a side by side new version). I believe this will cause these two systems to generate slightly different binaries from the xaml.

    If this turns out to be the case, it's logical that FxCop will find differences between you two machines.

    Try running fxcop on the vs2010 machine using the build output of the vs2012 machine, or compare the two binaries (especially the classes that generate these warnings in Reflector or maybe even better, in Introspector).


    My blog: blog.jessehouwing.nl

    Thursday, November 22, 2012 9:03 AM

All replies

  • Side-by-side installation adds some interesting challenges.

    By default MsBuild loads Code Analaysis by checking a standard path, based on the Visual Studio version:

    <PropertyGroup>
        <CodeAnalysisTargets Condition="'$(CodeAnalysisTargets)'==''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeAnalysis\Microsoft.CodeAnalysis.targets</CodeAnalysisTargets>
    </PropertyGroup>

    You can find the Microsoft.Common.targets file here: C:\Windows\Microsoft.NET\Framework\v4.0.30319

    The Microsoft.CodeAnalyis.targets file (which can be found under the $(Programfiles)\MsBuild\Microsoft\VisualStudio\$(VisualStudioVersion)\CodeAnalaysis folder will then either use the path defined in the 'CodeAnalysisStaticAnalysisDirectory' property, and if that isn't set will grab the location of Code Analysis from the registry.

    CodeAnalysis will load the rules from this path by default, unless the rule location has been overwritten in your project file, or when your .rules files contain a reference to a specific rules directory.

    So, check your project file and remove any references directly to a specific Code Analysis directory, MsBuild should handle this correctly by default depending on the version of Visual Studio used.

    Check your .rules fules (if you're using a custom file) and ensure it doesn't reference a version specific path, but instead either includes standard rules files and overrides the default error level, or references a rules directory you keep as part of your solution.

    If that doesn't work, try overriding the CodeAnalysisStaticAnalysisDirectory property in your project file, make sure the property is set before any other targets files are included into your project file.


    My blog: blog.jessehouwing.nl

    Tuesday, November 20, 2012 12:28 PM
  • Thanks for the quick reply! I can tell that I didn't do a good job of identifying our code analysis integration, so here goes...

    • We have a custom .targets file that ALL projects import before any Microsoft MSBuild import.
    • We store a .ruleset file in TFS and use an MSBuild property 'CodeAnalysisRuleSetFullPath'  to construct the full path.
    • Each project file includes <CodeAnalysisRuleSet>$(CodeAnalysisRuleSetFullPath)</CodeAnalysisRuleSet>. This is the only code analysis rules file used by our build system.
    • The .rules file doesn't reference anything at all as far as I can tell.
    • Each project file specifies TreatWarningsAsErrors.

    This is a snippet of what our custom .rules file looks like (I cut out all but 2 rules since we treat all warnings as errors across the board):

    <?xml version="1.0" encoding="utf-8"?>
    <RuleSet Name="Microsoft All Rules Cause Errors" Description="This rule set contains all rules. Running this rule set may result in a large number of warnings being reported. Use this rule set to get a comprehensive picture of all issues in your code. This can help you decide which of the more focused rule sets are most appropriate to run for your projects." ToolsVersion="10.0">
      <IncludeAll Action="Warning" />
      <Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
        <Rule Id="CA1000" Action="Error" />
        <Rule Id="CA1001" Action="Error" />
      </Rules>
    </RuleSet>

    Since all of our project files import a custom .targets file before any other import statements, this allows us to make changes that impact all projects very easily. I did an experiment in which I added this MSBuild property...

    <PropertyGroup>
       <!-- This will ensure that we use the Visual Studio 2010 code analysis engine. -->
       <CodeAnalysisStaticAnalysisDirectory>$(MSBuildProgramFiles32)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\</CodeAnalysisStaticAnalysisDirectory>
    </PropertyGroup>

    Unfortunately, this didn't make any difference. I looked in the some of the relevant 2010 code anlysis directories and the timestamps don't suggest that files were replaced due to having installed VS2012. I had previously analyzed Microsoft.CodeAnalyis.targets and I'm still puzzled because I don't see anything that suggests that we're somehow picking up the wrong tools?


    Scott Parillo

    Tuesday, November 20, 2012 8:05 PM
  • I'd expect your setup to work just fine... But I dont have a system with both 2012 and 2010 at hand to test this...

    Have you tried running msbuild with maximum diagnostics logging? That should tell you which exact values are used and why...


    My blog: blog.jessehouwing.nl

    Tuesday, November 20, 2012 8:24 PM
  • I went to Options->Projects and Solutions->Build and Run and set both MSBuild output verbosity to Diagnostic. I reviewed the build output for 1 of the projects that failed code analysis and this is what I see...

    135>CodeAnalysisApplyLogFileXsl = false
    135>CodeAnalysisDictionaryFileName = CustomDictionary.xml
    135>CodeAnalysisDictionaryFullPath = E:\TFS\Sage Estimating\Development\Celilo\LinkedSource\CodeAnalysis\CustomDictionary.xml
    135>CodeAnalysisFailOnMissingRules = false
    135>CodeAnalysisForceOutput = true
    135>CodeAnalysisGenerateSuccessFile = true
    135>CodeAnalysisIgnoreGeneratedCode = true
    135>CodeAnalysisIgnoreInvalidTargets = true
    135>CodeAnalysisInputAssembly = E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Estimating.Plugin.AddAdmin.dll
    135>CodeAnalysisLogFile = E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Estimating.Plugin.AddAdmin.dll.CodeAnalysisLog.xml
    135>CodeAnalysisModuleSuppressionsFile = GlobalSuppressions.cs
    135>CodeAnalysisOutputToConsole = false
    135>CodeAnalysisOverrideRuleVisibilities = false
    135>CodeAnalysisPath = C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\
    135>CodeAnalysisQuiet = false
    135>CodeAnalysisRuleDirectories = ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
    135>CodeAnalysisRuleSet = E:\TFS\Sage Estimating\Development\Celilo\LinkedSource\CodeAnalysis\AllRulesCauseErrors.ruleset
    135>CodeAnalysisRuleSetDirectories = ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
    135>CodeAnalysisRuleSetFileName = AllRulesCauseErrors.ruleset
    135>CodeAnalysisRuleSetFullPath = E:\TFS\Sage Estimating\Development\Celilo\LinkedSource\CodeAnalysis\AllRulesCauseErrors.ruleset
    135>CodeAnalysisSaveMessagesToReport = Active
    135>CodeAnalysisSearchGlobalAssemblyCache = true
    135>CodeAnalysisStaticAnalysisDirectory = C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\
    135>CodeAnalysisSucceededFile = E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Estimating.Plugin.AddAdmin.dll.lastcodeanalysissucceeded
    135>CodeAnalysisSummary = false
    135>CodeAnalysisTargets = C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\CodeAnalysis\Microsoft.CodeAnalysis.targets
    135>CodeAnalysisTimeout = 120
    135>CodeAnalysisTreatWarningsAsErrors = false
    135>CodeAnalysisUpdateProject = false
    135>CodeAnalysisUseTypeNameInSuppression = true
    135>CodeAnalysisVerbose = false

    This is an example of the command-line created to perform code analysis on one of the projects that's now failing...

    29>  C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\FxCopCmd.exe  /outputCulture:1033 /out:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Estimating.Plugin.AddAdmin.dll.CodeAnalysisLog.xml" /file:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Estimating.Plugin.AddAdmin.dll" /dictionary:"E:\TFS\Sage Estimating\Development\Celilo\LinkedSource\CodeAnalysis\CustomDictionary.xml" /reference:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Estimating.RolesService.Client.dll" /reference:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Estimating.RolesService.Library.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationCore.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationFramework.dll" /reference:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Sage.Estimating.Core.dll" /reference:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Sage.Estimating.LDAPSDK.dll" /reference:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Sage.Estimating.TelerikAlert.dll" /reference:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Sage.Estimating.ViewModelCommands.dll" /reference:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Sage.Platform.Core.UserInteraction.dll" /reference:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating\Sage.Platform.Core.WCF.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Runtime.Serialization.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Xaml.dll" /reference:"E:\TFS\Sage Estimating\Development\Celilo\Assemblies\Telerik.Windows.Controls.dll" /reference:"E:\TFS\Sage Estimating\Development\Celilo\Assemblies\Telerik.Windows.Controls.Navigation.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\WindowsBase.dll" /directory:"E:\TFS\Sage Estimating\Development\Celilo\Assemblies" /directory:"E:\TFS\Sage Estimating\Development\Celilo\Runtime Files\Program Files\Sage Estimating" /directory:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" /ruleSet:"=E:\TFS\Sage Estimating\Development\Celilo\LinkedSource\CodeAnalysis\AllRulesCauseErrors.ruleset" /rulesetdirectory:"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets" /rule:"-C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules" /searchgac /ignoreinvalidtargets /forceoutput /successfile /ignoregeneratedcode /saveMessagesToReport:Active /timeout:120  (TaskId:1442)

    I did a search across the entire build output for 'C:\Program Files (x86)\Microsoft Visual Studio 11.0' and 'Microsoft Visual Studio 11.0' and it didn't give me a single hit. Based on this fact and the output above, it sure seems that all of the correct tools are being used?


    Scott Parillo


    Tuesday, November 20, 2012 9:53 PM
  • Thanks for Jesse’s help.

    Hi Scott ,

    Thank you for posting in the MSDN forum.

    To get the issue confirmed and diagnose by product team, would you please create connect report for it? You will get email notification for update.http://connect.microsoft.com/VisualStudio/feedback/CreateFeedback.aspx

    In addition, could you share us a simple sample? I will try to check it in my Environment. Please also attach your Visual Studio project, you can upload it to the sky driver, and then share the download link in your post. It will be better if you could share us the detailed steps about how you analyze this app with VS2010 and VS2012, please also attach a screenshot image about the result you got in your post. I will try to repro this issue.

    If you submit this feedback, you could share us the link here, I will help you vote it if I could repro this issue. Thanks for your understanding.

    Sincerely,


    Jack Zhai [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, November 21, 2012 10:06 AM
    Moderator
  • Per request, I started a new connect report over here...

    http://connect.microsoft.com/VisualStudio/feedback/details/771851/vs2012-impacts-vs2010-code-analysis

    I have been doing some preliminary experiments and I think I have come up with a common denominator, so to speak. I created a small sample in a VM that only contains VS2010 with a single WPF user control project. From what I can tell, it seems that most of the issues are related to WPF libraries. The 'Suppress results from generated code' has never quite worked correctly in VS2010 and it got me thinking. I added a do-nothing WPF user control that only had a single button and added a code-behind click event which included only this line...

    var msg = string.Format(Strings.DoNothing, string.Empty);

    At a minimum, I expected this would yield a CA1305 because the string format doesn't include IFormatProvider; however, compiling this in the VS2010 only VM w/ didn't complain at all! I brought this solution directly into my current VS2010 + VS2012 workstation, rebuilt, and suddenly received 2 CA errors...

    Error 2 CA1305 : Microsoft.Globalization : Because the behavior of 'string.Format(string, object)' could vary based on the current user's locale settings, replace this call in 'UserControl1.button1_Click(object, RoutedEventArgs)' with a call to 'string.Format(IFormatProvider, string, params object[])'. If the result of 'string.Format(IFormatProvider, string, params object[])' will be displayed to the user, specify 'CultureInfo.CurrentCulture' as the 'IFormatProvider' parameter. Otherwise, if the result will be stored and accessed by software, such as when it is persisted to disk or to a database, specify 'CultureInfo.InvariantCulture'. E:\Shared\CodeAnalysisRepro\Projects\Sage.WpfControlLibrary\UserControl1.xaml.cs 30 Sage.WpfControlLibrary
    Error 1 CA1804 : Microsoft.Performance : 'UserControl1.button1_Click(object, RoutedEventArgs)' declares a variable, 'msg', of type 'string', which is never used or is only assigned to. Use this variable or remove it. E:\Shared\CodeAnalysisRepro\Projects\Sage.WpfControlLibrary\UserControl1.xaml.cs 30 Sage.WpfControlLibrary

    So I went back to the VM and, this time, I unticked the "Suppress results from generated code" option and I received the exact same CA warnings! I have understood that Microsoft was going to improve code analysis + generated code and I now believe that whatever has been done or changed is the root cause of this issue.


    Scott Parillo


    Thursday, November 22, 2012 3:21 AM
  • I think I might know why this happens, and I don't think it has to do with Visual Studio 2012 or its CA rules per se.

    I think it's caused by the fact that you have the .NET 4.5 sdk installed, which replaces parts of the 4.0 sdk/clr (since it's more like an addon than a side by side new version). I believe this will cause these two systems to generate slightly different binaries from the xaml.

    If this turns out to be the case, it's logical that FxCop will find differences between you two machines.

    Try running fxcop on the vs2010 machine using the build output of the vs2012 machine, or compare the two binaries (especially the classes that generate these warnings in Reflector or maybe even better, in Introspector).


    My blog: blog.jessehouwing.nl

    Thursday, November 22, 2012 9:03 AM
  • I think it's caused by the fact that you have the .NET 4.5 sdk installed, which replaces parts of the 4.0 sdk/clr (since it's more like an addon than a side by side new version). I believe this will cause these two systems to generate slightly different binaries from the xaml.

    (...)

    I have understood that Microsoft was going to improve code analysis + generated code and I now believe that whatever has been done or changed is the root cause of this issue.

    That's what we independently discovered:  the C# 5.0 compiler's XAML code generator now only applies the [GeneratedCode] attribute on generated methods instead of on the generated partial class (which, of course, applied it to the entire class, not just the generated portion).  You can confirm this by compiling the same [WPF] code on a machine with just .NET 4.0 installed and one with .NET 4.5 installed, then inspecting the assembly metadata by reflection.

    As Scott noted, unchecking "Suppress results from generated code" will yield similar results, unless the XAML-generated code itself contains CA violations.

    The way to restore the old Code Analysis behaviour to your .NET 4.0 [WPF] projects when using a mix of .NET 4.0 and .NET 4.5 is to manually apply the [GeneratedCode] attribute on code-beside classes wherever the compiler no longer adds them for you.

    Cheers,

    - Oli

    Thursday, December 06, 2012 7:32 PM
  • Oli,

    Yes indeed, I think you nailed it. We went back to our old branch and suppressed all of the warnings so that anybody building the old code using VS2010 w/ VS2012 installed won't run into these CA warnings.

    Given this information, it seems that Microsoft should include this detail in their VS2012 Project Upgrade material (web or otherwise). If that seems reasonable, how does one go about making that happen?


    Scott Parillo


    Tuesday, December 11, 2012 2:25 AM