Deploying many DLLs for a single DLL - c#

I have a solution with 50 projects.
There are times when I just modify a single class file in a project and I just get a single new DLL.
But there are times when that single project is referencing other projects and those projects are referencing other projects so when I make a small change in one class in one project, I may have to deploye like 30 DLLs.
Why is that.. ? Why are so many new DLLs being created and why do I have to deploy those new DLLs?

It sounds like you have auto versioning on in addition to "specific version=true" set in your references. You would probably want to manually version any of the dlls that don't change a whole lot, which would typically be your "framework" or "lib" dlls or what not. Some shops choose to not compile those assemblies every time and to just put them in a "lib" directory or something, causing your primary assemblies which DO change often to build against the same version of your lib or framework dlls on every build.
At my company, we put all of our framework assemblies on a public network share and leave them there until someone updates it. At that point, we make a new version, and place the new dll out on the share, alerting everyone that a new dll is there. Our reference share looks like the GAC, so we have \\\\lib.dll for all of our references. Some people check in the actual binaries into source control and reference them from there. What to do is really up to you and your team.

When you build a project you will find in the bin folder the dll and all the dll from the referenced projects. That's the default behaviour because if you want to use your dll you probably need the referenced projects. You don't have necessarily to deploy all the dlls, you just need the changed ones.
Bye,
Marco

Related

How to create a dll that includes all the others?

At the moment of creating a project of type "Library of Classes, usually one can generate a dll when compiling, but how could I generate a dll without losing others that I already have included?
I explain with an example: It turns out that Nuget downloaded an S22.Imap dll with the one I worked with, later I generated the dll in the traditional way that I explained in the beginning, but when I wanted to work with dll in another computer, I got errors that were not I found functions that contained the S22.IMAP dll. So to solve this problem, I had to copy the dll of my project, S22.IMAP in an additional way in a specific path of the other computer.
My question is:
How could you generate a dll that includes the ones included in the project you were working with?
All the referred 3rd party dlls (S22.Imap.dll in your example) will be copied to the output folder together with your own dll file (let's say a.dll) when you build your project. That means you should always copy them together (S22 + a.dll) to the place you want to refer them, on another computer/folder/place.
If you really want to make them only one file (although it is not recommended), you can set the S22 one as some "nested resource". Then you will get only one a.dll file and the S22 one is inside the a.dll. See below page for some reference:
Embedding one dll inside another as an embedded resource and then calling it from my code
AND, ILMerge is some tool that can help you do so.
In general, you don't. A DLL is a dynamic linked library, and you would normally only combine static libraries during a build. Here is an answer on the difference between static and dynamic linking.
Typically you would include all the DLLs you need in the installer package. If you use Visual Studio to create the installer, it can detect the dependencies for you. When you run the installer, all of the necessary DLLs are deployed. Nearly all commercial .NET software follows this pattern.
It is possible to merge an assembly into another assembly using a tool called ILMerge. This would be a very unusual thing to do, and could cause issues with intellectual property and code signing, so it is not recommended.

Referencing a project in another project creates unwanted dependencies

I have a project ProjectA in which I am keeping utility classes. I want to use this project in multiple solutions so I do not have to copy files, link files and update files every time I make changes in classes of Project.
But there seems to be a problem: if I am referencing ProjectA in ProjectB, the compiled application of ProjectB can not run unless there's a compiled application from ProjectA next to it. So if the output of ProjectB is ProjectB.exe, ProjectB.exe gives an error upon execution if ProjectA.exe is not next to it. Why is that? I just want to use namespaces from ProjectA in ProjectB, I do not need ProjectA to depend on a compiled version of ProjectB.
Can anyone tell me how to reference ProjectA in ProjectB without needing the output of ProjectA to run the output of ProjectB?
You probably need a shared dll.
You have created utility classes in project A out because they are shared all across project A (Application A?), now you have introduced project B (Application B) and as you state it needs to get hold of the code from projectA.dll/exe.
So create a new project in your solution (Ab.Shared.dll maybe:-)) and move your utiilty classes into it. You can now reference that dll from both project A and project B.
Update: Just read about your comment about sucking code out.
The shared dll is the most common way of sharing the code about, but there are other ways. Theoretically you can simply "include" the same *.cs files in both projects and share them that way (use the drop down on the Add existing item dialog and select Add as link) . However in practice it becomes more awkward maintaining this scenario so most people use a shared dll.
Namespaces are not restricted to one assembly - you can use the same namespace across several assemblies if you wish, and one assembly can contain as many namespaces as you like.
If you are referencing a class/type from another assembly, then that assembly must be present (or locatable) when you run the original assembly. If all you are doing is coding then a simple project reference in your solution will do the trick. If you don't have the source code to Project A then you will need it in its compiled form - without it the CLR cannot inspect it and know what it contains.
In that case add the ProjectA compiled dll in your bin folder and add the reference to that dll from your other project. Do not add reference to your ProjectA project.
When you add reference to the project using Visual studio, Add Reference -> Projects, then it requires the project to be compiled and it copies the dll/exe to the other project bin folder.
Open your csproj file in text editor and insert xml:
<Reference Include="AssemblyName.dll">
<HintPath>$(EnvironmentVariable)\bin\AssemblyName.dll</HintPath>
<Private>False</Private>
</Reference>
If I understand correctly, you have code in ProjectA.exe that you want to use in ProjectB.exe, but at run time, you'd like to run ProjectB.exe without requiring the user to have a copy of ProjectA.exe.
This is not possible. When you use a type from another assembly, that assembly is loaded at run time. The type is not copied from ProjectA to ProjectB.
It sounds to me like you should extract the common utility classes into ProjectUtility.dll, and then reference that from both your ProjectA.exe and ProjectB.exe applications.
EDIT: ILMERGE might be the way to go. See Linking statically in C# for more information.

