Visual Studio project reference that isn't version specific at runtime - c#

We have a multi-project solution. The references between projects are done as Project References rather than Assembly Reference (as one would expect). This works fine for our deployment, but creates a runtime dependency that is version specific. The trouble is that we would like to start creating hot fix installers that only update the specific dlls that changed. Updating all dlls is not an option for our current customer situation.
The 'Specific Version' property on project references is disabled and i'm having trouble finding out a workaround other than switching to Assembly References and using Choose blocks in the csproj to switch between debug/release bins based on build config.
Is there another alternative to allow any version to be used at runtime?

MAINTENANCE FREE
The approach we went with was to set the Assembly version to be a fixed number and only update the File version when we build.(we used to keep both in sync with each other). We went with this approach since it was maintenance free and let us keep our references by Project.
The assembly version is what .net uses to find specific versions of a dependent dll. File version is what will display if you view property details on a file via windows explorer.
If you want to be able to hotfix any dll then you'll need to update all of your Assembly References to be versionSpecific=false and set all of your projects to have a fixed assembly version. If you only want to be able to hotfix specific project dlls then you need only fix the assembly version on those projects. The referencing projects could then keep whatever assembly version scheme you want.
Assembly version is set in ProjectFolder/Properties/AssemblyInfo.cs. We've now fixed ours to be 1.0.0.0 and only increment the file version when building.
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.2.3.45678")]

REQUIRES MAINTENANCE
If you are unable to set a fixed Assembly version then another approach can be to use a File reference. The trouble here is that the path your project dlls will vary based on your active build configuration (debug vs release). To get around this you can make your reference be conditional based on the config.
The major downside being that you'll need to maintain the build sequence manually. Also, if you add a new project then you'll need to remember to use these dynamic references again.
<Choose>
<When Condition="'$(Configuration)'=='Release'">
<ItemGroup>
<Reference Include="Your.AssemblyName">
<HintPath>..\Your.AssemblyName\bin\x86\release\Your.AssemblyName.dll</HintPath>
</Reference>
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="Your.AssemblyName">
<HintPath>..\Your.AssemblyName\bin\x86\debug\Your.AssemblyName.dll</HintPath>
</Reference>
</ItemGroup>
</Otherwise>
</Choose>
You can also leave Debug as being a project reference if so desired, this would allow you to see what build sequence visual studio automatically generates due to the project references. You would then be able to mimic that sequence for your release config.

Related

Assembly Version of [MyMvcProject].Views.dll

