ResolveAssemblyReference slowness -- msbuild speed? - c#

I have a project with maybe 200+ projects in it. It's an old bird. To make local builds faster, I ran a diagnostic build. Seems resolving assembly and project references is taking msbuild awhile. VS seems to do this fast, is there a way to get MSBuild to use a cache for these references, or to somehow resolve it faster?
It seems MSBuild wouldn't need to resolve the assembly reference(s) this often with an incremental build, right?
Is there a way to get MSBuild to report its internal dependency tree for this?

VS uses the same MSBuild engine to perform the build, so whatever performance you observe from VS, you should be able to achieve by starting build from command line using MSBuild.exe.
There are couple of points to keep in mind, that might explain difference in build speed between VS and command line:
If you build "Project Only" in VS, i.e. right click on the project node, select "Build Project (this)" from "Project Only" menu, then the build skips building any referenced projects. This is the fastest way to do incremental build, but you have to know ahead of time that all dependencies are up-to-date.
If you want to replicate this from command line, just pass parameter BuildProjectReferences=false. E.g:
msbuild myproject.csproj /p:BuildProjectReferences=false
The defaults for VS might be set for multi-proc build, which in many cases greatly increases build speed. However on command line, the defaults are always to perform single-proc build, so that would appear much slower than VS. Always pass in /m to the msbuild command line. E.g.:
msbuild MySolution.sln /m

Related

Preventing VS 2019 from rebuilding a solution though no source has changed

I am trying to track down a VS 2019 build issue for a few weeks which drives me crazy. I have a C# project (targeting .Net Framework 4.8) which VS rebuilds regularly even when nothing has changed. The project is not very complex and has no specific dependencies, but a postbuild event which must always be executed. Hence I used the approach described in this answer, which forces msbuild to do the "up-to-date" check instead of the VS IDE. This has worked well for years, but started to make trouble a few weeks ago.
To create a minimal reproducible example:
use the VS project wizard to create a trivial "hello world" console app, .Net Fw 4.8, AnyCpu
add the following lines to the csproj file:
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
change the "Run Post Build" setting in the IDE's project settings to "On Build Success" (or back to "Always", this does not really matter), save the settings
The Postbuild action is intentionally left empty, one can add arbitrary actions here, but even an empty action will produce the issue.
When I choose to rebuild the solution in the IDE (using Ctrl-Shift-B), without touching anything the source code, the executable is recreated. This effect occurs when the time between two consecutive builds is approx. 10 seconds or more, when I rebuild the solution quicker, the exe file stays untouched.
To make the effect more visible, I set "AssemblyVersion("1.0.0.*"), stripped the "AssemblyInformationalVersion" attribute from AssemblyInfo.cs, so the build system assigns a new build number to the exe file with each new creation, which allows to observe the effect in the Windows Explorer more easily (by activating the "File Version" column in the Explorer view).
Note this effect does not seem to occur when I comment out either the post build event, or the DisableFastUpToDateCheck setting.
I observed this with VS 2019 V16.11.9 and V16.11.10 (currently the latest versions in the "2019" product line).
In my real project, this happens for a central DLL inside a solution where more then 70 other projects depend on, including a large C++/CLI dll, resulting in a build time of ~2 minutes - every time I only want to start the debugger, since this causes a new build! And yes, I also tried to set the "project build output" settings to "Diagnostic", but could not find anything suspicious in the large amount of messages.
PostBuildEvent is problematic and 'old style' since it doesn't define its inputs and outputs. Because of that msbuild can't calculate whether it caused any files to change and thus forces a rebuild.
By replacing the postbuildevent with a custom target and by correctly specifying the inputs and outputs of the target, MSBuild can check whether any of the inpu ts have changed and whether the outputs are up to date to properly decide to skip the build altogether.
See:
https://learn.microsoft.com/en-us/visualstudio/msbuild/incremental-builds?view=vs-2022
PostBuildEvent is also no longer supported in new style SDK projects. Visual Studio will now automatically generate a new target when you setup a postbuild event in the UI.
Starting with jesshouwing's answer, and using this information from Microsoft how to extend the VS build process, I implemented this workaround: in the csproj, I added the following section the end:
<Target Name="CustomAfterBuild" AfterTargets="Build"
Inputs="... input for postbuild step ..."
Outputs=" ... output of postbuild step ..">
<Message Text="... some message here ..." />
<!-- here are the post build actions -->
</Target>
This seems to work well for now without the nasty effects. The only drawback here is that this custom build step does not show up in the Visual Studio project editor, but I can work with that.

