views:

301

answers:

4

I have made a .NET class library in C# that initializes some logging, sent to an external tool. The library is altogether separate from any application, but in order to initialize it, I need to make at least one method call to it.

Is there a way for me to put something into app.config that will auto-load that dll, and call something in it? I can change the contents to suit whatever, I don't need to support any own class name or method name or whatnot.

Note, I need this to be done without any changes to the application in question, save for changing the app.config file.

Is this possible? If so, what should I be looking at?

A: 

Yes, you can use reflection to load the content of assembly

Anton Setiawan
The whole point was to avoid changing the target application code, at all. I can easily add reflection or whatnot if I want to go down that route.
Lasse V. Karlsen
@Lasse: Hmmmm... If the target app was't built to handle this, and you don't want to update it, you are stuck. This would be a security issue if it were that magical.
Brian Genisio
Yes, that's my assumption as well, and since I can't get the configuration section answer to work, I'm guessing I need some code in the application after all. Perhaps the debugging hook that @Brian commented above could work instead.
Lasse V. Karlsen
+2  A: 

It would probably be considered a hack, but if you put something that inherits ConfigurationSection in your dll, and add that configuration section to your app.config, this would allow you to execute the code in the configuration section's constructor and thus do pretty much what you want to. It will of course only be invoked once, at application start-up but if I understood you correct that would be enough.

klausbyskov
I will try this, sounds promising.
Lasse V. Karlsen
A hack is fine. This dll hooks into the listener system of Debug and Trace, to capture all log messages, and starts background threads to monitor memory and cpu usage, everything is sent to an external logger application. It's a forensic debugging tool I need to use for an application I regrettably cannot change.
Lasse V. Karlsen
Well, I can't see why that wouldn't work then. Good luck with it and let me know how it turns out.
klausbyskov
@Lasse: If it is a forensic debugging tool, have you considered using the CLR profiler/debugger hooks available to you?
Brian Genisio
No, I have not, how would that work, would it be easy to set up? I'm trying the configuration section tip now, but it doesn't seem to load the section class at all. I will look into it some more before I change my question or leave another comment. @Brian, could you leave an answer here with some information about that for me?
Lasse V. Karlsen
@Lasse, yeah, I'm trying it out too, but with the same result as you. I was actually pretty convinced that it was going to load the sections, but it does look as if I might be wrong. Maybe you want to explore Brians comment a bit further.
klausbyskov
@Lasse: I have never used the profiling API in .net, but it is what all of the debuggers and profilers use to do their work (Ants, .Trace, .Net Memory Profiler, etc)
Brian Genisio
A: 

Snoop does this using some C++ voodoo. Fortunately the source is available - look in the project named "ManagedInjector"

Rob Fonseca-Ensor
+1  A: 

This had me puzzled for a while on how to do it. I originally thought it could be achieved by creating a custom WebProxy that would configure the logging, and loading it into the main application using the defaultProxy configuration element. This however suffer from the same problem as the other configuration suggestions in that the code is only run when required (in this case when a HTTP request is used) - thus requiring a change to the original application.

I have achieved it though by reversing the approach. Instead of trying to get the original application to configure the logging, you could write a stub of an application that configures the logging and then launches the original application.

As an example:

I have a WinForms application called Forms.exe whose entry point is defined as:

[STAThread]
internal static void Main()
{
    Application.Run(new MainForm());
}

In my stub application (which I have as a console application), I configure the logging and then load and run Forms.exe:

internal static void Main()
{
    ConfigureLogging()
    Assembly app = Assembly.LoadFrom(@".\Forms.exe");
    app.EntryPoint.Invoke(null, null);
}

This uses reflection to load the other application into the one that configures the logging.

Caveats:

  • the other application has to be a .Net application in order to load it this way
  • you might need to use Reflector to inspect the other application to work out the correct arguments to pass to the entry point (ie. if it takes string[] args, you might need to pass in an empty string[] instead of a null as the arguments)
  • the original application 's console window will hang around while the other application runs (this is probably not a problem, but if it is you could try hiding it using FreeConsole)
adrianbanks
Ah, this approach hadn't dawned on me, yes, this sounds much more promising.
Lasse V. Karlsen
This is apparently the only viable option left. I don't know the exact rules used to determine when classes related to ConfigurationSection is loaded, but it seems they're only loaded if I ever touch that configuration. In my case, and in the general case, the application doesn't read this configuration, so that won't work. However, the stub application project works like a charm.
Lasse V. Karlsen