When compiling a .net core Web MVC project VS / Compiler creates an assembly called [MyMvcProject].Views.dll with an AssemblyFileVersion of 0.0.0.0.
Is it possible to change the Version for this generated file (and maybe also change other Assembly properties?
UPDATE
I've added Manually AssemblyInfo.cs and edited my csproj with <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
With this constellation it seems that the data is not propagated to [MyMvcProject].Views.dll
I would like to stick with AssemblyInfo.cs because I share the this file over several projects. (Unless there's another solution to have consistent Assembly Versions over many projects).
Still would like to give [MyMvcProject].Views.dll a specific version.
Any idea?
I would like to stick with AssemblyInfo.cs because I share the this file over several projects. (Unless there's another solution to have consistent Assembly Versions over many projects).
You can use a Directory.Build.props file to achieve this. This file is recognised automatically by the dotnet build system (it's part of MSBuild) and will apply to all projects within the same directory or lower. If you want to apply a Version property for an entire solution, for example, you can drop a Directory.Build.props file next to the .sln file, with the following contents:
<Project>
<PropertyGroup>
<FileVersion>1.0.0.404</FileVersion>
</PropertyGroup>
</Project>
As you might expect, this AssemblyFileVersion property will also apply to your [MyMvcProject].Views.dll assembly.
Here's a detailed list of the AssemblyInfo properties you can specify when using this approach: AssemblyInfo properties.
Addition by #gsharp:
If there's also a version set in the project properties, then the project version will "win" over the Directory.Build.props version.
Go to your project "Properties" and on "Package" tab you have most of the properties that are in AssemblyInfo in classic .Net Framework projects like "Assembly version" and "Assembly file version".
Also you could try to use this command to build your project: dotnet publish /p:Version=1.2.3

.NET Core build with dll reference

I am trying to get .NET core to work with the build system at my work, which had been designed with Java in mind. But it is sadly so integrated into our pipelines that there is no way we can be without it. So if I want to use .NET at work will it have to be with this build system.
Each project is built into a package, with their own git repository.
Given a program like below where MyConsoleApp has a dependency on MyLibrary.
MyProgram-Solution
- MyConsoleApp
- MyLibrary
At build time the source code would be placed in
/build/packages/MyConsoleApp/
/build/packages/MyLibrary/
However I can only build one at the time, and I cannot move the source code.
Which means that I would need to build MyLibrary first, with the DLL ending up in
/build/packages/MyLibrary/out/MyLibrary.1.0.dll
When I then build MyConsoleApp, I need a way to tell the .NET Core build tool that the MyLibrary.1.0.dll file can be found at
/build/packages/MyLibrary/out/MyLibrary.1.0.dll
Storing packages in Nuget is not an option, as the package may not be ready for release at the build time, and the build system works in a sandbox mode, meaning it has no external connections.
I can edit the MyConsoleApp.csproj if that makes it possible.
You can add assembly references using Visual Studio, same as with .NET Framework projects.
If you want to modify the project file by hand, you'll need something like the following:
<ItemGroup>
<Reference Include="MyLibrary">
<HintPath>..\..\..\MyLibrary\out\MyLibrary.1.0.dll</HintPath>
</Reference>
</ItemGroup>

Replace DLL refs with Project refs for project dependencies in Visual Studio C# solution

Is it possible to programmatically replace DLL refs with Project refs for project dependencies in Visual Studio C#/VB.NET solution?
BACKGROUND:
I'm working with some legacy code where dependencies for each project are mostly referenced as compiled DLLs instead of including project reference from corresponding project in solution or even worse - referenced straight from GAC!
Right now I have to manually remove each DLL reference and replace it with project reference from VS UI for each solution out of dozens projects.
Editing the project/solution XML .csproj/.sln files is not straightforward due to GUIDs:
<!--typical DLL reference-->
<ItemGroup>
<Reference Include="MyDLL, Version=2.0.1.0, Culture=neutral, PublicKeyToken=1b6d1e0267e1acba, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>...\MyDLL.dll</HintPath>
</Reference>
</ItemGroup>
<!--typical Project reference-->
<ItemGroup>
<ProjectReference Include="..\MyDLL\MyDLL.csproj">
<Project>{3cc27830-3d6b-4071-85e5-5a4006f11142}</Project>
<Name>MyDLL</Name>
</ProjectReference>
</ItemGroup>
Use this plug-in .. It might help on your problem
https://visualstudiogallery.msdn.microsoft.com/056617a4-da39-4d7b-8ecf-933009d9b721
It has description below
Switches references from file to projects (and vice versa) references
when adding projects. References are reverted when the project is
removed.
usage:
You are developing project A which has a file reference to assembly
"b.dll". At some point you need to make changes to "b.dll" . So you
add project "B" to the solution. The ReferenceSwitcher will detect
that project B produces an assembly called "b.dll" and ask if you want
to switch all references from "b.dll" to project B.
Then at some point later, you no longer need project B in your
solution, so you remove project B. The reference switcher will
detected that references to B used to point to "b.dll" and ask you if
you would like to update them.
More info here:
http://markkemper1.blogspot.com/2011/09/project-to-file-reference-switcher-for.html
Edit:
there are lots of plug-in available to solve your purpose check them out
https://visualstudiogallery.msdn.microsoft.com/197d94f6-6276-471d-853d-a5a322ccb08c
OR search them all
https://visualstudiogallery.msdn.microsoft.com/site/search?f%5B0%5D.Type=SearchText&f%5B0%5D.Value=reference&pageIndex=2

Visual Studio project platform dependent references

I have a WP project for which I use a runtime module from a separate project.
If I reference the runtime module project from the main project, the platform/configuration (e.g.: x86/Debug vs ARM/Release) is handled automagically by visual studio at build time.
Now, I would like to remove the project dependency and only reference the binaries from the main project in such a way that when I chose a specific platform/configuration the correct reference will be used to build.
For example if I build for ARM/Release it should use the binaries from ./lib/ARM/Release/MyLibrary.winmd and if I build for x86/Debug it should use the binaries from ./lib/x86/Debug/MyLibrary.winmd.
I tried multiple ways but still could not find a solution that works both for Visual Studio and msbuild.
I actually have it working making the hint path use Platsform and Configuration variables.
<Reference Include="MyLibrary, Version=255.255.255.255, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\$(Platform)\$(Configuration)\MyLibrary\MyLibrary.winmd</HintPath>
</Reference>
You might be able to use some macros dependent on your build selection in VS.
Example the two macros found within the linker are as follows:
$(ProcessorArchitecture) which for my example = x86
$(ProcessorArchitectureAsPlatform) which for me = Win32
and depending on the configuration you selected it will build in either Debug / Release.
Similar to what Pinco said.

TFS Build failing since it seems to be looking in the wrong place for references

TFS (2012) Build is checking C:\Windows\Microsoft.NET... for a few of my project references even though the dlls are included as project references (set to copy local) in a folder I'm checking in.
Building outside of TFS, both in VS and using MSBuild.exe command line succeeds.
I can see in the errors and warnings that the references it is complaining about not being to find 'Could not resolve this reference. Could not locate...' are all due to it simply not checking in the checkin dependency folder as defined in the proj file.
Any ideas on how to correct this?
I believe there is a "check gac first" rule for DotNet dependency resolution.
So I do my references like this.
\MySolution.sln
\BALLayer\Biz.csproj
\DALLayer\Data.csproj
\PresLayer\MyWebsite.csproj
\ThirdPartyReferences\
\ThirdPartyReferences\SuperCoolDll111.dll
\ThirdPartyReferences\SuperCoolDll222.dll
\ThirdPartyReferences\SuperCoolDll333.dll
This way, all csprojects reference the needed dll(s) with a relative path.
All cs projects reference the SAME dll.
This has helped me avoid the "I'm gonna look in the GAC no matter what you want me to do" issue.
Nuget does this similarly.
\packages\
\packages\repositories.config
\packages\SomeLibrary\SomeDll.dll
\packages\SomeLibrary\MyNugetDll.dll
and cs projects reference the same .dll with a relative path.
............
Footnote:
Open up your .csproj file(s) in notepad, and look for the HintPath.
Mine always say something like
<Reference Include="MyNugetDll.dll>
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\SomeLibrary\MyNugetDll.dll</HintPath>
</Reference>
OR
<Reference Include="SuperCoolDll333.dll>
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdPartyReferences\SuperCoolDll333.dll</HintPath>
</Reference>
.........
But I think the crux of your issue is "copy local" and the "gac first" rule.
.........
PS
Here is another question that discusses the order...better than I could.
In what order are locations searched to load referenced DLLs?
EDIT::::
So lessons learned:
If you have your third party references checked into source control, and the build machine says "i cannot find xyz.dll", then make sure that dll is actually in source control. There are alot of "voodoo" paths on (the local development) machine with visual studio installed, and subsequently will NOT be on the "build machine".
If you use nuget and you check in your dlls, make sure they are all checked in. You might add a new entry to the packages.config and then forget to put the actual dll(s) into source control.
There are some ways to use nuget that you only put the packages.config in source control, and not the third party dlls. Check the comments of this post for articles about that.

Categories