Modify Assembly Version and References (.NET) - c#

I have an application exe plus 3 referenced assemblies in a folder. Compiled in VS2010, CLR 4.0.
I'd like to modify the version of all 4 assemblies to match (1.0.0.0) and also modify the reference section in each of those assemblies to match the new version number.
Is that possible after the application was already build outside the IDE?
EDIT:
Here is the scenario: Our dlls are often installed in the GAC with a specific version. The version is only incremented when commercial products are released. We have many self written development tools that use some of those dlls that are installed in the GAC. The tools are build at a certain point and not rebuild when the code has changed. The CLR prefers to load the assembly from GAC though instead of the local assemblies, so many times our tools do not use the assemblies that they were build with. Thats a huge problem and I don't see how it could be solved otherwise.

Use Reflector and its plugin Reflexil; of course, if the assemblies are signed they won't work together anymore (actually I think they won't work at all?). Otherwise you won't even need to modify the references I think.
Edit: also, Marc is absolutely right; can't imagine what scenario would absolutely require you to do this, it's quite hackish.

The simplest option is to simply rebuild and redeploy. There are things you can do in config (runtime/assemblyBinding/dependentAssembly/bindingRedirect), but that seems overkill here, since I'm not sure how you would go about changing the version numbers of the assemblies without rebuilding them, especially if they are signed/strong-named (the runtime will detect evil-doers).
It sounds like making work to me...
If the dlls are yours, just rebuild them with the right version meta. If they aren't yours, perhaps don't monkey with them.

Sounds like you need a publisher policy or a binding redirect. This will enable your assemblies to always use the latest version, or to use a specific version of a referenced assembly.

Related

Different versions of same DLL in Multiple nuget package in Same .Net 6 Project

