Intercept ShutDown Event in C# ? Problem with error code 0xC000014

M

Milan

Hi all,

I am trying to write application which will intercept ShutDown event and
then cancel that even do some backup work and then fire again shut down
event. The problem I am facing is that after capturing shutdown event
following line does not help me to cancel it completlly:
System.Diagnostics.Process.Start(@"C:\WINNT\system32\shutdown.exe", "-a");

So ShutDown seems to be canceld but my application report error code
0xC0000142 in User32.dll, and can not proceed with backup operation.

Is there any way to cancel shutdown event and that application have all
needed dlls available so that my application can do its job completlly ?

br,
Milan.
 
J

Jackie

Hi all,

I am trying to write application which will intercept ShutDown event and
then cancel that even do some backup work and then fire again shut down
event. The problem I am facing is that after capturing shutdown event
following line does not help me to cancel it completlly:
System.Diagnostics.Process.Start(@"C:\WINNT\system32\shutdown.exe", "-a");

So ShutDown seems to be canceld but my application report error code
0xC0000142 in User32.dll, and can not proceed with backup operation.

Is there any way to cancel shutdown event and that application have all
needed dlls available so that my application can do its job completlly ?

br,
Milan.

I wrote some code for you but I haven't tried it, so I have no idea if
it actually works at all.

1. Drop a NotifyIcon your form or replace my code when I use it.

2. Put this code in your form:
------------------------------------------------------------
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case Unmanaged.Constants.WM_QUERYENDSESSION:
Unmanaged.User32.ShutdownBlockReasonCreate(Handle,
"Performing backup operation");
notifyIcon1.ShowBalloonTip(2000, "Information",
"Tried to prevent ending your session", ToolTipIcon.Info);
m.Result = IntPtr.Zero;

new Thread(new
ParameterizedThreadStart(beginBackup)).Start(new BeginBackupArg(Handle));

return;

case Unmanaged.Constants.WM_ENDSESSION:
notifyIcon1.ShowBalloonTip(5000, "Information",
"Your session is about to end", ToolTipIcon.Info);
m.Result = IntPtr.Zero;
return;
}

base.WndProc(ref m);
}

private class BeginBackupArg
{
public IntPtr ShutdownBlockerHandle { get; private set; }

public BeginBackupArg(IntPtr shutdownBlockerHandle)
{
ShutdownBlockerHandle = shutdownBlockerHandle;
}
}

private void beginBackup(object obj)
{
BeginBackupArg arg = (BeginBackupArg)obj;
// Do some work
Thread.Sleep(5000);

Unmanaged.User32.ShutdownBlockReasonDestroy(arg.ShutdownBlockerHandle);

// Shutdown Windows?
}
------------------------------------------------------------

3. Put this code somewhere as well:
------------------------------------------------------------
public class Unmanaged
{
public class Constants
{
public const int WM_QUERYENDSESSION = 0x11;
public const int WM_ENDSESSION = 0x16;
}

public class User32
{
[DllImport("user32.dll", SetLastError = true)]
public static extern bool ShutdownBlockReasonCreate(IntPtr
hWnd, [MarshalAs(UnmanagedType.LPWStr)] string reason);

[DllImport("user32.dll", SetLastError = true)]
public static extern bool ShutdownBlockReasonDestroy(IntPtr
hWnd);
}
}
------------------------------------------------------------
 
J

Jackie

I have tested my code on Windows XP and it seemed to kind of work. I
have improved it to work better. I have not yet tested it on Vista or
later but I'll test it on Windows 7 later.

Form1.cs
--------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;

namespace BackupApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
notifyIcon1.Icon = Icon;
}

protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case Unmanaged.Constants.WM_QUERYENDSESSION:
Unmanaged.EndSessionOption endSessionOption =
(Unmanaged.EndSessionOption)m.WParam;
if
(endSessionOption.HasFlag(Unmanaged.EndSessionOption.ShuttingDownOrRestarting))
{
// The system is either shutting down or
restarting.
// Prevent ending the session.
m.Result = IntPtr.Zero;
return;
}

break;

case Unmanaged.Constants.WM_ENDSESSION:
// Is the session is being ended?
if (m.WParam.ToInt32() != 0)
{
// Nothing we can do about it then?
break;
}

// Prevented ending the session

if (Environment.OSVersion.Version.Major >= 6)
{

Unmanaged.User32.ShutdownBlockReasonCreate(Handle, "Backup is in progress");
}

notifyIcon1.ShowBalloonTip(5000, "Backup", "Backup
is in progress...", ToolTipIcon.Info);

new Thread(new
ParameterizedThreadStart(beginBackup)).Start(new BeginBackupArg(this));

m.Result = IntPtr.Zero;
return;
}

base.WndProc(ref m);
}

private class BeginBackupArg
{
// Only used in Vista and later
public Form ShutdownBlockerWindow { get; private set; }

public BeginBackupArg(Form shutdownBlockerWindow)
{
ShutdownBlockerWindow = shutdownBlockerWindow;
}
}

private void beginBackup(object obj)
{
BeginBackupArg arg = (BeginBackupArg)obj;

Thread.Sleep(5000); // Do some real work instead

if (Environment.OSVersion.Version.Major >= 6)
{

Unmanaged.User32.ShutdownBlockReasonDestroy(arg.ShutdownBlockerWindow.Handle);
}

arg.ShutdownBlockerWindow.Invoke(new MethodInvoker(delegate
{
notifyIcon1.ShowBalloonTip(3000, "Backup", "Backup
is complete.", ToolTipIcon.Info);
}));
Thread.Sleep(3000);

// Shutdown Windows?
}
}