MSBuild clean operation fails due to missing dependency

I have a visual studio 2010 solution file containing a number of project files. If I clean the solution using devenv then the clean completes successfully, however, if I use MSBuild, two of the project files fail to clean due to a missing dependency, error MSB3395. If I run Clean a second time, immediately after the failure, the clean completes without errors.
Our build using MSBuild succeeds.
Task "UnregisterAssembly" (TaskId:204) ...
...
error MSB3395: Cannot unregister assembly
"C:\Build\Dir\MyFile.dll". Could not load file or
assembly 'MyOtherFile, Version=10.0.0.414,
Culture=neutral, PublicKeyToken=266e457ed35afd03' or one of its
dependencies. The system cannot find the file specified.
[C:\Build\Dir\ProjFolder\MyFileProj.vbproj]
Yes, this assembly is a COM interop assembly and so the build registers the assembly. If I delete the UnmanagedRegistration.cache files associated with the two problem areas then the clean finishes without problems. However, these files are not unregistered and registry fills up with old COM registrations. I am not certain of the impact on future builds either.
I have read the article for VS2008 projects here https://blogs.msdn.microsoft.com/visualstudio/2010/12/21/incorrect-solution-build-ordering-when-using-msbuild-exe/
However, I don't think this applies in this case because this build process has been cleaning and building properly for months.
I have also read: https://www.experts-exchange.com/questions/26259422/msbuild-can't-clean-project-with-C-COM-component-dependant-on-other-NET-library.html. I attempted to clean the two different projects before cleaning the solution affected by this, but this too failed. e.g.,
msbuild ".\ProjDir\MyProj.csproj" /t:clean /p:configuration=Release /fl /flp:logfile=".\..\LogFiles\msbuildClean.log";verbosity=diagnostic
I have tried reverting to a previous SVN revision before the problem began to show but I still get the same error. My build machines are on Virtual Machines, and I even tried reverting the build machine to a snapshot prior to the problem showing up, but still the error would show up.
I have been at this for two weeks now, and my only recourse is to use devenv to clean the solution, which is very slow. My only idea at this time is that when using msbuild that dependencies for COM interfaces are not handled correctly for a clean but I have no idea how to fix the problem.
I can reproduce the problem using the VS2010 CMD Prompt. Below is an example cmd line that I use
msbuild "A Solution.sln" /t:clean /p:Configuration=Release /fl /flp:logfile=".\..\LogFiles\msbuildClean.log";verbosity=diagnostic
msbuild "A Solution.sln" /t:build /p:Configuration=Release /fl /flp:logFile=".\..\LogFiles\msbuildBuild.log";verbosity=diagnostic
Within the vbproj files there are PropertyGroups with a Release configuration condition. All of these include <RegisterForComInterop>true</RegisterForComInterop>. If I set this value to false, then the error goes away because there isn't anything to unregister. However, I need the .tlb files in order to compile our vb6 project.
So, are there any problems for me to just set this to false and then use Regasm to register the assemblies post build, and unregister before a clean? Does anyone have any ideas why MSBuild would suddenly have problems with this process when for months the build has run successfully?
Thanks.
UPDATE
If I use msbuild to clean the first problem project, this clean works
successfully.
The second project however fails to clean properly
When cleaning the first project, ProjA, it also removes dependent
files from other projects, ProjB.
When I clean the second problem project, ProjC, it also has dependencies on ProjB.dll, and this file is missing.
QUESTION
- How do I keep MSBuild from removing files required by other projects?
In the end I have to go with stijn's answer.
I never did find the cause - something in the msbuild clean process seems to delete the files required to unregister an assembly.
I had tried to create a msbuild task to unregister the assemblies first, but that too failed.
In the end I coded a Powershell script that searched a path for *.unmanagedregistration.cache files. I then can determine the .dll file name from the unmanagedregistration.cache file and then once the code runs regasm /unregister, it will remove the file.
Just perform the clean as administrator. If using visual studio, open it as administrator and it should perform the clean action.

