Multiple solutions working with shared library project in Visual Studio - c#

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.

Related

How to create and manage subsites from main site in ASP.NET Core 6 MVC?

We have created multiple application solutions in ASP.NET Core 6 MVC.
I want to use each solution under a single solution so that I can use common menus/submenus in all applications.
Also not sure how will handle session in this case.
Example: we have created 4 separate solution modules for Admin, Employees, Department, Students.
Now I am creating a new Login solution which will have login functionality and menus.
I tried by creating DLL for each solution and referencing in Login solution but it's not working properly also static files are not getting added.
All modules for a single application should rather go in a single solution with multiple projects, if feasible. Each project yields a binary assembly that can be directly referenced in other projects. This prevents code duplication by allowing multiple projects to reference the same code. Using multiple solutions can lead to problems regarding referencing paths. There is also a big drawback of spliting your application into multiple solutions: your application's code cannot be accessed in full in the development environement, making refactoring harder.
Since Visual Studio 2022 is now 64bit, you can have solutions with a large amount of projects with little performance drops.
If you really need to have dependencies across multiple solutions, you should turn towards nuget. Nuget is the package manager for dotnet. After compiling a project, you provide some metadata to create a package. Then you publish the package to the repository. Other solutions can reference the package and the linker will download the binaries from the repository. Nuget packages support semantic versioning and you can reference specific versions of a library.
However, this will require you to write your code like a quality library. It means early design thinking, strong QA, and heavy testing are required so you don't ping-pong updates between your libs and their clients. This is why this strategy is more designed towards sharing libs accross multiple applications.
There are also on premises solutions if you don't want to upload your binaries to the internet. You can create a nuget repository as simply as creating a new directory and adding the path to the list of nuget packages references sources in Visual Studio. Nuget packages can be shared across your intranet using a simple SMB fileshare. If you need better access control, you can install a local copy of NugetGallery.
Details on nuget usage are availble in Microsoft documentation about nuget.

How create a .net standard and .net framework self-contained build?

My goal is to create a build output that acts as portable version of my application, containing the non-framework dependencies (nuget + projects) directly as dlls.
This demonstrates the solution and the four projects contained:
You can see the libraries are .net standard 2.0 while a console app (to run / debug some code) is using .net framework 4.7.2 (because we have some .net framework apps in use around here). The arrows in the image show the references that have been set.
Parts of the the libraries (not console app) might be imported into MS sql server in the future; these imports usually pick up all dependencies from the same folder if available (which is the reason for a self-contained output).
Problem A: Running the code on linux/mono
Using jetbrains rider to open the solution, build + restore packages will work without problems.
Running the console app will work to some extend (e.g. loading data from SQL) until it fails when calling some code that makes use of BouncyCastle (dll not found exception).
Looking at the build output shows three .dll files of my lib-projects along with the .exe file of the console-app plus all the .pdb files AND additionally the System.Data.SqlClient.dll.
Seems that might be the reason my sql code worked.
Problem B: Running the code on win10, .net framework / core installed
Using VS / rider made no difference here, opened the solution, restored packages + build without problems. Running the console-app fails earlier than before: this time it was unable to find the Syste.Data.SqlClient.dll.
Checking the build folder shows my three lib-dlls and the .exe including the .pdb files, nothing else.
To my understanding, the files have to be either in GAC or inside the same folder for them to be found. It seems when a .net standard library dependency includes nuget-packages, something is having troubling either loading them into GAC or at least copying them to the build directory (which is outdated I guess).
So even if my approach (having a portable-ish / self-contained version of my app) might be uncommon or even stupid, I would have thought that just running this code on the dev-machine should work fine.
Problem C: Including dependencies in the build output
According to information I found here, the <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> property can be used to have dependencies being copied to the build directory.
And while this seems to copy too many files (tried excluding some according to docs) it does indeed copy the .dll files for a complete package when building the ExchangeIntegration project (.net standard 2.0).
Looking into accomplishing the same for .net framework .csproj projects yielded mixed results. I was playing around with the copy-local setting and stumbled across similar problems when creating nuget packages and using .targets files but had no success.
About the specific libraries used
I'm more interested in learning the right concept to handle this, it's not really about whether or not it makes sense to import Newtonsoft.Json into MS sql server.
I feel I'm fundamentally missing something; maybe the output type library is not correct for my goal or maybe I'm mixing problematic .net versions, although I did a quick check and it seems ok.
How can I get a .net framework (console-app) build that contains all non-framework dependencies (e.g. nuget) AND an separate .net standard (library) build, that also contains all non-framework dependencies?
EDIT: Adding all nuget packages to the top tier project (console-app in my example) seems to work around the problem, code executes without problems. I'm still waiting for a proper solution.
EDIT2: Added mono/msbuild version used under arch: 16.4