why would a .cs file not see updates to an included dll file

I have a dll containing classes to access data in SQL (a sort of ORM system) included in my .cs page with a using statement. For some reason the dll (with definition for a new field) isn't seen by the cs code, though I've uploaded the new dll in bin. It won't see my new field in the dll's helper classes (now compiled into the dll).
Is there a way to troubleshoot the dll, or the cs to tell why this won't see the class I updated and rebuilt? The class works fine locally and on another server, but on my prod server, it bombs.
This is using Sitefinity 3.7 with a Subsonic/Substage module if that sheds some light on it.
If you are using Visual Studio, verify 2 things, first:
try deleting csproj.user and .suo files (visual studio will recreate them)
The second thing is the version of the framework your project is running, and the version of the framework the dll was compiled in.
If your project is using .NET 4.0 but the DLL was built using 2.0 or similar you may not be able to use it, you can add it, but it wont be loaded.
This sounds so familiar... have you check to see if there is another dll on the path that gets resolved? Dynamic-Link Library Search Order
Make sure that your dll was not registered on the production service in the GAC.
How to extract an assembly from the GAC?
Perhaps you have a local copy of the DLL in your project and the DLL that gets updated is elsewhere.
I tend to think the dll you build is 32 bit (X86) dll. where as you are trying to consume it from project that targets "Any CPU".
Is your production server a 64 bit ?
If answer is yes, goto project properties => Build tab (of your cs code's project which is not understanding the dll) and set the Platform target as X86.
If the updated DLL has a different version number, you may need to update the Project Reference to it by deleting and re-adding a reference to the DLL in the bin folder.
If the project generating the DLL is present in the same solution, you may have an issue in creating a file reference (may not be updated) instead of a project reference (will be updated).
fuslog.exe is a great tool when troubleshooting assembly (dll) binding issues.
http://msdn.microsoft.com/en-us/library/e74a18c4.aspx
Another .net developer helped me figure this out. I had a rogue ToString() in there where there should have been a cast to string, allowing nulls. My dll was okay after all. Thanks everyone for your suggestions, I learned a lot.

Where should you store 3rd party assemblies?

Okay, so we have a rather large solution with about 8 different projects inside it. Each of these projects depend on various different 3rd party assemblies. This solution is in the trunk branch of source control. We also have about 5 different branches off of trunk.
What is the best way to manage these 3rd party assemblies? When you add a reference to an assembly and then click it and view the properties window I notice that it has a hard coded path to the assembly.
For example: All our branches are mapped to "C:\Code\". So trunk would be "C:\Code\Trunk" and a branch would be "C:\Code\somebranch".
If I create a folder in "C:\Code\Trunk" called "Assemblies" and then drop all our 3rd party assemblies in that folder, and then I add a reference to an assembly in there is that assembly reference relative? If I click the added assembly I see the grayed out path property says "C:\Code\Trunk\Assemblies\someassembly.dll".
What happens if I then branch off of trunk? Would "somebranch" still have a reference to "C:\Code\Trunk\Assemblies\someassembly.dll" or would it then reference "C:\Code\somebranch\Assemblies\someassembly.dll"?
Currently we actually have a branch in source control called "Assemblies" which is mapped, just like any other branch, to "C:\Code\". So all branches with projects referencing assemblies have references to "C:\Code\Assemblies\someassembly.dll" no matter which branch the project is in, the path would be the same.
Unfortunately this means that you have to get the latest version of the branch you are working in AND the assemblies branch in order to get the solution to build successfully.
To sum it all up:
How do you add a reference that is relative to the solution? (i.e. Add a reference to C:\Code\Trunk\Assemblies\someassembly.dll and have that path be relative to the project that added it, so that when creating a branch it references the branched assemblies folder and not trunk's assemblies folder. Or is this reference already relative?
What are other recommended strategies for managing 3rd party assemblies?
Now we have nuget you can use it for all supported oss packages and even create your own nuget packages for other 3rd party assemblies. It is worth mentioning openwrap as an alternative to nuget.
nuget stores packages at solution level
so each branch (and trunk) would keep a version of these.
I'd suggest this is preferable behaviour. You would want to keep your assemblies version separate if upgrading a 3rd party for example.
In the past I've used svn's externals command to build the specific version from the internally developed dependencies. There's no reason you couldn't stick those in a repository and use externals (or you scm's equivalent) to get the right version.
I've used build events to get the dlls into the right place too.
Yes use an assemblies folder off of the trunk. I like the name lib better then assemblies.
Yes the path is already relative. When you branch your projects will get the correct assemblies folder.
Depending on how many third party assemblies you are using you make also want to organize your assemblies folder so it is not one big mess of dlls.
We have a SolutionItems folder in our solution for the 3rd party references.
Every branch of the solution has it's own copy.
When we add a reference we use the 'Browse' tab in the add reference dialog and select the assembly relative to our current project.
The Project file contains this:
<Reference Include="SomeAssembly, Version=0.1.0.0, Culture=neutral, PublicKeyToken=8xxxxxxxxxxx, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Solution Items\SomeAssembly.dll</HintPath>
</Reference>
I usually create a common project that all the others reference. Inside that common project, I create a folder called deps (for dependencies). Each of the other projects then references the copy of the DLL in the common project's deps folder.

C# - Are there disadvantages for all projects to share the same output path?

In a Visual Studio C# solution, are there any disadvantages for all projects to share the same output path? I'd like to do this because we use dependency injection and the files don't get copied automatically (since they are not referenced). Will this cause me any problems?
(This is related to: C# - Copy dlls to the exe output directory when using dependency injection with no references?)
We are doing this on our current project. We have about 30 projects output to the same bin folder and we have not had any problems.
There's a potential problem if you have two different projects depending on different versions of the same assembly. If I have project A depending on X.dll version 1, and project B depending on X.dll version 2, you're not going to be able to place both versions of X.dll into the same output folder (without a rename). Admittedly, the chances of these aren't high, but they're not zero.
The point of having multiple projects is to produce multiple assemblies. Assemblies are a deployment mechanism in .Net. If you always plan to bundle all the output dlls into one package, then I do not see disadvantages in this approach.
However, if you are planning to deploy Assemblies A,B,C separately from Assemblies D,E,F for one reason or another, keeping the output directories separate will ensure that the correct assemnbly and only its dependencies are in the output folder. It will be easier to then just write a script that correctly bundles those Assemblies into the correct packaging that you want.
Generally not a disadvantage, I find it quite beneficial to have a single output location for my target assemblies. When VS sorts the projects for compilation by determining dependencies, it will overwrite an existing instances of compiled assemblies that have been built earlier in the build order.
Saves me having to hunt round for the compiled assemblies when everything is built.
Some instances where you may have issues is if you have two projects with references to external assemblies that are of different versions, you may end up with an assembly bundled without the incorrect version of a dependency...
You may run into issues w/TeamBuild or whatever automated build process that you are using if you are planning on deploying your assemblies in different ways (core package vs. add ons, etc.)
How you customize your build scripts will be different (not necessarily disadvantageous) depending on how much customization you've done to your csproj files.
One big disadvantage with this approach is often you will run into access violation issues if your startup project holds references to any dlls that other projects reference during the build, even if copy local = false. I run into this issues everyday now. I would suggest having a project with all the needed references and copy local = true for those references. This will also help with making an installer.

Categories

Resources