Visual Studio: Build order random? - c#

I've a solution containing 239 projects. I've currently the following issue:
When I do a "rebuild all" on the solution, after having done a full clean(delete of the output directory):
17>------ Rebuild All started: Project: AAA, Configuration: Debug x86 ------
18>------ Rebuild All started: Project: BBB, Configuration: Debug x86 ------
18>CSC : error CS0006: Metadata file 'E:\Dev\Trunk\Debug\x86\AAA.dll' could not be found
17> XmsCommon -> E:\Dev\Trunk\Debug\x86\AAA.dll
I understand the following:
Visual studio is multithreading the compilation(in my case, 4 assembly at a time)
I've no explicit "Project Dependency" specify(Right click on solution -> Project Dependencies)
What I don't understand
In this example AAA is a referenced project of BBB, for me, it's an implicit dependency, how would it be possible to correctly build BBB without being sure that AAA has been built correctly?
How should we manage this for a solution that makes 239 projects? It's hard enough to ensure that we don't make any reference to a wrong project, so if we always have to ensure the build orders, it becomes complicated.
A single note: I don't know if this is due to a recent change(of a project/visual studio/...), because it makes 2 years I work on this solution, and it's the first time that I came accorss this issue again and again.
So the question:
Is there a way to handle this without having to indicate each Project Dependency on the solution?
If not, how should we do this?
EDIT
After the comment, here is some additionals infos:
There is no compilation errors in AAA or BBB except it can't find the reference
We references projects and not dll(checked in one specific case where I was having the error.
In BBB.csproj, I've the following reference:
<ProjectReference Include="..\..\..\..\SomeOtherFolder\AAA\AAA.csproj">
<Project>{6241076B-05B3-4D5D-AFA9-46D41E1CEC3A}</Project>
<Name>AAA</Name>
<Private>False</Private>
</ProjectReference>
EDIT 2
I don't know if this is directly related, but when checking the Project Dependencies, I found that BBB is depending on CCC(but nothing is indicated for AAA. I'm wondering if there is a dependency specify, it basically ignore all the informations coming from the references? If I try to remove the CCC dependency, I got a message:
This dependency was added by the project system and cannot be removed
EDIT 3
I made an interessting discovery: In fact the error I've in the EDIT 2 is because this dependency has been added when creating the reference between the two projects.
For an unknown reason, it seems this dependency has not been created for one reference here. If I remove the project reference, then add the reference again to the same project, I now have this dependency(which I cannot delete).
I can't find where this "dependency is stored.
Any idea on how to "fix" this solution wide?

From your post you said that
"I've no explicit "Project Dependency" specify(Right click on solution -> Project Dependencies)" This implies that all of your references are to the compiled DLLs, and not to the projects.
I have seen this approach many times done by teams with large solutions (you have 239 projects) due to the slowness of VS to load that many project references.
The workarounds that I have seen used are:
Multiple Solutions for each sub-area of the primary solution, such as Entities, DAL, Logic, Service, etc.
Checking in DLLs (not recommended, but I have seen it) into Source to be used for faster builds. Once you change a code area you are responsible for replacing the DLL.
Configuring the Project Dependencies settings so that builds are done in proper order.
Dealing with the performance of the Project References (slow, but ensures build order
A single solution with 239 projects seems to go against the tenet of compartmentalizing your development into smaller modules, but that isn't always your decision...

After some investigation, I found the issue:
In fact Visual Studio should automatically add those dependency between the projects when referring one into a project. I can see that very easily by just adding a project reference. In addition, it seems that those "dependencies" cannot be removed(see my edit 2).
So the question I asked is how can I have some projects referenced and no dependency for some projects?
I checked that my references(at least some case I saw it wasn't working) and they were project reference and not dll.
Some of my colleague, with the exact same code(Get latest version of code without changes) were not having this issue, and were having the dependency displayed in Visual studio.
So I ended by removing the *.sdf file near my solution file(after having closed visual studio). I reopened and tadaa, all the dependencies have been recomputed by visual studio. Now we I rebuild, everything is a success directly.
I'm not sure of why it happens, I had some time to kill visual studio, maybe something was corrupted then.

I have seen this issue in a smaller, but highly inter-dependent solution. We solved this issue by reducing the Maximum number of parallel project builds lower until it predictably succeeds. Tools --> Options --> Projects and Solutions --> Build and Run.

I know this is not a solution, but you could turn your compile dependencies into runtime dependencies is you use Dependency Injection technologies, like MEF or Unity.
In this case, your projects have limited dependencies (Interfaces, Containers).
But I have to say, these technologies carry some side effects - like 'pseudo random' initialization and so on...

Related

Cannot build solution because of log4net dependency issues C#

I am currently working on my colleague's project that he wrote a few years ago. The project uses "log4net" assembly although I do not really need it or use it. Anyways, when I'm trying to build project, i get this error:
Severity Code Description Project File Line Suppression State
Error Unknown build error, 'Cannot resolve dependency to assembly 'log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=9fea11e3513f1a42' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.' VersionChecker C:\windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.WinFx.targets 268
I've tried to remove the assembly, and also tried to redirect assembly versions without luck. I don't find any trace to log4net anywhere in my project and don't have a clue how to remove it completely and manage to build my project..
Thanks in advance for your help!
Go to 'Manage Nuget Packages for Solution' from Tools menu of VS and check if you could uninstall it from there.
There are multiple ways of building projects. The most common way is to use Visual Studio only. If this is your case, then simply go through each project in your solution explorer and expand references. You should see all the references to your project. Simply highlight Log4Net and press the delete key. You'll need to go through all the code that references Log4Net and remove it.
The other scenario is that you're using an external build script, like msbuild to do additional compilation. If this is the case you'll need to wade through your build scripts. The details vary among implementation, but a starting point is to simply highlight the project in question in the solution explorer and press alt+enter to bring up the properties. Check the build events tab for additional build script info.

Adding a ProjectReference to a project that is not in the same solution

While doing some refactoring of our projects and solution files, i have separated some .sln files to contain less projects.
Occasionally i need to reference some projects from outside the scope of the current .sln file.
For example, my initial state was this:
SOLUTION A
PROJ A
PROJ B
After refactoring it would look like this:
SOLUTION A_NEW
PROJ A
SOLUTION B_NEW
PROJ B
My question is -- Is it possible to add a ProjectReference node to a project that is not defined in the same VS solution? (in my case, having PROJ A have a project reference to PROJ B).
Also, if it is possible, is that recommended?
I know that this is not possible from the VS IDE, only by editing the .csproj file manually.
You can't do this. A project reference includes an identifying GUID for the referenced project, which is maintained in the solution file in order to track solution build options and dependencies. If you try to reference a project that is not in the solution, Visual Studio will complain.
You can add a file reference to the assembly produced by a project that's not in the solution, of course.
UPDATE: Since this got downvoted, I'll refine my answer.
Though it's technically possible to craft a project file that references another project outside the same solution, Visual Studio won't help you to do it easily. One very good reason why it's a bad idea to do this (that I've observed) is that whatever Solution Configuration and Platform you're building (the referencing project) will be ignored if MSBuild decides to build the referenced project - the default Configuration and Platform specified in that referenced project file will be used instead. Thus you may end up with a mixture of binary types in different folders.
Temporarily add the project to the solution, add a reference to it, unload the project that now has a reference added to it, remove the referenced project, reload the project with the reference.
If you don't unload the project then the reference will be automatically removed by Visual Studio when the referenced project is removed.
As you can probably tell, Visual Studios not designed to do this and you'd be better defining a build order for the solutions and use assembly references instead.
You can definitely add a project to a solution A that is in solution B. There is not any problem with that. From my experience, it's not something that I usually have done or do, but sometimes need to. This can be especially true on large projects where you need different nodes of your architecture to reuse same code base.
Hope this helps.

Unity not finding dll references

We are doing a project that uses interfaces and Unity to resolve concrete implementations of classes.
My questions is the following: I need to get my dll's all into the same folder otherwise unity will not be able to resolve the interface etc. So according to me I have a couple of options:
1. Add the projects with the implementations as references and let VS copy the files to the output folder (for some reason this just feels like a hack)
2. Change the build location of all my projects to build to the same folder
3. Create a post build event to copy all the files needed to whereever they need to go
I have implemented to second option but this could lead to files in your build folder that should not be there. I am not a big fan of post build events, so I would like to ask from other people using Unity what they found to be the best solution for them.
Thanks in advance
The first approach sounds like the right one to me. Your project does depend on the implementation libraries; it doesn't express that dependency directly in code, but it requires them, so it seems reasonable to add a reference to them.
This is basically the same situation as where you've got three projects, where project A depends on project B, which depends on project C - you need to explicitly add project C as a reference within project A. Visual Studio doesn't work out transitive dependencies for you (at least it didn't the last time I checked).

"An assembly with the same simple name has already been imported" error without duplicate reference

I'm getting the following error:
error CS1704: An assembly with the same simple name
'Interop.xxx.dll, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null has already been imported. Try removing one of the
references or sign them to enable side-by-side.
Everything I've seen says that I am referencing two assemblies with the same name and I need to remove one of them. However, I've checked and I'm only referencing it once.
This also only happens when I'm using msbuild to build from the command line on my dev box. If I build through Visual Studio or do a clean build on our CI server I don't see this error.
I've tried completely removing all of my source and building from scratch to more closely resemble the build machine but no luck.
So it looks like I can't read today!
The project had a reference to the Interop and a COM reference that generated the "same" interop. So there were two and I just didn't search very well. I still don't understand why it worked in other places but this did fix it.
In the Error List window, the project that was triggering this error was listed in the Project column. I got around the error by doing the following:
I unloaded the listed project (right-click => Unload Project)
Opened the XML for edit (right-click the unloaded project => Edit {ProjectName.csproj}).
Searched for the offending .dll, and noticed it was listed multiple times in the XML
Removed the entire Reference tag related to the offending dll, and did so for every copy of the reference except the first one listed
The reason it was listed multiple times was because several referenced libraries used that dll. This shouldn't be a problem, in and of itself, so I'm not sure what caused this error to suddenly pop up for me. I'll update this answer if I figure that out.
In my case the duplicate entry was caused by a NuGet package reference and a direct file reference to the same assembly in the packages folder. I am not sure how the project got into this state, but unloading the project and searching the XML file for the offending assembly name resolved the issue for me.
Note that in my case this started happening after updating a NuGet package to a newer version with no other changes to the project, so this maybe caused by a bug in NuGet.
If this is a web project, are there any strong-named references to the other version there? Those won't show up as a project dependency, but will cause a run-time error like you describe. Hope that helps
I had this problem but in my case, I had an old copy placed in the current folder for the EXE loading my component, that was loaded together with the current one, that was loaded by hand from my projects folder. Deleting that old copy solved my problem.
I used Debug > Windows > Modules window to see which modules were loaded at that time and that solved my problem.
For others facing the same as me: if building via command line using property AssemblyName, it will overwrite all assemblies generated by all solution projects - in other words, you will end up with (N -1) assemblies named the same where N is the no. of projects - the startup one (which generally will generate an exe).
This happens because all build command line properties are global and overwrite any project-specific setting. See this and this.
From the msdn link mentioned above:
Global properties are properties that are set by using the
/property switch on the command line, or properties that are set by
the integrated development environment (IDE) before a project is
built. These global properties are applied to all projects that are
built by using this Engine.
In my specific case, where Jenkins is the CI tool, I ended up adding a windows batch command at the end to rename the .exe only to what I originally intended when passing the AssemblyName parameter.
For those developing UWP projects that have project references that include specifically the Microsoft.Windows.SDK.Contracts nuget package (or other dependencies that reference it), this is a common error when the version of the SDK contracts is targeting a different version of the runtime to how your project is configured.
For instance, when targeting Windows 10, version 1903:
Any dependencies or reference projects should target or at least support the same runtime version.
it is common thought process to update all NuGet packages when a new stable version is available, but this is not always a helpful practise on its own. Just because a new stable version of a package is available does not mean that you should or that you can easily use that version.
Even though this package for SDK contracts has a stable update, it is not compatible with my main project configuration, Nuget does not know this so it allows the update.
This package is specifically designed to provide windows dlls for project types that DO NOT have windows platform targeting support, it copies the same dlls that are included by the UWP targeting config. By installing later versions of the package the references from the satellite project will be included in the output along with those provided due to platform targeting, ultimately causing OPs error.
There are similar SDK and targeting packs for Windows IoT Device Runtimes, this information should help you identify and resolve those issues if you get stuck on this issue as my team often does :)
In my case, the issue was on wrong characters in the ProjectReference section of my csproj file.
Background
I have a project that references another library I maintain, which I publish as a NuGet package.
Whenever I make changes to my library, I usually reference the local dll in my project to test and make sure everything looks good before I publish the library as a NuGet package.
When testing, I just comment out the PackageReference line and uncomment the ProjectReference one so it references my local dll, like so:
<ProjectReference Include="..\..\my-class-library\MyClassLibrary.csproj" />
<!--<PackageReference="MyClassLibrary" Version="2.0.1"/>-->
Root cause
I had the slashes inverted, so I was using / rather than \ in the path, like so:
<ProjectReference Include="../../my-class-library/MyClassLibrary.csproj" />
Once corrected, the issue went away.
Try this instead: remove Interop.xx.dll from the reference section in Solution Explorer and Rebuild the project
In our case this error was shown when we had a duplicate reference inside the .csproj file (although I have no idea how this happened).
The difference to an already posted answer is that, in our case, one was a project reference and another one was direct binary reference to a dll.
Once we removed one of those, project correctly compiled.

Dealing with dependencies in a large project... Is it possible to reliably alter build order without using project dependencies in C#/VS2008?

I've got a legacy project in VS2008 that we're about to start refactoring for better componentization. The references between the 150 projects in the solution are messy, so as a starting point, I'm trying to at least get to a point I can have a few projects use binary references to other projects while others use project references. (For build time reasons)
To Illustrate, given projects A, B, and C, I'd like to see...
A references C.dll
B references C.csproj
Now the problem is I need to make sure that C.csproj builds before A.csproj. I know I can control build order using project dependencies, but this appears to cause exactly the behavior I'm trying to avoid... building A always causes C to build. I'm sure I can monkey with the proj or sln files directly to get things to build in the order I want, but I'm also sure that will get overwritten in short order by VS's automatic magic.
Is there some way to control this order reliably, or am I missing something obvious here?
Thanks...
Separate related components (.csproj) into individual solutions. This enforces binary references across package boundaries. It also forces you and other developers to group components by layer.
Then use your build process to build solutions in correct order starting with the least dependent packages.
In my estimation, from an SCM standpoint Solution == UML Package == Merge Module (all solutions create a merge module)
You could make custom msbuild files instead of relying on the .csproj and .sln files, such that, depending on the target chosen, it will only build certain assemblies. It would require learning msbuild if you don't know it already though.

Categories

Resources