How to use wixlibs as file references with support for different platforms?

I just am trying to replicate my distributed C# project structure to WIX setup projects. Now there is the following problem:
LIB: a C# library solution that builds AnyCPU .NET dlls from several C# projects
APP: the dlls from LIB are referenced (as file references) by this main application solution. Additionally there are platform dependent libs included in this application solution, therefore it is important to being able to create setups for the two specific target platforms x86 and x64.
Now I started to create a wixsetup project within the APP solution (which works fine). Then I proceeded with creating a wixlib within the LIB solution that references the LIB .NET dlls into the wixlib.
Now the problem:
The wixlib references the AnyCPU .NET dlls within a DirectoryRef which seems to be platform specificly tagged when creating the wixlib. Therefore I have to go back to the LIB solution, build the project with one platform target, copy the built files (via SVN externals mechanisms) to the APP solution, build this project with the exact same target platform as the wixlib was created with and repeat this procedure for creating the other platform.
It may seem that this is kind of complicated, but doable. Due to the fact that I omitted several other library solutions for which the same problem applies and the fact that all those libraries are used in multiple application solutions and - finally - everything has to run on our build server automatically as well, it is clear that this will not work.
I know of the following solution, though:
Double the .NET dll references within wixlib to assign them to different DirectoryRef INSTALLDIR and INSTALLDIR32 e. g. and to implement those different directory references in the wixsetup.
But this would complicate things as well and is not my preferred solution therefore - if there is an alternative.
If there is no smart alternative, just tell me and I will do things as described in the last paragraph.

Management and structure of a growing .NET project

