views:

581

answers:

6

Hello everybody

I have a windows service started (written in C# .net2.0).

I want to detect when the computer shutdown/reboot and cancel it. After the cancel I want do some actions and restart windows.

I have tried it, but it not working

using Microsoft.Win32;
partial class MyService: ServiceBase
{
    protected override void OnStart(string[] args)
    {
        SystemEvents.SessionEnding += new SessionEndingEventHandler(OnSessionEnding);
    }

    private void OnSessionEnding(object sender, SessionEndingEventArgs e)
    {
        e.Cancel = true;
        //Do some work...
    }
}

Another test:

partial class MyService: ServiceBase
{
    protected override void OnShutdown()
    {
        //Do some work...
        //base.OnShutdown();
    }
}
+2  A: 

I wouldn't mess with this. Windows will treat your process like a hung process (unless you go direct to the Win32 API).

My suggestion would be to take note that you're being shutdown, and perhaps schedule the activities to happen on startup?

UPDATE:
I think you're going to get stuck here, because your service won't know why Windows is being shutdown. You'll have an infinite loop:

  • Windows shutdown fires.
  • Service notices, aborts shutdown, launches app.
  • User uses app to continue the shutdown.
  • Window shutdown fires.
  • Service notices......
  • Etc.
Neil Barnwell
I can not do my activities on startup because I want lunch a winform application from my windows service when the user loggoff/shutdown/restart.My winform application have a button "Restart Now", and an other "Remind me latter", and do some other work...
scrat789
@scrat: Another no-no, windows services aren't built and shouldn't be used for interactivity with a GUI.
James
@James he *did* say that his service would launch another application, though.
Neil Barnwell
@Neil, the question says `after the cancel I want to do some actions`. I don't see where he states it should launch another app? Also the infinite loop can easily be avoided by setting a flag...
James
@James It was in the comment above: "I can not do my activities on startup because **I want lunch a winform application from my windows service** when the user loggoff/shutdown/restart." (emphasis mine). I suppose you could "set a flag" somewhere, but that's ambiguous, and would be some sort of registry setting or a file somewhere. It just feels to me like hack-hack-hacking away to get something working that wasn't necessarily a good idea in the first place.
Neil Barnwell
@Neil: fair point, but it is *do-able*. Yeah you should only be considering services if you have a process that a) needs to be running continously and b) needs to be invisible c) requires no user interactivity....(IMO)
James
Thanks for your help, my program work as I want : http://stackoverflow.com/questions/2720125/how-cancel-shutdown-from-a-windows-service-c/2728079#2728079
scrat789
+1  A: 

My advice would be to write your actions out to a file or the registry e.g.

DoSomething = true
DoSomethingElse = false

Which you could read in OnStart and process.

James
+1  A: 

AbortSystemShutdown might work:

http://msdn.microsoft.com/en-us/library/aa376630%28VS.85%29.aspx

Though I agree with Neil that it's probably not a good idea to do this.

Edit: Added sample code

using System.Runtime.InteropServices;

[DllImport("advapi32.dll", SetLastError=true)]
static extern bool AbortSystemShutdown(string lpMachineName);


if (!AbortSystemShutdown("localhost"))
{
    int err = Marshal.GetLastWin32Error();
}        
ho1
How can use AbortSystemShutdown Function in C# ?
scrat789
Using PInvoke. Here's some information about it http://www.pinvoke.net/default.aspx/advapi32/AbortSystemShutdown.html
ho1
+1  A: 

You could use the shell command shutdown -a to abort the shutdown. I don't know if it's possible to detect a shutdown though...

Vinz
A: 

Finaly I abort the idea of detect and cancel windows shutdown/reboot, But now I want detect only "shutdown -r -t xx" !

Please note the operating system where is running the programme is Windows XP.

I have try it, but I have no ExitCode with WindowsXP:

Process process = new Process();

do
{
    process.StartInfo.FileName = "shutdown.exe";
    process.StartInfo.Arguments = "/a";
    process.Start();
    process.WaitForExit();
    MessageBox.Show(string.Format("ExitCode={0}",process.ExitCode));
    Thread.Sleep(1000);
}
while (process.ExitCode != 0) ;
scrat789
I've amended my answer above with actual sample code that should hopefully work so you don't have to start this process.
ho1
@ho Windows kill other process before i can detect the shutdown, so it's not the better solution.I decide to detect the timeout windows when "shutdown -r -t xx" stop launch my program at this time.
scrat789
The solution for detect the timeout windows after "shutdown -r -t xx" is based on detect the Title of the windows :http://www.pinvoke.net/default.aspx/user32.EnumWindows
scrat789
+1  A: 

the solution was to detect the shutdown whith a winform : http://msdn.microsoft.com/fr-fr/library/microsoft.win32.systemevents.sessionending%28VS.80%29.aspx

but Windows kill other process before i can detect it, so it's not the better solution!

scrat789