7

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"?

Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
Nick
  • 739
  • 11
  • 22
  • 1
    Why do you need that? Managed DLLs free their resources automatically by garbage collector. If you need to free unmanaged resources use Finalization. – Vladislav Rastrusny Jun 10 '10 at 06:51
  • @FractalizerR: Using finalizers for freeing resources is *not* recommended because it is indeterministic. Instead, object should implement `IDisposable`. – Dirk Vollmar Jun 10 '10 at 07:05

4 Answers4

8

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
  • 155,851
  • 29
  • 291
  • 343
  • 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 did AppDomain.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 Jun 10 '10 at 07:10
  • @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 Jun 10 '10 at 08:25
  • It worked for me(TM), then on the second or third attempt it stopped working!? I am finishing my process by Ctrl-C detection and graceful exit. – gatopeich Aug 13 '12 at 15:23
1

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());
        }
    }
}
Community
  • 1
  • 1
Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
  • 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 Jun 10 '10 at 07:12
  • @Nick: Releasing unmangaged resources like your device is exactly the scenario for using `IDisposable()`. – Dirk Vollmar Jun 10 '10 at 07:26
  • But if people dont use dispose, or using, then it will not be called right? – Nick Jun 10 '10 at 10:41
  • Also, the `using` is not run in case the Process terminates before leaving the corresponding scope . – irvnriir Jun 21 '23 at 17:38
0

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.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Ash
  • 60,973
  • 31
  • 151
  • 169
0

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.

Community
  • 1
  • 1
Soe Moe
  • 3,428
  • 1
  • 23
  • 32