Visual Studio Rebuilds unmodified projects

So, as the title reads, I have a VS2010 solution with ~50 projects in it right now. If I make a change to a "top level" project that nothing references then VS still rebuilds all 50 projects. I'm running Visual Studio 2010 Ultimate without any add-ons. I am using ILMerge to consolidate all of the projects into a single file.
I have verified this by checking the time stamps of the lower level dlls and see that they are indeed rebuilt even though their code wasn't touched.
I've read all responses and comments for:
Visual Studio 2008 keeps rebuilding
Visual studio keeps building everything
Strange VS2010 build glitch occurs in my solution
Reasons for C# projects to rebuild in Visual Studio
But most of them just offer suggestions on unloading projects to speed up build times but nothing concrete as to a fix. I'm trying to figure out why VS thinks these dependent projects need to be rebuilt when they don't and fix it.
I've turned on 'Tools > Options > Projects and Solutions > Build and Run > Only build startup projects and dependencies on run' but with no effect.
Also, if I just rebuild a "mid-level" project that only has 8 (in)direct dependencies then it still builds all 8 projects even though ILMerge isn't invoked and none of the dependent projects have been modified.
Thank you everyone for any insight you may be able to provide.
Added
To test some of the suggestions I created a new WinForms project from scratch. I then created two new projects inside that solution. I copied all of the code and resources (not project file) from my two 'lowest level' projects into the two brand new projects (I did this by dropping the files and folders from Explorer onto the project in Visual Studio).
The lowest project, let's call it B, did not reference any other project. The next project, A, referenced B only. So once I added the required .NET and external assembly references to the projects then the solution would build.
I then had my new WinForm project reference A and did a full build. So the ref chain is:
WinForm -> A -> B
I then modified WinForm only and did a standard build (F6). As before, Visual Studio rebuilt all three projects.
After some systematic eleminiation of source files in project B I found that if I removed my Resources.Designer.cs and Resources.resx (and commented out the code that made use of the .Properties.Resources object of those resources) then a modification of WinForm would no longer rebuild the entire solution and would only rebuild WinForm.
Adding the Resources.resx and Resources.Designer.cs back to project B (but leaving the referenced code commented out so that nothing was making use of the resources) would re-introduce the full build behavior.
To see if perhaps my resource files were corrupted, I deleted them again and then created a new one (via Project Properties -> Resources) and re-added the same resource as before, which was a single Excel file. With this setup the full rebuild would still occur.
I then removed the single resource, but left the resource file in project B. Even with no resources added, but the resource file still in the project, the full (unneeded) rebuild would occur.
It appears that just having a resource file added to a (.NET 3.5) project will cause Visual Studio 2010 to always rebuild that project. Is this a bug or intended/expected behavior?
Thanks all again!
Open Tools - Options, select Projects and Solutions - Build and Run in tree, then set "MSBuild project build output verbosity" to Diagnostic.
This will output the reason for building a project, i.e.
Project 'ReferencedProject' is not up to date. Project item
'c:\some.xml' has 'Copy to Output Directory' attribute set to 'Copy
always'.
or
Project 'MyProject' is not up to date. Input file
'c:\ReferencedProject.dll' is modified after output file
'c:\MyProject.pdb'.
In this case the fix is to copy some.xml only if newer.
Pre and post build events can trigger build as well.
While I don't think this is a fix, it is a workaround that has worked for my situation...
I originally had about 5 projects out of 50 that contained a Resources section. These projects would always be rebuilt and thus anything that they depended on would also be rebuilt. One of those 5 projects was a "base" level library that 48 of the other projects referenced, thus 96% of my project would be rebuilt every time even if it didn't need it.
My workaround was to use dependency injection, interfaces, and a dedicated "Resources" project. Instead of having those 5 projects reference their own Resources object, I created an interface in each project that would supply the desired resources. Then, the classes that needed those resources would require that interface be passed in during their creation in the constructor (constructor injection).
I then created a separate "Resources" project that had an actual Resources section like normal. This project only contained the resources themselves, and a class for each interface that was needed to provide those resources via an interface. This project would reference every other project that had a resource dependency and implement the interface that the project needed.
Finally, in my "Top Level" project which nothing referenced (and where the exe was actually built and my composition root lives) I referenced the "Resources" project, wired up the DI, and away we went.
This means that only two projects (the "Resources" and the "Top Level") will be rebuilt every time, and if I do a partial build (Shift-F6) then they won't get rebuilt at all.
Again, not a great work around, but with 48 projects being built every time a build would take about 3 minutes, so I was losing 30 to 90 minutes a day with needless rebuilds. It took awhile to refactor, but I think it was a good investment.
Here is a simplified diagram. Note that the dependencies from Main.exe to Proj1 and Proj2 are not shown in order to reduce clutter.
With this design, I can do a build of Proj1 or Proj2 without triggering a full rebuild, since they don't have any dependencies on a Resources section. Only Main knows about the Resources implementation.
This happens when a project has a file that doesn't really exist.
The project can't determine if the file was changed (because it's not there) so it rebuilds.
Simply look at all the files in the project, and search for the one that doesn't have an expandable arrow near it.
I had the same issue in VS 2015.
What did the trick for me is:
One project was referencing itself copy in some other project bin (magic, yes). This kind of stuff could be found when switching to diagnostic build output (in build options) and then trying to build projects one by one from the top of projects hierarchy - if you see the project that rebuilds even if nothing has been changed then see it's references.
I've changed all "copy always" files in all projects to "copy if newer". Basically, in all .csproj files replace <CopyToOutputDirectory>Always</CopyToOutputDirectory>
to <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Then I've disabled NTFS tunneling as described in this article with this powershell script:
New-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "MaximumTunnelEntries" -Value 0 -PropertyType "DWord"
After that I needed on rebuild and it seems working for now.
In my case the culprit was "Copy Local" setting of a referenced dll set to true and "Copy to Output Directory" setting a file set to Copy always.
For .Net Core Projects, all solutions above are not working.
I've found the solution. In case you are using Visual Studio 2019:
Build the solution twice
Turn on Tools -> Options -> Projects and Solutions -> SDK-Style Projects -> Logging Level -> Verbose
Clear the output window
Build your start project
Inspect the output window. All the string starting with FastUpToDate
You will find some project items that are making your project not up to date.
Fix these issues and try again from step 1. If your fixes are correct, you will achieve Build: 0 succeeded, 0 failed, {n} up-to-date, 0 skipped in the last string of build output.
The MSBuild team is collecting documentation about investigating build incrementality issues here:
https://github.com/Microsoft/MSBuild/wiki/Rebuilding%20when%20nothing%20changed
UPDATED LINK: https://github.com/dotnet/msbuild/blob/main/documentation/wiki/Rebuilding-when-nothing-changed.md
Based on your observations, it sounds like you have projects expressing dependencies to other projects in a way that isn't obvious. It is possible for orphaned dependencies to remain in project files without being apparent in the UI. Have you looked through a misbehaving project file after opening it in a text editor? Checked solution build dependencies?
If you're not able to spot anything, try recreating one of your projects from scratch to see if the new project exhibits the same problem. If the clean project builds correctly, you'll know that you have unwanted dependencies expressed somewhere. As far as I know, these would have to be in the project file(s) or the solution file, unless you have makefiles or other unusual build steps.
Another problem that frequently happens is when some item in your solution has a modified stamp that is in the future. This can happen if you set your clock forward, and then set your clock to the correct time. I had this happen while installing Linux.
In this case you can recursively touch all the files using git bash (yes, in Windows):
find . -exec touch {} \;
I've finally found one more culprit that I had hard time finding by increasing the build log verbosity.
In some cases, MSBuild looks for vc120.pdb in the output folder, and if this file doesn't exist, it will rebuild the entire project. This occurs even if you have disabled debug symbol generation.
The workaround here is to enable debug symbols and let this file get generated, then disable the setting again without deleting the PDB file.
I had this same problem and it turned out to be related to a couple of project that had a copy local reference to a dll in their own output directory.
The key to finding this was having diagnostic output set for the build output, but also knowing what to look for in the log. Searching for: 'not up to date' was the key.
Here is an answer from VS2010 always rebuilds solution?
This issue is solved by changing the project files, cleaning solution,
deleting all bin folders by hand, restarting Visual studio and
rebuilding everything.
I had the same issues with you.
I found that it came from some deleted files.
When I had removed the files from my project, the issues was gone.
Regards.
For this category of build problems setting MSBuild output verbosity to 'diagnostic' is indeed a necessary first step. Most of the time the stated reason for the re-builds would be enough to act upon, BUT occasionally MSBuild would erroneously claim that some files are modified and need to be copied.
If that is the case, you'd need to either disable NTFS tunneling or duplicate your output folder to a new location. Here it is in more words.
I had the problem of Visual Studio rebuilding projects when upgrading from Visual Studio 2015 to 2017 and I add this answer for the benefit of those who might experience similar problems, as it does not seem to be documented anywhere.
In my case, the problem was that all projects in the solution had the same intermediate Output path (obj). The file GeneratedInternalTypeHelper.cs gets generated by all projects containing XAML. Up to Visual Studio 2015, the build process apparently did not check for the file date of this file and thus no problem with it occurred. With VS2017 the file date of this file is checked and because a later project in the build process will overwrite it (with the same content), the earlier project will re-build, re-triggering the later build, ad infinitum.
The solution in this case is to ensure that all projects have differing intermediate output directories, which will make the problem go away.
In my case (mixed C#, C++/CLI and native C++ solution) , some C++ projects were being re-linked even if nothing had changed. I spent ages trying to work out what was happening. In the end I worked out from the "Command Line" option that the PDB output path (option /Fd) could not handle the folder setting $(IntDir). I removed that - an empty value will do the default correctly - and my issue went away.
As others have noticed, a likely reason is that CopyToOutputDirectory is set to Always. This can be fixed simultaneously in all project files by applying the powershell script below:
$folder = "C:\My\Solution\Folder"
$csvFiles = Get-ChildItem $folder *.csproj -rec
foreach ($file in $csvFiles)
{
(Get-Content $file.PSPath -Encoding UTF8 -Raw) |
Foreach-Object { $_ -replace "<CopyToOutputDirectory>Always</CopyToOutputDirectory>", "<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>" } |
Set-Content $file.PSPath -Encoding UTF8 -NoNewline
}
Files that do not exist are a problem and obviously files producing no output as well. That can happen, wenn you have a resource file in a static library. (C++)

Visual Studio Long wait before Starting to build

We have a moderately sized solution, with about 20 projects. In one of them I have my business entities. On compiling any project, visual studio waits and hangs about one and a half minutes on this BusinessEntities project.
I tried our solution in SharpDevelop and it compiles our complete solution, in 18 seconds. Similar timing with MSBuild.
My guess is that VS is trying to find out if the project needs a compile, but this process is about 15 times slower than actually performing the compile!!
I can't switch to the great sharpdevelop, it lacks some small, but essential requirements for our debugging scenarios.
Can I prevent VS from checking this project, And have it compile the projects without such a check, just like sharpdevelop?
I already know about unchecking projects in configuration management to prevent building some projects, but my developers will forget they need to compile this project after updating to latest sources and they face problems that seem strange to them.
Edit: Interesting results of an investigation: The delay happens to one of the projects only. In configuration manager I unchecked all projects, then compiled each of them individually. All projects compile in a few seconds!! The point is this: if that special project is built directly, compiles in a few seconds, if it is being built (or skipped, because it is up-to-date) as a result of building another project that depends on it, VS hangs for about a minute and half, and then decides to compile it (or skip it). My conclusion: Visual studio is checking to know if any files are changed, but for some reasons, for this special project it is extremely inefficient!!
I'd go to Tools -> Options -> Projects and Solutions -> Build and Run and then change the "MSBuild project build [output|build log] verbosity" to Diagnostic. At that level it will include timings which should help you track down the issue.
We had the same problem with an ASP.NET MVC web project running in Visual Studio 2013. We build the project and nothing happens for about a minute or so and then the output window shows that we are compiling.
Here's what fixed it... open the .csproj file in a text editor and set MvcBuildViews to false:
<MvcBuildViews>false</MvcBuildViews>
I had to use sysinternals process monitor to figure this out but it's clearly the cause for my situation. The site compiles in less than 5 seconds now and previously took over a minute. During that minute the Asp.net compilation process was putting files and directories into the Temporary Asp.net Files folder.
Warning: If you set this, you'll no longer precompile your views so you will lose the ability to see syntax errors in your views at build time.
There is the possibility that you are suffering from VS inspecting other freshly built assemblies for the benefit of the currently compiling project.
When an assembly is built, VS will inspect the references of the target assembly, which if they are feshly built or new versions, may include actually loading them in a .Net domain, which bears all the burdens of loading an assembly as though you were going to run it. The build can get progressively slower as it rebuilds more and more projects. When one assembly becomes newer the others do a lot more work. This is one possible explanation for why building by itself, versus already built, versus building clean, all have seemingly relevantly differing results. Its really tht the others changed and not about the one being compiled.
VS will 'mark down' the last 'internal' build number of the referenced assembly and look to see if the referenced assembly actually changed as it rolls through its build process. If its not differnt, a ton of work gets skipped. And yes, there are internal assembly build numbers that you dont control. This is probalby not in any way due to the actual c# compiler or its work or anything post-compile, but pre-compile steps necessary for the most general cases.
There are several reference oriented settings you can play with, and depending on your dev, test, or deployments needs, the functional differences may be irrelevant, however may profoundly impact how VS behaves and how long it takes during build.
Go to the references of one of the projects in Solution Explorer:
1) click on a reference
2) open the properties pane if its not (not the Property Pages or the Property Manager)
3) look at 'Copy Local', 'Embed Interop Types', 'Reference Output Assembly'; those may be very applicable and probably something good to know about regardless. I strongly suggest looking up what they do on MSDN. 'Reference Output Assembly' may or may not show in the list.
4) unload the project, and edit the .proj file in VS as text. look for the assembly reference in the XML and look for 'Private'. This means whether the assembly referenced is to be treated as though its going to be a private assembly from the referencing assemblies perspective, vs a shared one. Which is sort of a wordy way of saying, will that assembly be deployed as a unit with the other assemblies together. This is very important toward unburdening things. Background: http://msdn.microsoft.com/en-us/magazine/cc164080.aspx
So the basic idea here is that you want to configure all of these to be the least expensive, both during build and after deployment. If you are building them together, then for example you probably really don't need 'Copy Local'. Id hate to say more about how you should configure them without knowing more about your needs, but its a very fine thing to go read a few good paragraphs about each. This gets very tricky however, because you also influence whether VS will use the the stale old one when resolving before the referenced one is rebuilt. As a further example explaiing that its good to go read about these, Copy Local can use the local copy, even though its stale, so having this set can be double bad. Just remember the goal at the moment is to lower the burden of VS loading newly built assemblies jsut to compile the others.
Lastly, for now, I can easily say that hanging for only 1.5 mins is getting off very lucky. There are people with much much worse build times due to things like this ;)
Some troubleshooting idea's that have not been mentioned:
Clean solution?
Delete Obj and Bin folders plus the .suo file? FYI, neither Clean nor Rebuild will delete non-build files, eg files copied during a pre-build command.
Turn off VS scanning outside files. Options > tools > environment > document > detect when file is changed outside the environment?
Rollback SVN history to confirm when it started to occur? What changed? If the project file on day 1 takes the same time, recreate the project, add all the files and build.
Otherwise could you please run Process Monitor and let us know what Visual Studio is doing in the prep-build stage?
Sounds silly, but remove all breakpoints first. It sped up my pre-build checks massively - still don't know why though.
Based on the (limited) information provided one possibility is that there could be a pre-build action specified in the project file that is slow to compile.
Try disabling platform verification task as described here.
If your individual projects are compiling correctly then all you can do is change order of compilation by setting dependent projects explicitly in configuration.
Try to visualize your project dependency hierarchy and set dependent projects. For example, if your business entities project is referenced in each project, then in configuration of each project, this project must be selected as dependent.
When an explicit build order is not set, visual studio is analyzing projects to create an order of building project. Setting explicit dependent projects wiki make visual studio skip this step and use the order provided by you.
With such an extreme delay on a single project and no other avenue seeming to provide a reason I would attempt to build that specific project while running procmon from sysinternals and filter out all the success messages. You could probably also narrow it down to just the file system actions as well. From your description I might guess that the files are being locked by an external source like the event collection or workflow management process services.
Other things to consider would be whether or not this is a totally clean build machine or if it has been used to perhaps test the builds as well? If so, is there a chance that someone mapped an IIS application path to the project directly or registered it as a service location?
If you run procmon and see no obvious locks or conflicts I would create a totally new solution and project and copy the files over to see if that project also has the same delay. If it does have the same delay I would create a sample project of the same type but generic data (essentially empty) and see if that too is slow. If the new project with the same files builds fine you can then diff the directories to see what the variance is that causes the problem (perhaps a config or project setting).
For me, thoroughly disabling code analyzers helped per instructions here:
https://learn.microsoft.com/en-us/visualstudio/code-quality/disable-code-analysis?view=vs-2019#net-framework-projects.
I thought my code analyzers were already off, but adding the extra xml helped.
Thanks Kaleb's for the suggestion to set "MSBuild project build [output|build log] verbosity" to Diagnostic. The first message took more than 10 seconds to display:
Property reassignment: $(Features)=";flow-analysis;flow-analysis" (previous value: ";flow-analysis") at C:\myProjectDirectory\packages\Microsoft.NetFramework.Analyzers.2.9.3\build\Microsoft.NetFramework.Analyzers.props (32,5)
Which led me to the code analyzers.
Just in case someone else trips into this issue:
In my case the delay was being caused by an invalid path entry in "additional include directories" that referred to a non accessible UNC location.
Once this was corrected, the delay disappeared.

