C# + StyleCop + MSBuild + Global culture settings failing to be picked up - c#

I've got my C# project file set up to import a StyleCop.Targets project that runs all the StyleCop rules on build. This is great and I've got the project down to zero errors when compiling through Visual Studio.
However when I compile through MSBuild (on the same machine) I get errors along the line of :
The documentation text within the constructor's summary tag must begin with the text: Initializes a new instance of the <see cref="MyClass" /> class.
Focus on the 'Z' in initialises... I've configured my Settings.StyleCop with an en-GB global setting so that I don't get errors about Americanisms within the code. However I can't fathom out why this causes errors in MSBuild.
I know MSBuild is using the same Settings.StyleCop file as if I change a rule (say TabsMustNotBeUsed) MSBuild (and Visual Studio) picks this change up and throws errors all over the place.
I am using StyleCop 4.7, Visual Studio 2012 and MSBuild 4.
Here is a snippet of my Settings.StyleCop file :
<StyleCopSettings Version="105">
<GlobalSettings>
<StringProperty Name="Culture">en-GB</StringProperty>
</GlobalSettings>
<Parsers>
<Parser ParserId="StyleCop.CSharp.CsParser">
<ParserSettings>
<BooleanProperty Name="AnalyzeDesignerFiles">False</BooleanProperty>
</ParserSettings>
</Parser>
</Parsers>
<Analyzers>
<Analyzer AnalyzerId="StyleCop.CSharp.SpacingRules">
<Rules>
<Rule Name="TabsMustNotBeUsed">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
</Analyzers>
</StyleCopSettings>
Any clues ?
Cheers!

I'm assuming you're using the latest version of StyleCop (4.7.41.0) or a version close to that. There have been a lot of changes and fixes in the 4.7 version line, and there have been fairly regular updates released.
I'm guessing that there must be another Settings.StyleCop file lower down (in a sub-folder) in the folder hierarchy that is setting the culture back to en-US. Modifying other rules in this particular settings file (like TabsMustNotBeUsed) will still behave as expected as long as you're not setting it again in the other settings file. A potential cause could be the working folder that StyleCop is being run from.
I suggest doing a quick scan in your file system to see if you can find any other settings files, and if found, check their culture setting.
Another trick I've done is to stop merging in settings files at the solution root. This can be done by adding the following setting:
<GlobalSettings>
<StringProperty Name="MergeSettingsFiles">NoMerge</StringProperty>
</GlobalSettings>
This will ensure that StyleCop acts the same on all development and build machines, regardless of the settings configured higher up the hierarchy (such as the one in the StyleCop application folder). However if you do this, make sure you copy all the required settings from the files no longer being merged. From your description I doubt that this will solve this particular problem, but I have found it useful to help retain rule consistency.

Related

ReSharper 10 test runner failing to find AppSettings referenced from external file

I recently upgraded to ReSharper 10.0.1 for Visual Studio 2013. My unit test project contains an app.config file which contains this:
<appSettings file="AppSettings.local.config">
<add key="otherSetting" value="foo" />
</appSettings>
<connectionStrings configSource="ConnectionStrings.local.config" />
The referenced config files are set to "Copy always" to the output directory. I verified that tests are running from \bin\debug off the project folder, and that both referenced config files are copied correctly to that folder. However, when running the tests, I've observed that:
ConfigurationManager.AppSettings DOES NOT contain any of the keys from AppSettings.local.config.
ConfigurationManager.AppSettings DOES contain otherSetting.
ConfigurationManager.ConnectionStrings DOES contain all of the keys from ConnectionStrings.local.config.
Using the configSource attribute instead of file in <appSettings> does not work either.
The way I manage config files has not changed in a very long time and has always worked fine. The problem definitely seemed to coincide with the upgrade to ReSharper 10. In ReSharper's unit testing settings, I've disabled "shadow-copy assemblies" and "use seperate AppDomain", and "Run test from" is set to project output folder. I've restarted VS many times after changing these settings.
Does this sound like a possible ReSharper bug or could I be missing something obvious?
UPDATE:
I've downgraded to ReSharper 9.2 and my woes have disappeared. So I can only conclude that this is a ReSharper 10 issue. But I'm not certain whether it's a bona fide bug (sure seems that way), or if I missed a new setting somewhere, so any insights would still be appreciated.
It is a known issue for R# 10.0.0 and R# 10.0.1 releases. Fixed in R# 10.0.2 EAP builds

