Zamykanie systemu, a zapamiętywanie ustawień aplikacji

0

Witam. Mam aplikację która przy zamykaniu ma zapisywać swoje ustawienia, wyłączać pluginy (a te z kolei wtedy zapisują swoje ustawienia) etc, trochę tego jest, ale nie trwa dłużej niż 1-2s. Nie ma problemu kiedy użytkownik ręcznie wyłączy program, natomiast problem pojawia się kiedy aplikacja jest zamykana przez windowsa przy wylogowywaniu. Wtedy zdąży się zapisać tylko część ustawień, a potem najwyraźnej proces jest "killnięty". Działo się tak kiedy robiłem to w zdarzeniu Application.ApplicationExit. Obecnie jest tak i wydaje się działać poprawnie:

void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
    e.Cancel = true;

    // zapisywanie ustawień etc.. 

    e.Cancel = false;
}

Wydaje mi się to jednak mało elegancki sposób z tym chwilowym anulowaniem zdarzenia... Jest na to może jakiś lepszy sposób o którym nie wiem, a chętnie się dowiem?

0

To pierwsze ustawienie e.Cancel tak naprawdę nic tutaj nie daje.
Gdy użytkownik chce zamknąć system, ten wysyła każdej aplikacji komunikat WM_QUERYENDSESSION. Od momentu otrzymania go, aplikacja ma 5 sekund (albo 1 sekundę, jeżeli zamknięcie jest wymuszone, np. poprzez kliknięcie "zakończ teraz" czy czegoś takiego) na odpowiedź. .NET w tym wypadku wywołuje zdarzenie FormClosing. Jeżeli wywoływanie tej metody nie zakończy się w 1 albo 5 sekundach to system ma prawo ubić aplikację. Jeżeli zakończy się w "regulaminowym" czasie i ustawisz e.Cancel na true to aplikacja dostaje nieograniczoną ilość czasu na zamknięcie się (albo 5 sekund, jeżeli jest wymuszone).

W praktyce trzeba pamiętać, że system odpowie na komunikat dopiero, gdy FormClosing się zakończy. Powinieneś jak najszybciej odpowiedzieć na to zdarzenie, zostawić samo e.Cancel = true; i utworzyć nowy wątek.

Więcej o zamykaniu systemu masz tutaj: http://msdn.microsoft.com/en-[...]ry/ms700677%28v=vs.85%29.aspx

0

Może komuś się przyda:

[DllImport("User32.dll")]
public static extern bool ShutdownBlockReasonCreate(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] string pwszReason);

[DllImport("User32.dll")]
public static extern bool ShutdownBlockReasonDestroy(IntPtr hWnd);

const int WM_QUERYENDSESSION = 0x11;
const int WM_ENDSESSION = 0x0016;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_QUERYENDSESSION || m.Msg == WM_ENDSESSION)
    {
        ShutdownBlockReasonCreate(Handle, "powod");
        m.Result = IntPtr.Zero;

        // kod ktory ma sie wykonac w czasie zamykania

        ShutdownBlockReasonDestroy(Handle);
    }

    base.WndProc(ref m);
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0