I have a console application in C#. If something goes wrong, I call Environment.Exit() to close my application. I need to disconnect from the server and close some files before the application ends.
In Java, I can implement a shutdown hook and register it via Runtime.getRuntime().addShutdownHook(). How can I achieve the same in C#?
You can attach an event handler to the current application domain's ProcessExit event:
using System;
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit += (s, e) => Console.WriteLine("Process exiting");
Environment.Exit(0);
}
}
Hook AppDomain events:
private static void Main(string[] args)
{
var domain = AppDomain.CurrentDomain;
domain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
domain.ProcessExit += new EventHandler(domain_ProcessExit);
domain.DomainUnload += new EventHandler(domain_DomainUnload);
}
static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
Console.WriteLine("MyHandler caught: " + e.Message);
}
static void domain_ProcessExit(object sender, EventArgs e)
{
}
static void domain_DomainUnload(object sender, EventArgs e)
{
}
I'd recommend wrapping the call to Environment.Exit() in your own method and using that throughout. Something like this:
internal static void MyExit(int exitCode){
// disconnect from network streams
// ensure file connections are disposed
// etc.
Environment.Exit(exitCode);
}
Related
I want to handle all unexpected errors in a WPF application. When I look at, there are different events for different situation to capture and control error. Also I added these in application constructor method
public App()
{
AppDomain.CurrentDomain.FirstChanceException += OnFirstChanceException;
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
Dispatcher.UnhandledException += OnDispatcherUnhandledException;
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
}
However, I try that for checking handling but they didn't work. What is the reason?
private void btnStart_Click(object sender, RoutedEventArgs e) //2021112242
{
throw new StackOverflowException();
}
Every exception event has his own callback method & event object
// Dispatcher.UnhandledException
private static void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
}
// TaskScheduler.UnobservedTaskException
private static void OnTaskSchedulerUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
}
// AppDomain.CurrentDomain.UnhandledException
private static void OnCurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
}
// AppDomain.CurrentDomain.FirstChanceException
private static void OnCurrentDomainUnhandledException(object sender, FirstChanceExceptionEventArgs e)
{
}
App has an event for this called DispatcherUnhandledException. This works in most cases but when the exception is thrown from a separate thread it gets a little hairy.
public partial class App
{
public App()
{
// Globally handle errors/exceptions for a friendly close.
DispatcherUnhandledException += DispatcherOnUnhandledException;
}
private void DispatcherOnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
try
{
e.Handled = true;
e.Exception.Display("An unhandled exception occurred, the application will now close.");
e.Exception.Log(); // log the problem.
Shutdown(-1); // assume not recoverable.
}
catch
{
Shutdown(-1);
}
}
}
I am writing a program that has a FileSystemWatcher. I also have two other methods that I want to run alongside the FSW. But my other methods don't get executed because the program is always at the FSW.
Essentially, I want to have the FileSystemWatcher keep going and be able to perform other actions in my program at the same time.
How can I structure my code to achieve this?
Currently, my code has this structure:
namespace MyApp
{
class Program
{
static void Main(string[] args)
{
// call the FSW
MyFileSystemWatcher(path);
// call another method
AnotherMethod1();
// call another method
AnotherMethod2();
}
//----- file system watcher methods -----//
private static void MyFileSystemWatcher(string path)
{
// code for the file system watcher
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
fileSystemWatcher.Path = path;
fileSystemWatcher.Created += FileSystemWatcher_Created;
fileSystemWatcher.Renamed += FileSystemWatcher_Renamed;
fileSystemWatcher.Deleted += FileSystemWatcher_Deleted;
fileSystemWatcher.EnableRaisingEvents = true;
}
private static void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
{
Console.WriteLine("File created: {0}", e.Name);
}
private static void FileSystemWatcher_Renamed(object sender, FileSystemEventArgs e)
{
Console.WriteLine("File renamed: {0}", e.Name);
}
private static void FileSystemWatcher_Deleted(object sender, FileSystemEventArgs e)
{
Console.WriteLine("File deleted: {0}", e.Name);
}
//----- end of file system watcher methods -----//
//----- other methods in the program -----//
public static void AnotherMethod1()
{
// code for Method1
}
private static void AnotherMethod2()
{
// code for Method2
}
}
}
Thank you.
Make your method async
private static async Task MyFileSystemWatcher(string path)
{
// code for the file system watcher
}
then
static void Main(string[] args)
{
// call the File System Watcher
var task = MyFileSystemWatcher(path);
// call another method
AnotherMethod1();
// call another method
AnotherMethod2();
}
Alternatively, If you dont want to touch your method (not preferable), then
var task = Task.Run(() => MyFileSystemWatcher(path));
I am trying to monitor a log file for changes. My code is working, and does everything it should. However, as I want this to run as a windows service and be constantly monitoring I'm not sure of the proper way to set it into a waiting state. Here is what it's doing at the moment.
public static void Main()
{
log_watcher = new FileSystemWatcher();
log_watcher.Path = Path.GetDirectoryName(pathToFile);
log_watcher.Filter = recent_file.Name;
log_watcher.NotifyFilter = NotifyFilters.LastWrite;
log_watcher.Changed += new FileSystemEventHandler(OnChanged);
log_watcher.EnableRaisingEvents = true;
//do rest of stuff OnChanged
while (true)
{
}
}
And then just a simple:
public static void OnChanged(object sender, FileSystemEventArgs e)
{
Console.WriteLine("File has changed");
}
What would be a better way in a windows service to do this?
You can start a message pump using Application.Run() from WinForms.
using System.Windows.Forms;
// The class that handles the creation of the application windows
class MyApplicationContext : ApplicationContext {
private MyApplicationContext() {
// Handle the ApplicationExit event to know when the application is exiting.
Application.ApplicationExit += new EventHandler(this.OnApplicationExit);
log_watcher = new FileSystemWatcher();
log_watcher.Path = Path.GetDirectoryName(pathToFile);
log_watcher.Filter = recent_file.Name;
log_watcher.NotifyFilter = NotifyFilters.LastWrite;
log_watcher.Changed += new FileSystemEventHandler(OnChanged);
log_watcher.EnableRaisingEvents = true;
}
public static void OnChanged(object sender, FileSystemEventArgs e) {
Console.WriteLine("File has changed");
}
private void OnApplicationExit(object sender, EventArgs e) {
Console.WriteLine("File monitor exited.");
}
[STAThread]
static void Main(string[] args) {
// Create the MyApplicationContext, that derives from ApplicationContext,
// that manages when the application should exit.
MyApplicationContext context = new MyApplicationContext();
// Run the application with the specific context. It will exit when
// all forms are closed.
Application.Run(context);
}
}
See Run(ApplicationContext) on learn.microsoft.com.
I have C# application and can monitoring Logoff and SystemShutdown events
class Program
{
static void Main(string[] args)
{
SystemEvents.SessionEnding += SystemEvents_SessionEnding;
Console.ReadLine(); //This is needed to keep the application running.
}
static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
switch (e.Reason)
{
case SessionEndReasons.Logoff:
MessageBox.Show("User logging off");
break;
case SessionEndReasons.SystemShutdown:
MessageBox.Show("System is shutting down");
break;
}
}
}
please help me , how I can monitor (get event) user Logon event?
thank you
Assuming you are running as windows service you should use SessionSwitch handler for logon session.
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
private void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
if(e.Reason==SessionSwitchReason.SessionLogon)
{
}
}
probably you should use SessionSwitch event:
static void Main(string[] args)
{
SystemEvents.SessionEnding += SystemEvents_SessionEnding;
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
Console.ReadLine(); //This is needed to keep the application running.
}
static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
switch (e.Reason)
{
case SessionSwitchReason.SessionLogon:
//do something
break;
}
}
I would like to execute a function when the running application terminated via normal close way (right top X) or un expected error happened and software terminated.
How can i do this at c# 4.5 WPF application
Thank you
In your App.xaml.cs -
Override OnStartUp method and hook UnhandledException event of
Current AppDomain, it will get called whenever application was
about to close because of some unhandled exception.
Override OnExit method for normal close of application.
Create CleanUp method and call the method from above two methods.
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}
private void CleanUp()
{
// Your CleanUp code goes here.
}
protected override void OnExit(ExitEventArgs e)
{
CleanUp();
base.OnExit(e);
}
void CurrentDomain_UnhandledException(object sender,
UnhandledExceptionEventArgs e)
{
CleanUp();
}
You could handle the Exit event of the app's Application subclass main instance
and the UnhandledException event of the current AppDomain instance like so:
public partial class App : Application {
public App() {
this.Exit += App_Exit;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
MessageBox.Show("Exception " + e.ExceptionObject.GetType().Name);
}
void App_Exit(object sender, ExitEventArgs e) {
MessageBox.Show("Bye bye");
}
}
Please note that given the following (simulated by clicking some buttons)
scenarios for unhandled exceptions:
which handle their respective click events like so:
private void buttonThrowNice_Click(object sender, RoutedEventArgs e) {
throw new Exception("test");
}
private void buttonStackOverflow_Click(object sender, RoutedEventArgs e) {
this.buttonStackOverflow_Click(sender, e);
}
private void buttonFailFast_Click(object sender, RoutedEventArgs e) {
Environment.FailFast("my fail fast");
}
private void buttonOutOfMemory_Click(object sender, RoutedEventArgs e) {
decimal[,,,,,] gargantuan = new decimal[int.MaxValue,int.MaxValue,int.MaxValue,int.MaxValue, int.MaxValue, int.MaxValue];
Debug.WriteLine("Making sure the compiler doesn't optimize anything: " + gargantuan.ToString());
}
The UnhandledException event of the AppDomain class only handles:
regular exceptions
the OutOfMemoryException
whereas the:
failfast
and the StackOverflow exception
are not caught.