views:

107

answers:

4

Is there a way to monitor when an application that is using the dll closes? The DLL and the application are both C#, neither are Windows Forms.

I can check when the main application is closing, but I would like for the DLL to see "hey the program is closing and releasing me, I should do this real quick before I die".

Any way to do it? Or am I stuck having the application dish out "do this before you die"?

+6  A: 

Perhaps the AppDomain.ProcessExit event would work for you? Note the following though (from the docs):

The total execution time of all ProcessExit event handlers is limited, just as the total execution time of all finalizers is limited at process shutdown. The default is two seconds. An unmanaged host can change this execution time by calling the ICLRPolicyManager::SetTimeout method with the OPR_ProcessExit enumeration value.

Fredrik Mörk
Thanks. I have tried to implement it, however I do not think the event is ever being called. Not sure if there is a trick to make it work. I didAppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);and as far as I can tell, it wont go into CurrentDomain_ProcessExit. My ways of checking is the code I want, as well as just making a winform message box show itself when it gets there. The box should appear then go away, or appear then hang the app from normal shutdown. But neither happen. :(
Nick
@Nick: can you share the details of that implementation (update the question for instance). I tried it out as you describe it and it works as expected.
Fredrik Mörk
A: 

We don't know the details of your code but the fact that your class library needs to be aware of when the process is exiting might indicate a design flaw of your application.

If you need to release resources or clean up other things in a deterministic way you should have a look at the IDisposable interface. If the classes exposed by your library implement this interface caller can state easily that they no longer need the dll functionality by calling Dispose().

Maybe a good starting point for further reading are the following articles:

For example you could have the following class in your class library:

using System;
using System.IO;

public class ResourceManager : IDisposable
{
    private Stream _resource;
    private bool _disposed;

    public void Dispose()
    {
        Dispose(true);

        // Use SupressFinalize in case a subclass
        // of this type implements a finalizer.
        GC.SuppressFinalize(this);
    }

    public void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                Console.WriteLine("Exiting Process. Cleaning up.");
                // free resources here
                if (_resource != null)
                    _resource.Dispose();
                Console.WriteLine("Object disposed.");
            }

            // Indicate that the instance has been disposed.
            _resource = null;
            _disposed = true;
        }
    }
}

In your main module you can then use in the following way; the using statement will guarantee that the Dispose() method is called:

using System;
using System.Windows.Forms;

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        using (ResourceManager manager = new ResourceManager())
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}
0xA3
It is a device driver, and as such needs to release the device and if possible set it back to a neutral state when the application using it leaves and does not do its duty of cleaning up. Therefore I need it to be in the DLL.When a program uses the dll, it might not call disposable, it might just leave. It will be used by myself in my program as well as others' that might not have the same coding.
Nick
@Nick: Releasing unmangaged resources like your device is exactly the scenario for using `IDisposable()`.
0xA3
But if people dont use dispose, or using, then it will not be called right?
Nick
A: 

AppDomain.ProcessExit will "normally" work but is not guarateed to fire if a process is terminated by task manager for example. Therefore it may not be ideal if your device driver needs to release large resources etc (ie they may not be released until the GC get's around to it).

See Rick Stahls blog for more details.

Ash
A: 

If it is Console Application, you need to do as the accepted answer in this question. And it is best to develop using IDisposable interface.

Soe Moe