Shared AssemblyInfo for uniform versioning across the solution - c#

I've read about this technique: Shared assembly info in VS projects - JJameson's blog
Basically it means to create a SharedAssemblyInfo.cs with versioning information about the assembly, and adding this file as Link to all projects of the solution, so the actual file resides only in 1 location on disk.
My question deals with 2 scenarios:
Existing solution that doesn't use this mechanism: Is there a way to easily add the ShareAssemblyInfo to all projects? (lets say i have a solution with 50 projects).
When creating a new project, by default a new AssemblyInfo.cs is created. However i'd like to link automatically to the SharedAssemblyInfo as well.
Is there any solution for this? what is the common practice?

It is possible to link to a shared assembly info file in VS 2010. Ashish Jain has a good blog post about it: Sharing assembly version across projects in a solution.
After creating the shared assembly info file at the solution level, his instructions for linking to it from a project are:
Right click on the project, in which you wish to add the Shared
assembly file, and select Add -> Existing Item...
Select the file “SharedAssemblyInfo.cs” from the solution folder.
Instead of Add, click on the the arrow next to Add and click “Add as
Link”
Drag down the added linked file alongside AssemblyInfo.cs in the
same folder.
Repeat steps 1 – 4 for all projects for which you wish to add shared
assembly file.
I've tried this and it works.

First point could be solved with simple text editor that could handle several files at once and find/replace. Just open all of your csproj in it and replace string <Compile Include="Properties\AssemblyInfo.cs" /> with
<Compile Include="..\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
Alternatively you could write a utility like that:
var files = Directory.GetFiles(yourSolutionDir, "*.csproj", SearchOption.AllDirectories);
foreach (var f in files) {
string contents = File.ReadAllText(f);
string result = contents.Replace("<Compile Include=\"Properties\\AssemblyInfo.cs\" />", putSecondStringHere_ItIsJustTooLong); // :)
File.WriteAllText(f, contents);
}
As for the second question... You could take a look at Visual Studio custom project templates , but I'm not sure it worth the efforts. You should IMO write test that will check this instead. It will be much simpler and outcome is actually almost the same.
UPD: About writing tests for checking solution/project files against some custom rules. Basically, sln/csproj format is simple enough to be parseable without much efforts. So if you want to have SharedAssemblyInfo.cs linked into every project - just parse csproj's and check that. Then put that checker in your build server and run it on each build. We have such system working currently and it costs something about two days to write but saved us many more (we have there more sophisticated rules and multi-solution project, so it was worth the efforts).
I won't write about this checking in detail here right now (it is not that short), but I'm going to write blog post about it soon - most probably till the end of this week. So, if you're interested - just check my blog soon :)
UPD: Here it is.

I have created an application to increment the file version automatically.
Download Applicaiton
add the following line to pre-build event command line
C:\temp\IncrementFileVersion.exe $(SolutionDir)\Properties\AssemblyInfo.cs
Build the project
To keep it simple the app only throws messages if there is an error, to confirm it worked fine you will need to check the file version in 'Assembly Information'
Note : You will have to reload the solution in Visual studio for 'Assembly Information' button to populate the fields, however your output file will have the updated version.
For suggestions and requests please email me at telson_alva#yahoo.com

This does not work for solution that has both C# and F# projects. c# project cannot reference shared f# file and vice versa.
The only option in this case is to make a separate project and refer to it from other projects

Related

Why does Visual Studio mark my added .cs files as "ignored"?

