[EntLib 5]: Logging between assemblies - c#

I've got a project that I'm working Enterprise Library logging into, and that application is made up of multiple assemblies. The UI assembly, the domain assembly and some others. Is there a way to have the logging all go to the same location (in the case of rolling flat file)?
Edit> Now that I look at it further, can you even use EntLib loggin in a class library? None of the setup that I've used thus far is available because of a lack of an app.config for a class library.

Yes, multiple assemblies can log to the same file provided that they are all running in the same app domain.
For configuration you can use the FileConfigurationSource and use the factory method LogWriterFactory(IConfigurationSource) to create a LogWriter. See External configuration files in Enterprise Library for more information.
An alternative approach would be to forgo file based configuration and use programmatic configuration.

Related

How can I run a code once per application domain in .NET Core

We have a library that is used by multiple companies. They have read-access to built DLL files which are obfusticated.
For each project this library is used, they should pay us. We want to have a telemetry system to make sure that they don't run this library in a non-agreed project.
We thought about somehow calling a telemetry URL each time a process on Windows is started that loads our DLL files. But we need to do it without requiring any coding or configuration from their side.
Is that possible? Can we implement a mechanism in .NET Core inside our library that whenever loaded inside the AppDomain is called once per process lifecycle?
Of course I know we can write code at Program.cs, but in our case, we don't have access to Program.cs and we can't ask them to code, or config anything.

Universal Apps with IoC: Dependency management/isolation

I'm a huge fan of using Unity for .NET applications to keep code module and dependencies "manageable" in large code-bases. I've used it for years with .NET by dropping assemblies into the main program's program directory and re-configuring an IoC configuration file (usually the .exe.config file), injecting new behaviour into a program without needing to re-compile the main program.
However, I have started my foray into writing universal apps for Windows Store and more importantly, Windows IoT - however because these apps are "packaged up" during compilation, I'm finding it difficult to understand how best to continue doing this.
One possible option would be to compile the "modules" (PCL/Universal class libraries) and include them (and their dependencies) as "Content" files within the Universal app, then use reflection to load types from these assemblies during the start-up of the program via reflection.
Another option would be to include all modules and their dependencies into the main program's project references before compilation but using "poor man's dependency injection to hard code the registrations and resolutions", but this feels really wrong to me - I'd ideally like to keep the separation of dependencies if at all possible?
Any ideas...?
PS. I'm not tied to Unity in any way, if there is another IoC library that does it better on this platform then fine - but Unity is what I already know and love!
I do this using Castle Windsor. You can probably use the same approach with Unity:
Limit references only to when an assembly needs a type defined in
another assembly
Define a class (or classes depending on how you want to organize) for IoC configuration in each assembly by implementing IWindsorInstaller and configure DI using the fluent API inside the implemented Install method.
Define a container instance inside your app root
At application start, use reflection to find all types implementing
IWindsorInstaller in the bin folder and run their Install method,
passing in the container instance
This way you can keep your dependencies separate, and you don't have to worry about adding extra references or adding .dlls as content files.

How can I force an application to load .NET classes from a different assembly?