I have one base nuget library called Foundation.dll.
I have another 5 nuget libraries which are using a different version of Foundation.dll.
Everything is in one project.
My question is when I build a project, VS .Net is obviously going to put only one Foundation.dll in the bin/debug folder. So how VS/.Net decides which nuget package's foundation.dll should be put in the bin/debug folder. Is it randomly?
If I do reference Foundation.dll directly in the project then it is putting my direct reference version into the bin/debug folder but for some other developers in the team, it is putting an older version.
it is very scary that the same exact branch code in 2 different machines works differently. I added one argument in one of Foundation.dll's methods & for one developer it is working but for another developer, the same exact code gives a compilation error.
What is the ultimate solution to this problem? What change should I make in my project?
Thank you.
This is a difficult topic and yes, there are a lot of factors that determine which version is being put to the bin folder. Normally, the compiler chooses the latest version from all the dependencies automatically. But particularly if you have several "final" assemblies in your solution (e.g exe's, unit test libraries) the compiler sometimes gets it wrong. Usually, the code works anyway, but I agree, this is scary.
The actual outcome may depend on the build order, build environment (whether building from the command line or within VS, etc.). Me and my team has had a hard time figuring out the best way around this problem.
The safest approach we found is to reference the latest version of your package directly in the project. This does not need to be the latest version available, but the latest version used anywhere within your solution. Of course, this only works if the versions are backwards compatible. If some library requires an older version of the dependency and you can't rebuild that library, you are in for really big trouble.
I've met the same issue. One project in the solution was depending on .net standard version of a library, while others were expecting a classic framework version.
As PMF wrote, which library will finally occur in the output depends on a build order.
I've solved it by copying the .net standard version into the output folder on post-build events.
The output should not depend on random things, there's some (complex) rules for these situations:
https://learn.microsoft.com/en-us/nuget/concepts/dependency-resolution
It should choose the direct dependency over the indirect ones.
Do you still get different results when doing "rebuild all"?

How to prevent Visual studio loading dlls from diferent path of his project refrence path

I've noticed that Visual studio looks for a referenced dll anywhere (other projects, GAC, ...) if that dll isnĀ“t in referenced path. It happens mostly with nugget packages.
Is there anyway to prevent this behavior?
I think this behavior is dangerous, because it gives you false security that your application has all refenreced dlls correctly, at the time of deploy app you can get a surprise.
Thanks
The .Net Framework does look in the applications directory or subdirectories, GAC and (if deployed to) on http server.
You can find the description here.
For GAC and http server the framework does require a strong name signing. So if your assembly is not strong signed the framework won't search there.
When deploying an app with release, this normally also should include a test installation on a non-development workstation (where no visual studio or anything else is installed). Additionally, checking that all dependent assemblies are deployed is another task of programming (at least, in my opinion).
Visual studio also does copy referenced nuget packages assembly to the output directory without any manual action.
What you're describing is not a behavior of Visual Studio but rather of .NET itself. The process of how and where assemblies are resolved is an intrinsic and essential part of the technology. So in my eyes, you are contradicting one paradigm of .NET.
However, you can use a couple of workarounds. This post contains Microsoft's description of how the .NET runtime locates assemblies. Thus you could try to ship around these manners, e. g. not signing assemblies would skip accessing the GAC.

C# build against non specific version of strong-named assembly

According to MSDN:
When you build a .NET Framework application against a specific version
of a strong-named assembly, the application uses that version of the
assembly at run time.
https://msdn.microsoft.com/en-us/library/7wd6ex19(v=VS.100).aspx
Question
Is there a way, to build a .Net Framework application against a strong-named assembly, so that it does not require the specific version at run time?
The quote from MSDN seems to imply that ("against a specific version of a strong-named assembly")
But how to do that. How do I build against a non specific version of a strong named assembly?
All tests I did tell me, that if I build against a strong named assembly, it will always require that version at runtime.
Except when I use Publisher Policys or Assembly Redirects.
Update:
But when I check for example this nuget Package:
https://www.nuget.org/packages/Microsoft.Owin.Security.OAuth.
It says that it accepts Newtonsoft.Json greater then 6.0.4.
And I want to understand how they do that? Since Newtonsoft.Json is a strongly named assembly. And I don't see any assembly redirects and I think there is also no publisher policy. Or do I miss something?
This is handled by assembly redirection, as you've already mentioned.
The NuGet dependency management for the packet manager itself, not the assembly references. You still have strict binding for the references in your project, and this can cause collisions when you end up with two versions of the same assembly in the same AppDomain as usual. NuGet doesn't even try to solve the problem.
When that conflict arises, you're back to square one - you need to add binding redirects. If that isn't possible (for incompatible versions of the assembly, for example), you're in for a lot of fun.
The policy NuGet uses to pick the best version of the library is quite simple: get the lowest possible major + minor version, and the highest possible patch version (the third version number). Again, this only happens when updating the packages, not at compile-time or runtime. This allows NuGet to pick a compatible version of a dependency when you have multiple packages that have different requirements. However, it isn't transitive - it only helps if all your references are in the same project. If you're referencing a project that NuGet's a different version of the dependency, you're back at the original problem again.

Using two different versions of same the NuGet package

I wanted to use two different version same library (OpenCVSharp 2.x and OpenCVSharp 3.x).
I downloaded those two packages both to the separate project (let's call it OCV2Wrapper and OCV3Wrapper) and reference both wrappers in my project. I had to renamed libraries from one package (2.x) and reference them manual because: Can we add 2 different versions of same package in NuGet. I read about external aliases and I used external alias in one of the wrappers (2.x in my case).
But I have some major problems:
My renamed libraries are not copied to the launch project build (that one which reference both wrappers), but is in build of the 2.x wrapper
It doesn't work because yet it says it cannot find a type from my 2.x wrapper even when I manually copy my renamed libraries from 2.x wrapper.
What is the correct approach for this scenario in C#?
I want to use both wrappers in solution because the 2.x version contains algorithms (SIFT and SURF) and 3.x version contains algorithms (Kaze and AKaze).
I can live that with both packages coming from somewhere other than NuGet, but I prefer that 3.x comes from NuGet and the 2.x version is manually configured.
As already stated, there is nothing wrong with referencing 2 different versions of a NuGet package, as long as it's in different Visual Studio Projects that those references are made.
But this is also where the easy part ends, but I think there are a few options left. Depending on your needs, I see the following options.
Create a post build step which registers the multi-versioned assemblies into the GAC. As long as each assembly have different assembly version, the CLR will pick up the right assembly from the GAC when needed.
Create a post build step which copies the different assemblies into a subfolder of your application bin folder like bin/package-v1 and bin/package-v2. Then you can, in your application, override the AssemblyResolve event as described here: https://msdn.microsoft.com/en-us/library/ff527268(v=vs.110).aspx. This will make it possible for you to load the assembly in the right version at the time of need.
If you don't want to play around with AssemblyResolve, then you can also modify your web/app.config to do assembly redirect/probing as described here: https://msdn.microsoft.com/en-us/library/4191fzwb(v=vs.110).aspx
Hope this helps a bit, so you don't have to modify third party source code next time.
OK so, I solve this by downloading whole sourcecode for 2.X wrapper version.
Renamed its namespace to ABCDEF2 where ABCDEF was original namespace. Build my own nuget package with my own key and... publish it to our private nuget server.
This is such a lame solution but there is no other way than manually downloading the original packages and reference it directly with different filename etc and you loose nuget advantages.

Looking for an msbuild and xbuild task to fetch referenced libraries (without nuget.exe)

I have an issue with creating an easy solution for my build system, based on mono.
Current situation is that I keep my referenced libraries inside the git repository, which is not good, for many obvious reasons.
What I want to achieve is something like what NuGet provides - automatically download dlls from the Web, put them in some directory and forget about them.
I want to do this at build time, so it would not require any additional actions with downloading libraries etc. The best option would be an msbuild (xbuild on mono) task, but I want it to be system independent, so the popular one, executing NuGet.exe, is out of question (consider parallel mono installations, etc.).
I've tried Pepita project, but it's... wrong. No, really, it is, it has too many design mistakes to be easy to use or repair. To make a proper configuration would require a serious rewrite of the whole project.
What I would love is a library, that would employ NuGet.Core library and be available as a task. If such a lib is not there, I could use any solution, that would download a nuget package and unpack it to a directory specified in .csproj.
Even better, it would be nice if such a library could resolve dependencies without specifying them explicitly in packages.config (or similar) file, e.g. if I want to include Castle.Windsor I don't want to include Castle.Core in my config file.
I know about the OpenWrap project (with NuGet Gallery), it looks promising, but I can't find the solution where I would just put a constant set of libraries in my repo once, modify csproj files, some configs and have it done.
I can tell you that OpenWrap at the core has everything built-in to do what you want. Everything you can do with the openwrap-shell is also available to be called from msbuild. So, it seems to me that you would just need to add a before build hook to call out to openwrap to perform an "update-wrap". Several months back I actually looked into doing something similar. AFAIR I actually wrote an msbuild script to call openwrap tasks, but didn't really hook them into the normal build process.
I don't know exactly what you mean with "put a constant set of libraries in your repo once"? For OpenWrap, all you need to do is maintain the "openwrap descriptor" for your project. That file contains all direct dependencies of your project (with or without restrictions on version numbers). (Indirect dependencies are pulled in automatically) Are you wondering about how you get started when you have a bunch of binary dlls to start with? I can tell you what I did. Basically, I do not use any NuGet packages, I created OpenWrap packages for everything. I also created OpenWrap packages for all our binary dependencies (some of which are open-source). This is really super simple: you fill in correct dependencies in the OpenWrap descriptor and specify that the package must only contain the given dlls. We had a bunch of binary dependencies, but once you start packaging them, it's definitely not that much work.
If you want to see an example, you can check this one:
http://code.google.com/p/ppwcode/source/browse/dotnet/External/Apache.Log4Net/trunk/Apache.Log4Net.wrapdesc
That is all you have to do to package your binary dependencies. This is a package I created and we currently use it in the company where I work. I know Log4Net is probably available as a NuGet package, and I could probably use that. The advantage of creating those binary packages myself, is that I have full control over the packages, over the version numbering of the packages, over how a big project is split over several smaller packages and so on.
As an OpenWrap repo, you can use a folder on your local filesystem, or a folder on a network share. What we use, is actually a webdav repository that we mount locally on a drive (using Windows 7). This works fine for us and also allows us to specify who has read and write access to the repository.
You mention mono.... well, that might be a problem: the currently released version of OpenWrap (2.0.2) does not run on mono AFAIK. But the good news is that Sebastien Lambla has been working hard to get OpenWrap to run on mono+xbuild for the new version that is going to be released very soon: 2.0.3. No alpha/beta builds available yet, but you can build from git. (In that case you would need to build both openwrap-shell and openwrap). Sebastien Lambla, who created OpenWrap, normally keeps an eye on questions on StackOverflow and will probably be able to give you a more complete answer on the mono status.
Btw, where I work, we are using OpenWrap already for over a year. Back then we compared both NuGet and OpenWrap, and at that moment OpenWrap was way way way ahead of NuGet. Basically, to me, NuGet was not a tool for dependency management, but a tool to assist you in Visual Studio to pull in binary dependencies from a remote server (meaning: copy dll from remote server to local folder and add reference to local dll in project file). In the mean time, NuGet has been playing catch-up with OpenWrap and has added functionality that already existed in OpenWrap. There are in my opinion only 2 things that NuGet has over OpenWrap and that is integration in Visual Studio (aka overview of remotely available packages and click-click-click adding of packages) and the fact that it is maintained by Microsoft people (AFAIK). Both things are just political: it's easier to convince people with a pretty interface and microsoft support. Personally, however, I think that OpenWrap is technically superior and I think it's really a pity that it doesn't get the attention that it deserves.

Categories

Resources