I cloned an existing but almost empty project on my local machine through GitHub for Windows. Then I opened it in VS 2017 and added a few classes after what they all became marked up as "ignored" with red icons with "minus" sign on them.
When I tried to make a commit, (I want to make commits and push through GitHub App), non of the files where pushed.
Then I tried right-clicking on the files and adding them to source control. Then "minus" signs became "+".
I also thought maybe the problem lies in the fact that I didn't stage them. So I did (in VS). But I still cannot push these files. After an attempt to make a commit in GitHub app all my .cs files again become marked up with "minus" sign.
What is the reason of it and how to make them not be signed as "ignored"?
They are (most likely) being ignored by .gitignore file.
If you can't see anything obvious (check substrings of the file name as well as extension), then look for these and remove them:
/*
!/content/
Not sure if this helps the #Tanya, and here's my partially similar experience.
And sadly (as a reflection on my powers of observation) it turned out to be exactly as #goamn had suggested.
I was building a new console app (very short list of files) to help me do a backup activity, and I had called the VS project “backup”.
What I missed (at first and second glance) was that in the .gitignore was the line (in the “Backup & report files” of all likely places!):
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
Backup*
Merely removing this line from that file, even after I had (what appeared to me to be a horked) repository already set up and non functional in github, fixed it right up. I was able to commit the files with no problem.
Hope that helps.
Say the .gitignore file has this:
*.log
in it.
Now, a project that's named with a .Log suffix will not be committed(for example a project called CompanyName.Domain.Service.SubService.Log)
To add such a project to source control, you'd need to manually add it using:
git add <RootFolder>/<CompanyName.Domain.Service.SubService>.Log/* -f
This will force commit the change contrary to the opinion of the .gitignore file. However, this does not remove the .log from the .gitignore file. But once the force commit happens, the project is already in source control and will therefore not be subject to the .gitignore file. Thereafter, commits to this project will be committed.
You need to add first, ensure they're staged, commit, then push

How does a "stand alone" class file work?

I'm looking into the source code of Kestrel and found something interesting. From its dev branch, you can see there is a stand alone class file named HttpClientSlim in /test/shared folder which doesn't belong to any project. And it's used in a few projects. I cloned the source code, the solution explorer looks like
how does it compile?
When you attempt to add an existing item to a project there is a small dropdown next to the "Add" button which allows you to add as a link.
This means that if you want a class included in multiple projects you can keep the actual source file in one place, but "link it in" to multiple projects.
It saves copy/pasteing code, but the project compiles it into the binary as if it were local.
Note that for users of VS2015, you may need to manually edit project.json to get the same functionality, this is described in more detail in this Q/A:
When adding an existing item with "Add as Link", this file is not compiled in VS2015?

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.

Reuse a solution for a new task

I am new to C# and Sharepoint Web Services. I wrote a program awhile back, and I want to use that program as my starting point for the next project. It has all the references and resources already in place. Essentially, I want to copy the solution, and rename it, then change it to meet my current needs.
What's the best way to do that?
Try this:
open Windows Explorer, copy your solution and its folders, paste into a new location.
rename your copied .sln to something else (hit key F2 from Windows Explorer)
open that copied solution, and rename the solution (and perhaps your projects within)
You can open the old project in visual studio and then go to File --> Export Template and follow the wizard.
This will allow you to create a project template that will then be available with all your other project templates in File --> New project.
You can do this per project (or per item which will not help in your case). It then automatically renames your namespaces etc. if the template is configured correctly.
The most straight-forward approach would probably be to just create a new solution, then manually copy all the projects under that solution and add to the new solution (right click on the solution name in Solution Explorer -> Add -> Existing Project.
From there, rename the projects if required, being careful to keep things like the Default namespace and Assembly name consistent with your new project name (you can find these under each project's properties page). Also keep an eye out for any paths that might need changed in the pre / post build steps. You will probably also want to rename the existing namespaces (right-click the namespace in code, Refactor -> Rename...)
Also, this might be a good opportunity to spot which projects will be common to both the old application and your new one, and possibly moving these to a third location from which both solutions can reference them.

Why is "Set as Startup" option stored in the suo file and not the sln file?

It seems like this setting should be stored in the solution file so it's shared across all users and part of source code control. Since we don't check in the suo file, each user has to set this separately which seems strange.
It is absolutely necessary that everyone can define their StartUp Project themselves, as Jon has already said. But to have a dedicated default one would be great, and as I can tell, it is possible!
If you don’t have a .suo file in your solution directory, Visual Studio picks the first project in your .sln file as the default startup project.
Close your Visual Studio and open the .sln file in your favorite text editor. Starting in line 4, you see all your projects encapsulated in Project – EndProject lines.
Cut and paste the desired default startup project to the top position.
Delete your .suo file.
Open your solution in Visual Studio. Ta daa!
In most cases, it does make sense to have a default on this.
It would be much better to accommodate a default startup project and store this in the .sln file, but which can be overridden by a developer in their .suo file. If the startup setting isn’t found in the .suo file, the default startup project in the .sln would be used.
Actually, this has been suggested on Visual Studio’s UserVoice.
Why should it be a non-user-specific preference?
If I've got a solution with 10 files in, and one developer is primarily testing/using one of those tools, why should that affect what I start up?
I think MS made the right choice on this one. The project I want to start is far from necessarily the project that other developers want to start.
I wrote a little command line utility for Windows called slnStartupProject to set the Startup Project automatically:
slnStartupProject slnFilename projectName
I personally use it to set the startup project after generating the solution with cmake that always sets a dummy ALL_BUILD project as the first project in the solution.
The source is on GitHub. Forks and feedback are welcome.
If you are using GIT, you can commit the default SUO file and then mark it as unchanged using
git update-index --assume-unchanged YourSolution.suo
It works also if you want to have more than one project in your default start group. The only disadvantage that I know about is that this command must be run by everyone who don't want to commit the SUO file.

Categories