I have several solutions in .NET many of them have projects with same DLL but different versions of these same dlls, inside the same solution.
So when deploying the build of the solution to the production server, only one of the dll versions were deployed resulting in assembly reference error. Except when the missing dll was in the server's GAC.
The current solution is to install manually the missing dlls in the server's GAC, or to deploy all the packages folder in version control, which I consider both bad solutions.
What is the standard procedure/best solution for this problem?
I was reading some material about the subject and all of them involve or creating another piece of code in the solution or to manually place the dlls in the server.
Related
My application references the Sage50 SDK and I need to support multiple versions of the SDK.
In Visual Studio each version of the SDK has its own project and has the SDK DLL's referenced.
But when I build the solution the DLL's overwrite eachother and only 1 version remains.
I can't rename the DLL's because the SDK loads other DLL's by name and will error out when they are renamed. And they are signed.
How would I go about a situation like this?
Make each project uses a 'strong' reference to those different sage SDK assemblies. That is, make sure it specifies a version, culture, and token etc... Nothing worse than a versionless, sloppy reference.
You will have to output your project DLL's to separate locations. Because the build will copy all dependencies to the output folder.
Because of #2, you will have to dynamically load your assemblies in your application. (i.e. Assembly.load(...))
Some background:
At my company, I have been working the last few months with converting our C# libraries to function on .dll references instead of project to project references. To do this, we have created a local NuGet server which contains NuGet packages for all of our libraries projects. We have Jenkins jobs set up for every project which build new NuGet packages and add them to the server every time a change is made to one of them.
For working on a single project, this system works great. You only have to worry about updating your packages folder through Visual Studio's NuGet manager, and then the rest is just writing code and building.
The issue:
When you add a new reference, or update your packages through NuGet, NuGet automatically specifies that specific version of the project that you selected in NuGet. With the current system I have setup, rebuilding a project locally will then replace it's .dll in the packages folder so that all projects that reference it can see these new changes you're testing. However, the issue come in that locally built projects have a different version than our Jenkins built packages. Our local builds use a different versioning system from our Jenkins builds so that you can easily tell whether something was built using Jenkins, or if some of the .dlls came from a developer's build. Because of this different versioning scheme, the reference of projects to the project breaks, because the new .dll that was built locally has a different version than the .dll that was retrieved from the NuGet server.
Current Solution:
For the moment, I have resolved this through the addition of a pre-build step. Before every project builds, the project calls one of my PowerShell scripts, which goes through and adds <SpecificVersion>False</SpecificVersion> to every project reference in the project being built's .csproj file. This resolves the issue, but only in the sense of putting a bandaid on it. Instead of dealing with the consequences of the system, I wanted to prevent them ahead of time so that this isn't needed every time a project builds. I have tried researching a lot about NuGet packages specific versioning issues, but have not been able to find anything online even remotely close to what I am asking. This makes me think that I'm going about this wrong.
The question:
What can I do to solve this issue? Or am I doing something very wrong and dumb that could be easily avoided by using another system? Any suggestions or tips would be greatly appreciated
I am a dinosaur developer, so NuGet is relatively new to me, I am used to manage third parties open source libraries having a single project with the code or the binaries, that I will keep updated when necessary and this project publishes the dll(s) on a common folder from where I reference the libraries in all my projects. This makes easy to maintain the third party libraries and in my projects I just need to rebuild when I update the library and all goes OK. Now many open source projects publish their libraries on NuGet and it is easy to reference them in the projects, but I dread the fact that I have to download a copy of the library for each project in which I use it, this, in my opinion is something that can lead to chaos. Especially if I have 2 projects that build dlls that end up using 2 different versions of the same packages and are used both in an application with problems and conflicts. So my question to those who use NuGet from a longer time is:
Can I proceed with NuGet packages as with other libraries and create a project that references them, use it to publish the dlls in a single folder and then reference the dlls of the packages from my dlls and applications on the published folder.
I hope I've been clear. Thanks for any thoughts you can share on this topic
Sabrina
Having all your 3rd party libraries for all your projects in a single folder can lead to dll versions hell. If you update a single dll which contains breaking changes and which is referenced by other projects, then you will have fix/rebuild all projects that references it.
To resolve the issue with downloading the same packages for every project you can create a local repository and configure Visual Studio to use your local repository. So if your local repository contains a single version of log4net, you'll be able to use only that specific version. Even more you can configure repository to use a shared folder, in this case all developers and even your build server will be able to use that repository.
There are a lot advantages of using NuGet, such as saving a lot of space on your hard disks and others. For example I created NuGet packages for our internal framework, so all our projects just reference those packages, rather than each project has its own version in its bin folder.
I have an independent solution with multiple projects including class libraries and control libraries. This solution and all its projects are under TFS source control.
I reference the output of one or more of these libraries in all new projects I develop. References are currently binary rather than project references.
The new projects are also always under source control and now I need to add debugging support for the libraries.
If I reference the library projects from them, the project file is modified and no longer works with the original library solution since source control providers for the library and referencee may be different.
Is there an easy way to accommodate this?
You should package the shared binaries, along with indexed PDB's, into a Nuget package. Nuget was specifically designed to solve these problems.
You can index your PDB's by running an indexing tool. TF Build can automatically index your PDB's.
Nope.
There are some strategies you can use, however. Easiest (possibly, but not in some cases) is to build the project you wish to debug, drop the binaries on top of the application that hosts them, and attach your debugger to the running application. This makes sure you have the correct version of the assembly under debug, but you might have to do unwanted things, such as making sure you're not targeting a specific version of the assembly
Which may be bad news for an assembly under development. It also requires lots of handiwork, which depending on where your application runs may require you run remote debugging, deal with issues transmitting dlls across untrusted networks, etc etc.
In my web and worker roles, I am referencing an alternative version of a core framework DLL. The file is marked Copy Local. Visual Studio shows the correct version in as a project reference. When compiling the project, the bin directory also contains the correct version.
However, when I ask Visual Studio to create an Azure package, the package (and the csx folder created during packaging) contains the wrong (original) DLL for the Worker role only. The Web role has the correct DLL. This does not occur if I manually use cspack, but that's not really a desirable way to package.
What could cause Visual Studio to compile with the correct reference DLL but bundle the wrong one?
Additional info:
When I run msbuild to do the packaging instead of Visual Studio, I see the following two lines:
Copying file from "C:\Users\bytenik\Dropbox\Treadmarks\lib\EntityFramework\System.Data.Entity.dll" to "C:\Users\bytenik\Dropbox\Treadmarks\src\Azure\obj\Debug\Worker\System.Data.Entity.dll".
Copying file from "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Entity.dll" to "C:\Users\bytenik\Dropbox\Treadmarks\src\Azure\obj\Debug\Worker\System.Data.Entity.dll".
So, it seems to copy my reference, and then copy over it with the system reference.
Note: I'm well aware that the entire concept of replacing a .NET CLR DLL is a huge hack. When .NET 4.5 comes out supporting the feature I need, this will all be stripped out. In the meantime, I need to be able to continue development.
This is a replacement to question "Azure References Incorrect DLL", which was actually factually incorrect and lead to answers that were valid, but did not solve my problem.
Even if a Visual Studio project has a reference to a local and/or modified copy of a assembly that is in the GAC, it will be used during the compilation, but at runtime, the CLR will always load the assembly from the GAC, even if it is sitting right there in the same directory as your application.
So the solution does not involve figuring out a clever way to pack or deploy the modified assembly, but figuring out a way of making the CLR actually load it if it's there.
Two possible solutions:
1) Use a role startup task and an installation project to deploy the modified version of the assembly in the production server's GAC.
2) Remove the signature of the assembly and make sure all references are made to this version without the signature. Beware other assemblies that may be referencing the original signed version and will try to load it from the GAC.
For more details and links see How to prevent a .NET application to use an assembly from the GAC?