Does anyone know of any way to force an application to load a specific .NET class from a separate file, without having that application's source code? Like, say, if I want to make a change to a single class in mscorlib and see what happens in a certain application, I wouldn't want to have to make a wrapper DLL for every single class in mscorlib. One thing that brought this to mind is because I absolutely hate the Windows folder browser dialog, and I'd like to be able to write a replacement class for FolderBrowserDialog. Then whenever an application tries to use it it'll use mine instead.
I just found TypeForwardedToAttribute, but that requires access to source code. I'd like to be able to do this to an existing application I don't have any source code for.
Assembly redirection / publisher policy is for this purpose but it's not very likely that you can apply it to mscorlib, especially in a system-wide fashion. When assembly redirection is used, one can redirect a given assembly to a different version of the same assembly but the target assembly must have the same public key token as the original one. Since mscorlib is strongly named (in the GAC) it's not likely that you can re-sign it after your modifications.
Also, keep in mind that FolderBrowserDialog internally uses SHBrowseForFolder so if you somehow manage to redirect it or redirect mscorlib, you still only handled managed applications - any native applications will still use the underlying SHBrowseForFolder call and you'll end up seeing different folder dialogs in different applications.
Additionally (after reading your comment) your users may already be familiar with the 'regular' Browse for folder dialog - giving them a different one may end up confusing some of them if you do that. I'm not saying it's a great dialog (it's not) but standard behavior across all applications is better for users than a single application with a better dialog.
Why not create a new folder browser dialog instead in your own projects? It's not that hard to do so. Here's an article to start with - it has links to other articles that describe techniques to change the dialog (but only within a single application).
It might be possible using .Net policy settings. Check this out (extracted from Don Box's excellent Essential .Net). Look especially at Listing 2.4 and Figure 2.11. The only thing is I am not sure if you can override built-in .Net classes and assemblies using this technique.
Listing 2.4. Setting the Version Policy
Version policy can be specified at three levels: per application, per component, and per machine. Each of these levels gets an opportunity to process the version number, with the results of one level acting as input to the level below it. This is illustrated in Figure 2.11. Note that if both the application's and the machine's configuration files have a version policy for a given assembly, the application's policy is run first, and the resultant version number is then run through the machine-wide policy to get the actual version number used to locate the assembly. In this example, if the machine-wide configuration file redirected version 1.3.0.0 of Acme.HealthCare to version 2.0.0.0, the assembly resolver would use version 2.0.0.0 when version 1.2.3.4 was requested because the application's version policy maps version 1.2.3.4 to 1.3.0.0.
You can always try decompiling the dll with ILSpy. It allows you spit out a project file with generated source code from any .net dll.
You can then edit the generated source code and compile a modified dll.

Windows service + Plugins design

I have a windows service. The idea is to execute as many different tasks as possible. Lets say we have this IServicePart interface with Start() and Stop() methods. When the service starts it will search all assemblies in some directory and find all classes which implements IServicePart. Done, no problem.
The problem:
Assembly1.dll is a good candidate for IServicePart. But it needs a configuration. For example Assembly1.dll.config. Now I can copy/paste/rename the dll to task2.dll and task2.dll.config and create a second task for the service. Each of those plugins comes with 10-20 dll dependencies
1) The most obvious problem is how to load the configuration, because the service host's appDomain is different than assembly1 and task2.
2) I expect issues when I try to load the two IServiceParts when they depend on the same 3rd party assemblies
Solution 1 is to make a custom configuration and not use the app.config.
Solution 2 is to run each plugin in its own appDomain.
What are your suggestions.
Hope I explained this correctly
===================
reference: similar question here: Plugin to use its own app.config
The way I've done this, involves having each plugin in its own app domain. However, the codebase property of those appdomains continue to point to the root directory where my service exe is located. This achieves two things:
The many tertiary dependencies that the plugins have now don't need to be duplicated. For example, I can put my logger assembly in the root folder (with the service exe) and all the plugins can see it. This is great, because I neither wish to put my logger assembly into each plugin subdirectory, nor do I wish to use the GAC.
All plugins now share the same app config (the same one used by the service exe). This is a good or bad thing, depending on your needs. But don't forget the configSource attribute, which can allow you to put specific config sections into seperate config files within your plugin subdirectories.
Incidentally, I've been using MAF for my plugins.

In .NET, is there a need to register the DLL?

