Reputation: 4807
I am experiencing a crash in my app which I believe is ultimately caused by having two .csproj files in the same folder. I suspect this may be causing problems since the files in the obj folder do not specify which .csproj they belong to. Is it possible to have two csproj files in the same folder if they both use NuGet references? The files in the obj/ folder seem to suggest that is not a good idea.
I would like to using a library (Common.Standard.csproj) on two separate projects. For reasons which would take a long time to explain, one project needs to reference an older set of nuget packages, while the other project needs newer. To solve this, I created a copy of Common.Standard.csproj which I called Common.MobileStandard.csproj. Both .csproj files are identical except that one references a different set of nuget packages.
My application crashes when I run it, and I have a missing method exception, which I believe is caused by it using the wrong .dll. I've noticed a few other symptoms which I believe are caused by the same root problem. For example, Visual Studio shows a different set of NuGet packages being referenced in the Solution Explorer vs. compared to the .csproj file:
The files shown in Visual Studio's Solution Explorer match the NuGet package references in the other .csproj which is not referenced:
I believe this may be caused by the files stored in the /obj folder. Notice that the "project" files do not specify which .csproj they belong to, so perhaps a single set of "project" files is created despite there being two .csproj files outside of the obj folder?
Am I correct in assuming that this is causing the confusion in Visual Studio, and also the missing method exception at runtime? If so, does that mean that two .csproj files should never share the same folder?
I followed suggestions below to use a different in the Common.MobileStandard.csproj so that each .csproj would have its own obj folder, as shown here:
This did produce an objmobile file as expected:
However, the objmobile folder remains empty wnen I build the Common.MobileStandard project. Furthermore, if I delete the contents of the obj folder (the non-mobile one), the nuget packages in Visual Studio get cleared out. It seems as if Visual Studio is always looking in the obj folder rather than in the objmobile, even though the .csproj tells it to look in the objmobile, as shown in the following animation:
I believe the only solution here is to move the .csproj to a separate folder unless I'm mistaken in this being a Visual Studio (or msbuild) bug.
It seems that the issue listed in Update 1 is expected behavior. After changing , the following is shown in the output when building the project:
3>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(858,5): warning MSB3539: The value of the property "BaseIntermediateOutputPath" was modified after it was used by MSBuild which can lead to unexpected build results. Tools such as NuGet will write outputs to the path specified by the "MSBuildProjectExtensionsPath" instead. To set this property, you must do so before Microsoft.Common.props is imported, for example by using Directory.Build.props. For more information, please visit https://go.microsoft.com/fwlink/?linkid=869650
To fix this, I can create a new file named Directory.Build.props with the following contents:
<Project>
<PropertyGroup>
<MSBuildProjectExtensionsPath>objmobile</MSBuildProjectExtensionsPath>
</PropertyGroup>
</Project>
This does solve the issue in Update 1 (why nuget is still reading from obj) but it brings up a second question - how can I have a different Directory.Build.props for each .csproj file?
Upvotes: 5
Views: 1898
Reputation: 5762
It is not possible to have a different Directory.Build.props
per project in the same folder. However, you can reference $(MSBuildProjectName)
and it evaluate uniquely for each project in the same directory.
Example Directory.Build.props
with conditions:
<Project>
<PropertyGroup Condition="'$(MSBuildProjectName)'=='Common.MobileStandard'"
<MSBuildProjectExtensionsPath>objmobile</MSBuildProjectExtensionsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(MSBuildProjectName)'=='Common.Standard'">
<MSBuildProjectExtensionsPath>objstandard</MSBuildProjectExtensionsPath>
</PropertyGroup>
</Project>
Simpler example:
<Project>
<PropertyGroup>
<MSBuildProjectExtensionsPath>obj$(MSBuildProjectName.Replace('Common.', ''))</MSBuildProjectExtensionsPath>
</PropertyGroup>
</Project>
Upvotes: 0
Reputation: 3164
It seems I can set BaseIntermediateOutputPath
in the .csproj
file if I structure it like this:
<Project>
<PropertyGroup>
<BaseOutputPath>bin-example</BaseOutputPath>
<BaseIntermediateOutputPath>obj-example\</BaseIntermediateOutputPath>
<RestorePackagesPath>packages-example\</RestorePackagesPath>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk"/>
<!-- stuff VS normally puts in <Project> -->
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk"/>
</Project>
That is, I pulled the Sdk
attribute out of the Project
tag and converted it to imports, so that I could set things before importing Sdk.props
.
I did that based on the page here: https://learn.microsoft.com/en-us/visualstudio/msbuild/how-to-use-project-sdk?view=vs-2022
In a test rebuild which makes use of nuget packages, this does not touch the obj
folder.
It seems .NET Framework projects are structured differently, and I don't think this approach will work there. Hopefully you don't need more than one Framework project in the same directory.
Upvotes: 4