Dynamically Naming DLL's - c#

I'm working on a project where plugins are deployed in DLL's.
When deploying a DLL, it gets locked by the application. To update it I have to change the name of the DLL (since I can't overwrite the original), and update the app database to use the new version of the library.
I'd like to make this as automated as possible.
In AssemblyInfo, I've set the [assembly: AssemblyVersion("1.0.*")] to automatically increment.
I'm hoping that I can pull this version into the project properties Assembly Name, so that it automatically appends the version number to the generated DLL.
Is this possible at all with VS/C#?

Following Hans advice that the file renaming can't be done during the build, I've decided to rename the file after build.
In order to find the version number quickly for renaming, I've removed the AssemblyFileVersion line from the AssemblyInfo file. Which will set the file version to the version number. Automatically Update Assembly File Version
After building the DLL I can check the file properties, where the version number will be listed as File version under the details tab.
I'll copy the version number from here and append it to the DLL name.

Related

How can I sync the build version number with the version number on the executable?

When building an application using a traditional language, the build version number was embedded as the version in the compiled executable (right-click properties, and there the version would be). It was a magical and beautiful time as this process was automatic, and in sync with whatever the current publish build in your project was. (when i state build in reference to version number, what I actually mean is the entire version string Major.Minor.Build.Revision )
Now, Visual Studio still has the same feature, except there doesn't seem to be any way to naturally embed this into the published executable. It does a fine job at using it to name the folder where the build is located, but the exe inside ALWAYS reads v1.0.0.0, even after modifying the AssemblyInfo file with the following line :
<Assembly: AssemblyVersion("1.0.*")>
.. which only sets arbitrary numbers based on the current time for the masked parts, and even still, this isn't what shows as the file version..
When attempting to change the AssemblyFileVersion value, from
<Assembly: AssemblyFileVersion("1.0.0.0")>
to :
<Assembly: AssemblyFileVersion("1.0.*")>
It is unsupported. Even if it did work, this would NEVER match the build of the project :
How can I embed the above number in an automatic way into the compiled executable so that the version shows up here :
Notice how neither the file version or the product version reflect neither the AssemblyVersion or the version in build settings.
If you are using the 'Release' exe,then you should change the version in:
Project > Properties > Assembly Information

AssemblyVersion and AssemblyFileVersion in a separate file

We have our AssemblyVersion and AssemblyFileVersion attributes in a separate properties file. This is because they are "linked" between all the projects and are updated by the build server. We don't want to have to manually update versions after every build or release.
AssemblyInfo.cs:
[assembly: AssemblyTitle("MyProductTitle")]
[assembly: AssemblyCulture("")]
[assembly: Guid("579eb194-08f1-44fc-9422-21aaf6cb2963")]
AssemblyVersionInfo.cs:
[assembly: AssemblyFileVersion("0.0.14056.19")]
[assembly: AssemblyVersion("0.0.0.0")]
The problem is that our build server complains with the following warning for each project:
CA1016 : Microsoft.Design : Add an AssemblyVersion attribute to 'MyProduct.dll'.
When building the projects locally, the actually DLL files in bin have all the version numbers applied (file property dialog):
When looking at the project properties in Visual Studio, the version info is not detected in Assembly Info:
My guess is that this is due to AssemblyVersion and AssemblyFileVersion not residing in AssemblyInfo.cs.
Is there any way to "include" the custom AssemblyVersionInfo.cs file?
More than one thing going wrong here:
The dialog is pretty empty because it strictly looks at the AssemblyInfo.cs file for attributes. And will write them to that file if you enter a version number. Using a separate file is not a great idea.
The Windows "Details" property sheet is agnostic of .NET, it only displays the content of the unmanaged version resource in the file. Which is only indirectly related to the attributes in your C# source code, the C# compiler auto-generates the unmanaged version resource from the attributes. Sadly, the super-important [AssemblyVersion] number is not displayed in this dialog, XP was the last Windows version that could still display it.
You probably got CA1016 because you left the version number at 0.
Windows not displaying the [AssemblyVersion] is not a good reason to skip the attribute. If it is important to you to see it in the property sheet then simply make the [AssemblyFileVersion] the same as the [AssemblyVersion]. Do keep in mind what it used for, if you change the [AssemblyVersion] then all of the projects that have a reference to the assembly need to be recompiled.
There's bad history between the Windows and DevDiv groups at Microsoft, I don't want to get into the details of it. Let's just say that Windows does very little to accommodate .NET. It is up to us to work around this.

Why would a replacement .DLL not be found?

I made a change to an ancillary DLL that my project uses, built it of course, renamed the legacy DLL to *.dll_old, and copy and pasted in the new version of the DLL to that same folder.
However, when I then ran the app that uses the DLL, it errored out with:
"An expected error has occurred...bla bla bla...or select Details for more information.
I did select Details, and saw:
TypeLoadException
File or assembly name <name of the DLL, which I just replaced>
Version=<bla>
Culture=neutral
PublicKeyToken=null, or one of its dependencies, was not found.
UPDATE
Based on the comments, I guess there's more to replacing a DLL than one might expect. I don't know if this is significant or not, I thought replacing a DLL would be like replacing an EXE, but maybe not: the DLL project's AssemblyInfo.cs says,
[assembly: AssemblyVersion("1.3.*")] // used by .NET framework only
[assembly: AssemblyFileVersion("1.3.0.308")] // File Version - increment here
[assembly: AssemblyInformationalVersion("6.3.0")] // Product version - set to current IEQ system
...and the Version in the err msg is "1.3.3889.27539"
Do I need to update one of these lines (I would guess the middle one, if so) to that value (1.3.3889.27539)? Or...???
UPDATE
So since the .DLL is not strongly named, I tried simply removing the reference (to the old .DLL) in the project that uses the DLL and then adding it back again (same file name, different version). I see, though, that updating the .DLL does not change the version numbers shown above - IOW, the AssemblyInfo.cs does not get updated when building. Should it? Do I need to manually update these vals?
It seems that types inside your original DLL were referenced by your EXE file. WHen you replaced it with your own version the references were messed. The EXE file contains metadata table with a list of types, methods, properties, etc that it references and exact version of the assemble expected. Providing something else even if everything was the same but the version number is simply not the same thing. That is why you are getting the exception.
UPDATE: Yes it is possible. However it involves creating a manifest file. For more information check this MSDN web site on Redirecting Assembly Versions. Also, keep in mind that only strongly signed assemblies can be redirected. Non-signed assemblies will be ignored.

Whether or not to include external DLLs in C# project

Our project has a lot of external DLLs, most but not all of which are 3rd party DLLs.
Currently we do not have these DLLs included in our project. They are included in SVN and given a path to our build output directory. So, after building our project the neccessary files are there, because of SVN, but the project itself has no knowledge of them.
My feeling is that we should have a folder under the root of our project named something like Dependancies or ThirdParty with all of the DLLs included there and set their build event to copy to the output directory. They would exist in SVN as well, but in the same structure as the project, not in the build output directory.
The project itself only references one of these DLLs called CommunicationProc.DLL. The CommunicationProc.DLL then references all of the other DLLs. We have numerous DLLs to support different types of radio. So not all DLLs will be used, but any one of them may be used depending on the radio type.
As to whether or not the DLLs should be included in the project we have differing opinions internally, some of the team beleives they should only be in SVN and not part of the project itself.
Of note is that this are not .NET DLLs, most are old C DLLs.
What is the accepted practice? Can someone please provide me with a compelling arguement one way or the other as to whether to include them in the project or just SVN?
Its better to have them in a folder on source control and then copy them over to the debug folder on build event. This way you can manage their versions. If a newer version of some dll comes then you can replace the old one and put some comments with check in. Also if you are working in a team, then instead of copying files from debug folder to each team member, you can let each team member to use the same set of dlls from source control. If you are developing some control and want your customers to use that control then its easier for you to have a set of dependent dlls some where so that you can give those to your customer along with your .Net dlls.
I had the same issue with some un-managed dlls and ended up putting them in a folder so that all the team members have the same version of the dlls. Hope this helps.
I include a project that has no code but contains a folder where all the external assemblies and their dependencies are kepts. For each file set the Build Action to None and Copy to Output as Do Not Copyp. The project then references the binaries from this location. In your other projects, reference this special project. When you build, because the special project is referenced and it references all the needed dependencies, the binaries are copied as needed.
If you do not want a special project, still create the folder in your main project, added the assemblies, set their properties, then reference the assemblies as needed.
This gives you complete control over the versions and output, and more importantly, it is simple.

A problem regarding dll inheritance

I have created a dll that will be used by multiple applications, and have created an installer package that installs it to the program files, as well as adds it to the Global Assembly Cache.
The dll itself uses log4net, and requires a xml file for the logging definitions.
Therefore when the installer is run, the following files get copied to the install directory within program files:
The main dll that I developed
- The Log4Net.dll
- the Log4Net.xml file
I am now experiencing a problem. I have created a test console application for experimentation. I have added my dll as a reference, and set the 'local copy' flag to false.
When I compile the test console exe however, I noticed that it has copied the log4net.dll and log4net.xml files to the bin directory. And when running the test console, it appears that it will only work if the log4net.dll is in the same directory as the exe. This is dispite the fact that the test console application does not use log4net, only the dll that was added as a reference does.
Is there some way to have it so that the log4net.dll & xml files used will be the ones that were installed to the program files, rather than any application needed to copy over local copies? The applications that will be using my dll will not be using log4net, only the dll that they are referencing uses it.
Many thanks
Don't install into the Global Assembly Cache! Even if your library dll is used by multiple applications each should have it's own local copy. Otherwise you get into a whole world of pain for saving a few KB of disk space.
Always copy the required dlls locally. If you are really sure that the application won't need it you can simply delete the unnessesary dlls later or don't include them in the installer. But if your application will call ANY reference there it will crash at runtime. So best option is to leave them there (after all they WERE referenced for a reason).
No, it's not possible (at least not without much efford) to have .Net load dlls from arbitrary locations on the disk. And it should be this way (look up DLL-hell if you want to know why).
I suspect your problem is the configuration. You must use fully qualified names if you want it to work from the GAC. As per the documentation at http://logging.apache.org/log4net/release/faq.html:
"When loading an assembly from the GAC the fully qualified assembly name, including the version, culture and public key must be specified. This is in the standard syntax supported by System.Type.GetType. See the next FAQ on how to get the version and public key for an assembly."
I managed to resolve this by adding Log4net.dll to the GAC as well. It will now run without needing a local copy the dll.
It does however require a local copy of the XML file, to correctly log.

Categories