Project <PROJECT NAME> is not up to date. Missing input file 'netframework,version=v4.0,profile=client.assemblyattributes.cs

I have a sln with > 50 projects, and recently, when I moved to VS2013, every time I press F5 for a build, it will rebuild all the projects, even though I have just performed a build. The diagnostics show, that each project is marked as not up to date with the following error:
Project <PROJECT NAME> is not up to date. Missing input file 'c:\users\USER\appdata\local\temp\2\.netframework,version=v4.0,profile=client.assemblyattributes.cs
I have read these threads:
In Visual Studio 2010 why is the .NETFramework,Version=v4.0.AssemblyAttributes.cpp file created, and can I disable this?
https://social.msdn.microsoft.com/Forums/vstudio/en-US/15d65667-ac47-4234-9285-32a2cb397e32/migration-from-vs2008-to-vs2010-and-netframeworkversionv40assemblyattributescpp?forum=vcgeneral
but the suggestion there is to add the following line to the proj file:
<Target Name="GenerateTargetFrameworkMonikerAttribute" />
I did and it did not work. Suppressing the warning as MS suggestion will also not work as the project will remain "not up to date".
I am using VS2013, C# and VB projects. With the very same project and VS2012, such error is not raised and the projects are up to date.
Any suggestions?
UPDATE
Perhaps it is worth mentioning that I do have a few build definitions in the solution, where all of the projects are building for AnyCPU except one: http://screencast.com/t/fuw9k4IubN
I had the same problem and solved it by upgrading the ToolsVersion attribute in *.csproj files:
ToolsVersion="4.0" replaced with ToolsVersion="16.0"
(I’m using Visual Studio 2019, which is v16.x internally).
<Target Name="GenerateTargetFrameworkMonikerAttribute" />
Well, not a good idea, that accomplishes the exact opposite of the problem you are trying to solve. It forces MSBuild to create the AssemblyAttributes.cs file, inevitably your project needs to be rebuilt since the file is new. The Q+A you found addresses a completely different issue, these were C++ programmers that were trying to come to grips with a new linker warning in VS2010. They hate warnings that appear from nowhere from files that are not part of their project. Well, don't we all. The marked answer on that SO question is quite evil btw, that other guy posted a much better answer :)
Missing input file 'c:\users\USER\appdata\local\temp\2\.netframework...
There's a signal in this message, note the presence of the \2 subdirectory in that path name. That is a Big Red Flag, it is not normal. This auto-generated .cs file normally lives inside the TEMP directory, not a subdirectory of that folder. Surely this has something to do with your real problem.
MSBuild doesn't do anything special and simply uses System.IO.Path.GetTempPath() to generate the folder name. That method isn't special either, it simply delegates the job to the GetTempPath() winapi function. The diagnostic therefore is that on this build machine, that OS function sometimes generates an odd-ball path, picking a subdirectory of the TEMP folder. And that it doesn't always generate the same one, thus causing your projects to getting rebuilt.
There is at least one good theory for this behavior, mentioned by commenter #Darran Rowe to this blog post:
No, this is Terminal Services at work. When you log in over remote desktop, Windows will set the temp directory for the logon session to %LOCALAPPDATA%\Temp\<session id>
Rings a bell?
Try deleting the hidden .vs directry which is in the same folder than the solution file.
This worked for me
Close visual studio and Deleted the .sou files from the projects
I was getting the same error and I solved it by removing the project from my solution and re-adding it. It is a pain because then you have to add the inter project references back in.

Using msbuild to execute a File System Publish Profile