We're building a .NET software platform for test automation for in house use in our company.
The application is composed of a GUI (WinForms) component, and various "Actions" that are dynamically being loaded into it to be executed.
There are approximately ~ 100 Action projects going already, with this number increasing.
Some of these projects are interdependent on other projects and so on.
All actions loaded must reference our "SDK" dll for various activities (results to the main app, logging, etc).
With this relatively simple design, we are facing some management decisions that we'd like to solve in the best way:
Should actions ("plugins") reference our SDKs project output, or some known stable version of it?
For example, when developing a large application (MS Office just for the example), not all teams work with source code for all components naturally.
What is the best solution for something like this ? and why?
How to properly verify that all needed dependencies (3rd party libraries for example) are indeed taken from the correct location ?
What are common practices in scenarios where managing multitude of projects that are linked in between? are there any tips for doing so ?
This is a problem that doesn't have a clear answer, but...
There are two paths you can take. A strongly coupled system or a loosely coupled system.
For a strongly coupled system I can suggest two directories for binaries: a 3rd party directory and a directory that houses DLLs that you company builds that other developers can reference. The 3rd party DLLs (outside your company) should be located in source control so that all developers reference the same versions of the 3rd party DLLs from the same location this avoids developer machine inconsistencies and having the problems of installing 3rd party software on every machine. The in house DLLs should not be referenced in source control and should be built on each developers machine via an automated build batch file or similiar. In a build post step you can copy them all to the same directory and as long as developers get the latest source control and build, everyone has the same DLLs from within your company.
For example, get latest, build (using a batch file to build all the projects needed), and then as a post build step copy the output to common. Now all of your other projects can reference the common compnay DLLs and the third party DLLs from the same location and everyone is consistent.
The problem is that the references are strong coupled, so changes can sometimes be problematic if not communicated properly.
A loosely coupled system uses a framework such as MEF (Managed Extensibility Framework) and your components reference "Contract DLL" which define the interfaces for your components. The project reference the interface or contract DLLs and don't really care about the implementation and then MEF manages the plugin for you.
In this case, you reference the interface DLL but not the actual DLL that implements.
For example, say I have an interface called ILog with a method called LogMessage.
private ILog _logger;
_logger.LogMessage();
So, in a strongly coupled case: Action.DLL references Logger.DLL directly.
In a loosely coupled case Action.DLL references ILog.DLL (just the interface). Logger.DLL implements ILog.DLL. But Action.DLL has no refernce to Logger.DLL directly.
Now I can have any number of DLLs that implment the ILog interface, but the Action.DLL does not reference them directly. That's pretty cool and one of the more exciting features of MEF and loose coupling in general, the ability to not to have dependencies.
How you choose to go, either way is acceptable, I think the loosely coupled idea fits your scenario the best as teams would just have to know the contracts versus the actual implementations.
I wouldn't have one massive contract DLL, I would try and break the interfaces into logical groupings. For example, logging seems like a Utility type of interfance, so I would create a Utility contract DLL with a ILog interface. How it is split up depends on what you are trying to do. Or each interface could be a contract DLL, but maybe that is a little extreme.
This is a somewhat complex topic, especially in .NET land. I don't know about "best" solution, but I'll explain how we manage it; perhaps you will it useful for yourself.
This allows you to build large systems with lots of linked projects, but incurs in a lot of complexity issues. As, I think, any solution of this kind would.
First: physical structure (we use SVN).
There is a source control root for each project
Each project has its own trunk, branches and tags
The trunk folder has a versioned \src and \build folder, and an unversioned \lib folder
The \lib folder contains binaries to reference.
Those binaries could be 3rd party libraries or other projects that you need to link to (e.g., your SDK). All binaries under \lib come from an enterprise ivy repository (see http://ant.apache.org/ivy/). There is a lot of movement these days in .NET land concerning NuGet, so you could check that out too.
Your versioned \build folder contains build scripts, for example to get binaries from ivy, publish your project to ivy, or compile each project. They will also come in handy when you want to point a Continuous Integration server at each of your projects.
Second: To define where dependencies come from
Answer: They come from your ivy repository (it could be as simple as a network shared file system).
You have created your repository, so you have control as to its contents.
Be very careful with 3rd party binaries that get installed in the GAC. Visual Studio is a pain in the a^^ to deal with this.
Specifically:
How to properly verify that all needed
dependencies (3rd party libraries for
example) are indeed taken from the
correct location ?
Ivy gives you a great flexibility with dependencies, and it also resolves transitive dependencies; e.g., you can depend on SDK rev="1.+" status="latest.release" which would mean "the latest stable 1.x release of SDK, or on SDK rev="2.+" status="latest.integration" which would mean the latest available binary of 2.x SDK (probably as produced from a continuous integration build).
So you will always depend on compiled binaries, never on project output. And you can control which version of the binaries to get. 3rd party dependencies will probably be brought in as transitive upon your SDK.
This also means that the amount of code in your projects will stay as small as you need to have workable Visual Studio solutions. It also means that refactoring tools like ReSharper will be a lot less useful. There will also be a certain amount of complexity concerning your build scripts and your branching strategy. That depends a lot on the logic of your components.
This is a brief overview, if you think this is the sort of thing you want I can expand the answer. Good luck; the .NET ecosystem, and Visual Studio in particular, isn't really thought to work like this.

Packaging C# Applications with third party libraries?

I have an application that utilises the BouncyCastle framework, how can I package this application so that I don't have to manually put BouncyCastle's .dll on others computers? I'm assuming that this can be done with an installer or something similar? Where do applications look for referenced third party libraries by default?
As an alternate approach, you can inject assemblies into your main assembly.
There are cemmercial tools that support this like DeepSea Obfuscator or you can use ilmerge.
The general way of working is that you develop using separate assemblies and when you ship the product you do an additional build step that merges assemblies into one big assembly. You can even internalize the injected assemblies so only your public interface is accessible.
This way you can deploy your product as a single assembly which is especially nice if you're building components.
To answer your second question; the .NET framework will look in a couple of locations. The GAC is dominant but if you make sure the referenced assembly is in the same folder as your main assembly .NET will find it. No need to register it in the GAC.
Since BouncyCastle is a managed library, if you create an installer project in Visual Studio and add your application's exe to it, the installer will automatically detect the dependency on BouncyCastle, and add it to the installer project. When users install your application, BouncyCastle's dlls will be automatically copied to the installation directory and everything will be good.
You need to create installer. Best one to start with is ClickOnce. It will give you ability to put all needed files into one and provide UI for installation.
Second question. The default place to look for assemblies is GAC.

Categories