Home > Software engineering >  Detect when a console application is closed?
Detect when a console application is closed?

Time:03-26

I have an app that I need to clean up some resources before it shuts down. I've got it handling the event using: AppDomain.CurrentDomain.ProcessExit = OnProcessExit;

private static async void OnProcessExit(object? sender, EventArgs e)
{
    Console.WriteLine("We");
    Thread.Sleep(1000);
    Console.WriteLine("Are");
    Thread.Sleep(1000);
    Console.WriteLine("Closing");
}

But the event never gets fired? At least I don't see it, it instantly closes. I've tried this in an external and internal console and neither seem to catch it.

Using Linux Ubuntu 20.10

CodePudding user response:

Normally you should use AppDomain.ProcessExit rather than AppDomain.CurrentDomain.ProcessExit. Is there a specific reason why you're using the second form?

How is your console app closing? Is it a normal exit after finishing its work, or failing due to an unmanaged exception, or dying due to a rude shutdown (eg Ctrl-C, Environment.FailFast, etc)?

In the first two cases AppDomain.ProcessExit should be invoked normally. But if that isn't happening for some reason, you can use Try..Finally to do resource cleanup.

In the third case, it's very likely that AppDomain.ProcessExit won't be invoked. And there's not a lot you can do about that.

Are you using a Debug or Release build? Because shutdown behaviour can be different depending on the build type. In addition, apps hosted within Docker might have unusual shutdown behaviour.

CodePudding user response:

While you might see it as overkill in the beginning, I can recommend wrapping your console app in .NET Generic Host. This enables you to easily handle resource initialisation and cleanup, it also encapsulates logging and DI and nested services if available. The console app becomes easy to startup in an integration test, install as a Windows service (e.g. via Topshelf) or just keep running as a console app.

https://docs.microsoft.com/en-us/dotnet/core/extensions/generic-host

To get started you can run in command prompt

dotnet new worker

Then in Worker.cs you can override the StopAsync

public override async Task StopAsync(CancellationToken cancellationToken)
{
    await Task.Delay(1000);
    _logger.LogInformation("Ended!");
}

Running with dotnet run you will see logging each second, and when you Ctrl C you will see "Ended!" after 1 second - here you do any resource cleanup needed.

  • Related