I have a c# .Net 4.0 project created with VS2010 and now being accessed with VS2012.
I'm trying to publish only the needed files from this website to a destination location (C:\builds\MyProject[Files])
My file structure:
./ProjectRoot/MyProject.csproj
./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml
I'm running the following via MSBuild:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml
Here's the xml in FileSystemDebug.pubxml
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<ExcludeApp_Data>False</ExcludeApp_Data>
<publishUrl>C:\builds\MyProject\</publishUrl>
<DeleteExistingFiles>True</DeleteExistingFiles>
</PropertyGroup>
</Project>
The resulting behavior is:
a zip file is created here:./ProjectRoot/obj/Debug/Package/MyProject.zip
Nothing is deployed to <publishUrl>C:\builds\MyProject\</publishUrl> WTF
the zip file that is created is a pigs breakfast and full of files that aren't needed for the application.
When I run this publish profile through visual studio a folder is created at *C:\builds\MyProject* and contains the exact artifacts that I want.
How do I get this simple result from msbuild?
FYI: I had the same issue with Visual Studio 2015. After many of hours trying, I can now do msbuild myproject.csproj /p:DeployOnBuild=true /p:PublishProfile=myprofile.
I had to edit my .csproj file to get it working. It contained a line like this:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets"
Condition="false" />
I changed this line as follows:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0\WebApplications\Microsoft.WebApplication.targets" />
(I changed 10.0 to 14.0, not sure whether this was necessary. But I definitely had to remove the condition part.)
Found the answer here:
http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
Visual Studio 2010 has great new Web Application Project publishing
features that allow you to easy publish your web app project with a
click of a button. Behind the scenes the Web.config transformation and
package building is done by a massive MSBuild script that’s imported
into your project file (found at: C:\Program Files
(x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets).
Unfortunately, the script is hugely complicated, messy and
undocumented (other then some oft-badly spelled and mostly useless
comments in the file). A big flowchart of that file and some
documentation about how to hook into it would be nice, but seems to be
sadly lacking (or at least I can’t find it).
Unfortunately, this means performing publishing via the command line
is much more opaque than it needs to be. I was surprised by the lack
of documentation in this area, because these days many shops use a
continuous integration server and some even do automated deployment
(which the VS2010 publishing features could help a lot with), so I
would have thought that enabling this (easily!) would be have been a
fairly main requirement for the feature.
Anyway, after digging through the Microsoft.Web.Publishing.targets
file for hours and banging my head against the trial and error wall,
I’ve managed to figure out how Visual Studio seems to perform its
magic one click “Publish to File System” and “Build Deployment
Package” features. I’ll be getting into a bit of MSBuild scripting, so
if you’re not familiar with MSBuild I suggest you check out this crash
course MSDN page.
Publish to File System
The VS2010 Publish To File System Dialog Publish to File System took
me a while to nut out because I expected some sensible use of MSBuild
to be occurring. Instead, VS2010 does something quite weird: it calls
on MSBuild to perform a sort of half-deploy that prepares the web
app’s files in your project’s obj folder, then it seems to do a manual
copy of those files (ie. outside of MSBuild) into your target publish
folder. This is really whack behaviour because MSBuild is designed to
copy files around (and other build-related things), so it’d make sense
if the whole process was just one MSBuild target that VS2010 called
on, not a target then a manual copy.
This means that doing this via MSBuild on the command-line isn’t as
simple as invoking your project file with a particular target and
setting some properties. You’ll need to do what VS2010 ought to have
done: create a target yourself that performs the half-deploy then
copies the results to the target folder. To edit your project file,
right click on the project in VS2010 and click Unload Project, then
right click again and click Edit. Scroll down until you find the
Import element that imports the web application targets
(Microsoft.WebApplication.targets; this file itself imports the
Microsoft.Web.Publishing.targets file mentioned earlier). Underneath
this line we’ll add our new target, called PublishToFileSystem:
<Target Name="PublishToFileSystem"
DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
<Error Condition="'$(PublishDestination)'==''"
Text="The PublishDestination property must be set to the intended publishing destination." />
<MakeDir Condition="!Exists($(PublishDestination))"
Directories="$(PublishDestination)" />
<ItemGroup>
<PublishFiles Include="$(_PackageTempDir)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(PublishFiles)"
DestinationFiles="#(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')"
SkipUnchangedFiles="True" />
</Target>
This target depends on the
PipelinePreDeployCopyAllFilesToOneFolder target, which is what VS2010
calls before it does its manual copy. Some digging around in
Microsoft.Web.Publishing.targets shows that calling this target causes
the project files to be placed into the directory specified by the
property _PackageTempDir.
The first task we call in our target is the Error task, upon which
we’ve placed a condition that ensures that the task only happens if
the PublishDestination property hasn’t been set. This will catch you
and error out the build in case you’ve forgotten to specify the
PublishDestination property. We then call the MakeDir task to create
that PublishDestination directory if it doesn’t already exist.
We then define an Item called PublishFiles that represents all the
files found under the _PackageTempDir folder. The Copy task is then
called which copies all those files to the Publish Destination folder.
The DestinationFiles attribute on the Copy element is a bit complex;
it performs a transform of the items and converts their paths to new
paths rooted at the PublishDestination folder (check out Well-Known
Item Metadata to see what those %()s mean).
To call this target from the command-line we can now simply perform
this command (obviously changing the project file name and properties
to suit you):
msbuild Website.csproj "/p:Platform=AnyCPU;Configuration=Release;PublishDestination=F:\Temp\Publish" /t:PublishToFileSystem
Still had trouble after trying all of the answers above (I use Visual Studio 2013). Nothing was copied to the publish folder.
The catch was that if I run MSBuild with an individual project instead of a solution, I have to put an additional parameter that specifies Visual Studio version:
/p:VisualStudioVersion=12.0
12.0 is for VS2013, replace with the version you use. Once I added this parameter, it just worked.
The complete command line looks like this:
MSBuild C:\PathToMyProject\MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=MyPublishProfile /p:VisualStudioVersion=12.0
I've found it here:
http://www.asp.net/mvc/overview/deployment/visual-studio-web-deployment/command-line-deployment
They state:
If you specify an individual project instead of a solution, you have to add a parameter that specifies the Visual Studio version.
It looks to me like your publish profile is not being used, and doing some default packaging. The Microsoft Web Publish targets do all what you are doing above, it selects the correct targets based on the config.
I got mine to work no problem from TeamCity MSBuild step, but I did specify an explicit path to the profile, you just have to call it by name with no .pubxml (e.g. FileSystemDebug). It will be found so long as in the standard folder, which yours is.
Example:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=FileSystemDebug
Note this was done using the Visual Studio 2012 versions of the Microsoft Web Publish targets, normally located at "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web". Check out the deploy folder for the specific deployment types targets that are used
Actually I merged all your answers to my own solution how to solve the above problem:
I create the pubxml file according my needs
Then I copy all the parameters from pubxml file to my own list of parameters "/p:foo=bar" for msbuild.exe
I throw away the pubxml file
The result is like that:
msbuild /t:restore /t:build /p:WebPublishMethod=FileSystem /p:publishUrl=C:\builds\MyProject\ /p:DeleteExistingFiles=True /p:LastUsedPlatform="Any CPU" /p:Configuration=Release
FYI: Same problem with running on a build server (Jenkins with msbuild 15 installed, driven from VS 2017 on a .NET Core 2.1 web project).
In my case it was the use of the "publish" target with msbuild that ignored the profile.
So my msbuild command started with:
msbuild /t:restore;build;publish
This correctly triggerred the publish process, but no combination or variation of "/p:PublishProfile=FolderProfile" ever worked to select the profile I wanted to use ("FolderProfile").
When I stopped using the publish target:
msbuild /t:restore;build /p:DeployOnBuild=true /p:PublishProfile=FolderProfile
I (foolishly) thought that it would make no difference, but as soon as I used the DeployOnBuild switch it correctly picked up the profile.
First check the Visual studio version of the developer PC which can publish the solution(project).
as shown is for VS 2013
/p:VisualStudioVersion=12.0
add the above command line to specify what kind of a visual studio version should build the project. As previous answers, this might happen when we are trying to publish only one project, not the whole solution.
So the complete code would be something like this
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" "C:\Program Files (x86)\Jenkins\workspace\Jenkinssecondsample\MVCSampleJenkins\MVCSampleJenkins.csproj" /T:Build;Package /p:Configuration=DEBUG /p:OutputPath="obj\DEBUG" /p:DeployIisAppPath="Default Web Site/jenkinsdemoapp" /p:VisualStudioVersion=12.0
Run from the project folder
msbuild /p:DeployOnBuild=true /p:PublishProfile="release-file.pubxml" /p:AspnetMergePath="C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools" /p:Configuration=Release
This takes care of web.config Transform and AspnetMergePath

VS 2008 Professional, Smart Device .NET C# project - slow build

I have VS 2008 Professional and a Smart Device .NET C# project. I have ~100 cs files in total. The build takes a very long time, I have to wait for linker approx. 1min (60s) every time I compile the project. I have Core i3, 4GB RAM, 7200rpm disk.
What causes this and how can I optimize the build? Any Visual Studio options?
If you follow the advise from Hans Passant's comment and set MSBuild to diagnostic output it will give a clearer picture of just what is taking the time. If you find that your build is hanging on the Licensing Compiler (LC.exe) then this could be due to it trying to call a server and timing out. You can resolve this by altering your machine.config -
edit c:\windows\microsoft.net\framework\v2.0.50727\config\machine.config, and add the following key:
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
EDIT://
Based on the comment below I did a little digging. The platform verification task has a known issue where it runs very slowly in VS2008. More detail on it can be found here:
http://blogs.msdn.com/b/vsdteam/archive/2006/09/15/756400.aspx
One way around this is to disable the task itself in your build. To do this
1) Open the file:
%windir%\Microsoft.NET\Framework\v2.0.50727\Microsoft.CompactFramework.Common.Targets
for editing.
2) Go to the line which reads:
Name="PlatformVerificationTask">
and change it to:
Name="PlatformVerificationTask" Condition="'$(SkipPlatformVerification)' != 'true'">
3) Add the SkipPlatformVerification environment variable to the system and set it to "true" (To re-enable Platform Verification set the environment variable to "false"). If you need help on setting up an environment variable read http://vlaurie.com/computers2/Articles/environment.htm. If you don't want to add an environment variable you can swap the condition for something that is always false (i.e. Condition="'true' == 'false'")
Just re-define an target in your .csproj file like this. Then it will works across the machine, Or of course you could copy the whole block of code with the conditional line added.
Either way, you need not to modify the system file.
<Target Name="PlatformVerificationTask"></Target>
For windows 10 and framework 3.5,
in C:\Windows\Microsoft.NET\Framework\v3.5 folder, find Microsoft.CompactFramework.common.targets file.
In this section
<Target
Name="PlatformVerificationTask">
<PlatformVerificationTask
PlatformFamilyName="$(PlatformFamilyName)"
PlatformID="$(PlatformID)"
SourceAssembly="#(IntermediateAssembly)"
ReferencePath="#(ReferencePath)"
TreatWarningsAsErrors="$(TreatWarningsAsErrors)"
PlatformVersion="$(TargetFrameworkVersion)"/>
</Target>
change this, (add Condition="'$(DoPlatformVerificationTask)'=='true'" line)
<Target
Name="PlatformVerificationTask">
<PlatformVerificationTask
Condition="'$(DoPlatformVerificationTask)'=='true'" <!-- Added -->
PlatformFamilyName="$(PlatformFamilyName)"
PlatformID="$(PlatformID)"
SourceAssembly="#(IntermediateAssembly)"
ReferencePath="#(ReferencePath)"
TreatWarningsAsErrors="$(TreatWarningsAsErrors)"
PlatformVersion="$(TargetFrameworkVersion)"/>
</Target>