public class Unmanaged
{
public class Constants
{
public const int WM_QUERYENDSESSION = 0x11;
public const int WM_ENDSESSION = 0x16;
}

[Flags]
public enum EndSessionOption: uint
{
ShuttingDownOrRestarting = 0x0,
CloseApp = 0x1,
Critical = 0x40000000,
Logoff = 0x80000000
}

public class User32
{
[DllImport("user32.dll", SetLastError = true)]
public static extern bool ShutdownBlockReasonCreate(IntPtr
hWnd, [MarshalAs(UnmanagedType.LPWStr)] string reason);

[DllImport("user32.dll", SetLastError = true)]
public static extern bool ShutdownBlockReasonDestroy(IntPtr
hWnd);
}
}
}
--------------------------------------------------
 
J

Jackie


Just so you know, there are some errors in my code (it will still work
however). Just read the documentation. I will however experiment with it
because I am kind of interested. :)
 
J

Jackie

Just so you know, there are some errors in my code (it will still work
however). Just read the documentation. I will however experiment with it
because I am kind of interested. :)

Before someone tells me what I already know (that there is a mistake in
my code), I'll just let you know what it is:
You should call ShutdownBlockReasonCreate when handling
WM_QUERYENDSESSION and not in WM_ENDSESSION.
 
M

Milan

Hi Jacki,

thanks a lot for your interest & code it work in sence that it stops
ShotDown Event (it can be done from my point of view even simplier with
e.CloseReason.Equals(CloseReason.WindowsShutDown)
and
System.Diagnostics.Process.Start(@"C:\WINNT\system32\shutdown.exe", "-a");

but the problem I still have is that after I call cancel of Shut down I am
calling external tool cleartool.exe (ClearCase tool) in order to save same
files.
Problem I am still getting is that cleartool.exe have problem in
initiallizing and than it reports error 0xc0000142. Is seems that ShutDown
event have allready shut down some services before the turn to shut down of
my application came, possible ?
Is it possible to catch ShutDown event before it start turning off
applications, and services on my PC ?

Br,
Milan.
 
J

Jackie

Hi Jacki,

thanks a lot for your interest& code it work in sence that it stops
ShotDown Event (it can be done from my point of view even simplier with
e.CloseReason.Equals(CloseReason.WindowsShutDown)
and
System.Diagnostics.Process.Start(@"C:\WINNT\system32\shutdown.exe", "-a");

but the problem I still have is that after I call cancel of Shut down I am
calling external tool cleartool.exe (ClearCase tool) in order to save same
files.
Problem I am still getting is that cleartool.exe have problem in
initiallizing and than it reports error 0xc0000142. Is seems that ShutDown
event have allready shut down some services before the turn to shut down of
my application came, possible ?
Is it possible to catch ShutDown event before it start turning off
applications, and services on my PC ?

Br,
Milan.

I understand the problem. Have you tried my method? I gave it a try to
launch notepad at least, and it worked fine without errors.
Worked in both Windows XP and 7. IE seems to work as well.
 
R

Rick Lones

Milan said:
Hi Jacki,

thanks a lot for your interest & code it work in sence that it stops
ShotDown Event (it can be done from my point of view even simplier with
e.CloseReason.Equals(CloseReason.WindowsShutDown)
and
System.Diagnostics.Process.Start(@"C:\WINNT\system32\shutdown.exe", "-a");

but the problem I still have is that after I call cancel of Shut down I am
calling external tool cleartool.exe (ClearCase tool) in order to save same
files.
Problem I am still getting is that cleartool.exe have problem in
initiallizing and than it reports error 0xc0000142. Is seems that ShutDown
event have allready shut down some services before the turn to shut down of
my application came, possible ?

Of course, it's entirely possible that anything external that your app depends
on has already been shut down. You have no control over the order in which apps
are notified, AFAIK. If you have that kind of dependency on a service then I
would think it is up to you to be sure it is satisfied. If that means checking
for and possibly restarting services, then you need to look into how to do that.
And you just might have to stop the service afterwards as well - I have no
idea whether Windows will catch a service it has already shut down once that has
been restarted . . .

(But frankly, if you have this kind of dependency at all, I have to wonder
whether your overall system design is fully baked.)
Is it possible to catch ShutDown event before it start turning off
applications, and services on my PC ?

I don't know for sure that it isn't - but I would doubt it. Possibly setting
your task priority higher than normal would get you notified sooner, but that
strikes me as a very shaky thing to depend on even if it did APPEAR to work.

HTH,
-rick-
 
M

Milan

HI Jacki,

yes I tried your code but it brought the same error as before. Could you
please send me yout test project with Notped start, so that I can try it ?

My eMail is:
(e-mail address removed)

Br,
Milan.
 
M

Milan

Hi Rick,

I tried wit High proces priority but the same initialization problem
happens. Any other idea ?


Br,
Milan.
 
J

Jackie

HI Jacki,

yes I tried your code but it brought the same error as before. Could you
please send me yout test project with Notped start, so that I can try it ?

My eMail is:
(e-mail address removed)

Br,
Milan.

I have now e-mailed you. :)
 
J

Jackie

Also, please be aware that the balloon tips are somehow not working
optimally under Windows 7, but they do on XP. I don't know why they
don't. They are somehow delayed or don't show up at all. Maybe it's a
problem with my setup but I doubt it.
Also, it seems like when you try to shutdown Windows 7, the my example
application does not close, and you will either need to force the
shutdown or cancel it. I am not really sure how to fix that yet, but I
don't feel like digging into that now.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top