-1

I am developing an app that need to save the time when computer shutdown, I need to be sure that always computer shutdown/restart, this code executes.

I'm writing it at Form Closing event like this:

    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    {         
        if(e.CloseReason == CloseReason.WindowsShutDown)
        {
            Properties.Settings.Default.lastShutdown = DateTime.Now;
            Properties.Settings.Default.Save();
        }
    }

Usually the code is working and it's saving the DateTime in settings, but I think sometimes the app is closed before the saving is done and lost the data. I don´t know how much time has the app before closing when shutdown.

¿Is there any way I can be sure that code always finish before shutdown?

Thanks.

WP8_CT
  • 166
  • 1
  • 2
  • 13
  • 2
    _"I think sometimes the app can be close before the saving is done and lost the data"_ -- that is always a possibility. The odds increase if your code is inefficient or otherwise slow, because Windows may terminate it. But the user can always kill your program outright, or the power could go out, or whatever. You need to be able to recover from those kinds of situations gracefully. – Peter Duniho Jul 12 '17 at 06:29
  • 1
    Also the provided code has lot's of cases were it never will be run. So if somebody just closes your form because he want's to you don't save a time. Why bother and wait for form_closing at all if you can just catch the windows message internally? – Nico Jul 12 '17 at 06:32
  • 1
    Aside from the already mentioned fact that nothing allows your code to know when a power failure is about to happen, the windows event system already *tries its best* to record shutdown and startup events. Why are you duplicating that functionality rather than just querying the event log? – Damien_The_Unbeliever Jul 12 '17 at 06:56
  • I think it's duplicated https://stackoverflow.com/questions/4617538/is-there-a-way-in-c-sharp-to-detect-a-windows-shutdown-logoff-and-cancel-that-ac – Hicham Bouchilkhi Jul 12 '17 at 07:42
  • @Damien_The_Unbeliever That's a good idea, I'm going to try to query Windows event log instead of saving it. Do you know an example of how to read it? Thanks. – WP8_CT Jul 12 '17 at 07:42
  • Possible duplicate of [Is there a way in c# to detect a Windows shutdown/logoff and cancel that action (after asking the user)](https://stackoverflow.com/questions/4617538/is-there-a-way-in-c-sharp-to-detect-a-windows-shutdown-logoff-and-cancel-that-ac) – Hicham Bouchilkhi Jul 12 '17 at 08:49

4 Answers4

2

You can attach a handler to the SystemEvents.SessionEnded event and run your code there. You can even cancel the shutdown / logoff event using the Cancel property. The same code could be run on the FormClosing event but with CloseReason == CloseReason.UserClosing || CloseReason == CloseReason.ApplicationExitCall || CloseReason == CloseReason.TaskManagerClosing to cover all scenarios.

Bogdan Anghel
  • 184
  • 3
  • 12
1

You could periodically save the last time you are alive for each session. e.g. Create a timer on the form. This way even if you lose power immediately you know the last time you were alive.

private void Form1_Load(object sender, EventArgs e)
{
    /* Set the last shutdown to the last time we were alive.. */
    Properties.Settings.Default.LastShutdown = Properties.Settings.Default.LastHeartbeat;

    this.timer1.Interval = 100;
    this.timer1.Tick += timer1_Tick;
    this.timer1.Start();

}

private void timer1_Tick(object sender, EventArgs e)
{
    Properties.Settings.Default.LastHeartbeat = DateTime.UtcNow;
    Properties.Settings.Default.Save();
}
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
1

I think it would be better if u save the variable periodically, instead of saving on 'shout down time'. This way if something goes wrong, u lose at most 1 interval.

Sabouei Alireza
  • 97
  • 1
  • 10
0

Just save the whole time the time with a timer an when the computer is shutdown and starts again, u call the last entry in the config.

`Timer time = new Timer(1);
time.Elapsed += timer_elapsed();
private static void timer_elapsed(Object source, System.Timers.ElapsedEventArgs e) { YOUR CODE HERE}`