VS2008 - Outputting a different file name for Debug/Release configurations

When building a C# application with Visual Studio 2008, is it possible to set a different output filename per configuration?
e.g.
MyApp_Debug.exe
MyApp_Release.exe
I tried a post-build step to rename the file by appending the current configuration, but that seems a scrappy approach. Plus it meant that Visual Studio could no longer find the file when pressing F5 to start debugging.
You can achieve this by editing your project file by hand. Locate the <AssemblyName> node and add a conditional attribute to it:
<AssemblyName Condition="'$(Configuration)'=='Debug'">MyApp_Debug.exe</AssemblyName>
<AssemblyName Condition="'$(Configuration)'=='Release'">MyApp_Release.exe</AssemblyName>
You'll have to duplicate it also to add another conditional attribute for the release version.
Whilst it is possible, it may cause problems. There is an AssemblyConfiguration attribute that can be applied to your assembly. In AssemblyInfo.cs, put:
#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif
This will add a property to your compiled assembly that will tell you which build configuration your application was built using.
As adrianbanks mentioned, you can edit your .csproj file by hand to accomplish this.
I would, however reccomend the simpler form of:
<AssemblyName>MyApp_$(Configuration).exe</AssemblyName>
If you ever edit the properties of this project however, this change will very likely be lost. It's something you will have to manually stay on top of, as it's not going to be a supported setup.
To manually edit your project definition, right click the project in Visual Studio, and select "Unload", then right click the unloaded project, and select "Edit" and it will open the XML definition for you.
I'm sure there is, however in my experience having different filenames for debug / release configurations is a bad idea as it can cause all sorts of problems (very much like the issue VS has when it tries to execute the renamed app)
Why not simply indicate whether or not its debug / release in the Assembly attributes (for example in the comments)

Categories