Build or Rebuild on the build server (CI server)

I am running TeamCity to build a .NET project (several projects to be more exact).
Should i be using Rebuild target or Build target?
I would like to minimize the build time, while not producing any newer versions of projects that haven't changed.
Is this safe practice to use "Build" target? what if the previous project outputs were erased? how do i verify that i can be doing this safely?
You should use rebuild if you need to rebuild all the projects, for instance in order to get coherent timestamps or version numbers (though usually, a change in a linked AssemblyInfo.cs will trigger a build as well.)
Build is completely safe even if the build output from a previous build is gone, or even if the build happens to be done on a new build agent which has no build output. In that case, all necessary projects will be built.
However, you might have custom MSBuild steps in your sln/csproj files that depends on a (Re)build, in which case you need to be more careful, but other than that, go for Build if you want to.
You should always perform rebuild operations on Continuous Integration servers.
Contrary to what you may read, it is possible to have leakage from a prior build into the current one. The leakage is almost never the result of failing to compile source code to binaries, but depending on which tool you're using to perform the build, there may be non-code files that don't get copied over because they already exist in the output directory, or deleted files that aren't removed from it.
For similar reasons, if you can afford the cost of execution time, you should also always clean the source tree before the build. Either destroy it and check out a clean copy, or revert any changes and delete any files not under source control. If you don't do this on every build, at least do it on "idle time" builds (e.g., overnight or weekend builds), and on the builds you intend to actually deliver to customers or deploy into production (and ideally into QA).
Build produces everything needed to run the project, keeping non-changed assemblies. Rebuild forces a complete build of any assembly involved. Unless for specific circumstances (version number, dependent process on something), it is safe to use build to minize time spent.
You should use Build to build your project incrementally. It is completely safe.

Categories

Resources