Is it necessary to register a compiled DLL (written in C# .NET) on a target machine.
The target machine will have .NET installed, is it enough to simply drop the DLL onto the target machine?
I think you're confusing things a little. Registering a dll has never been needed in order to use it.
Using a dll requires only to load it (given a known location or if the library is in the system path) and get the address of the function you wanted to use.
Registering the dll was used when distributing COM or ActiveX objects which need to add certain entries to the windows registry. In order to use a COM service (for example) you need to reference a GUID — that is, a unique identifier — which allows you to get a handle to the dll that implements the service (or provide access to it). Sometimes you can make reference to a fully-qualified name and get the same results.
In order for all that to work the dll needed to be registered. This "registration" process just creates several entries in the registry, but mainly these two: one associating a GUID with the location of the dll (so that you can reference it through the GUID without knowing where is it exactly located) and a second one associating the full name with the GUID. But again, this is just for COM or ActiveX objects.
When you develop an application in .NET, the libraries referenced on your project are automatically loaded when they're needed without you having to worry about locating or loading them. In order to to that, the framework checks two locations for the referenced libraries.
The first location is the application path.
The second location is the GAC.
The GAC (Global Assembly Cache) allows you to effectively register a dll to be used throughout the system and works as an evolution of the old registering mechanism.
So basically you just need to put the dll in the same folder of the application.
You need to "drop" it into a directory where the application needing it will find it.
If there are multiple applications, or you want to "drop" the file somewhere other than the application directory, you generally need to either adjust the PATH variable, or register the assembly in the Global Assembly Cache (GAC).
It is usually enough to drop the dll into the folder of your app on the target machine.
If the dll must be available to other applications then you may want to consider the GAC.
If you wish to access the assembly via com+. An example would be using a type defined in a .NET assembly from a non .NET application, such as a VB6 winforms app.
If you plan on accessing the assembly from another .NET application, you don't have to do anything. If your assembly has a strong name, it probably is a good idea to drop it in the GAC. Otherwise, just drop it in the directory of the application that will be referencing it.
One of the great selling points of .NET for the Windows platform when it came onto the scene is that by default, .NET assembly DLLs don't have to be registered and can be consumed privately by an application by merely putting them in the same folder as the EXE file. That was a great stride forward because it enabled developers to avoid the fray of DLL/COM hell.
Shared DLL/COM modules proved to be one of the greatest design mistakes of Windows as it lead to instability of applications that users installed. Installing a new app could well screw up an app that had been working just fine - because the new app introduced newer versions of shared DLL/COM modules. (It proved in practice to be too much of a burden for developers to properly manage fine-grained version dependencies.)
It's one thing to manage versions of modules with a build repository system like Maven. Maven works extremely well doing what it does.
It's an entirely different matter, though, to deal with that problem in an end-user runtime environment spread across a population of millions of users.
The .NET GAC is by no means a sufficient solution to this age-old Windows problem.
Privately consumed DLL assemblies continue to be infinitely preferable. It's a no-brainer way to go as diskspace is extremely cheap these days (~$100 can by a terabyte drive at Fry's these days). There is nothing to be gained with sharing assemblies with other products - and yet company reputation to loose when things go south for the poor user.
Actually there is NO need to register a dll in .NET on the target machine.
If you reference a .dll in your application, click on the referenced .dll under references in your project, look at the properties and set Isolated to TRUE.
This will now automatically include this .dll in your project and your application will use the copy of the .dll included in your project without any need to register it on the target system.
To see a working Example of this look here:
http://code.msdn.microsoft.com/SEHE
The .dll in question will need to be registered on the system where you build your application for this to work properly. However once you build your project, there will not be any need to register the .dll in question on any system you deploy your application or program.
An additional benefit of using this method, is that even if in the future, another .dll is registered with the same name on the target system in question, your project will continue to use the .dll you deployed with. This is very handy where a .dll has many versions and you wish to maintain some stability, like using the one you tested with, yet all other applications will use the registered .dll unless they use the isolated = true method as well.
The example above is one of those cases, there are many versions of Skype4COM which is a Skype API .dll and can change often.
This method allows the above example to use the API .dll that the project was tested with, each time a user installs a new version of Skype, it is possible that a modified version of this .dll is installed.
Also, there are some Skype clients that do not install this .dll, the business version of the Skype client for example, is smaller, and does not include this .dll, so in this case, the project does not fail on that .dll missing and not being registered because it is included in the project as isolated = true.
An application can use a .NET dll by simply having it present in the same folder with the application.
However if you want other third-party applications to find the DLL and use it they would also have to include it in their distribution. This may not be desirable.
An alternative is to have the DLL registered in the GAC (Global Assembly Cache).

Categories