C# 怎么阻止关机 注销 重启

时间:2022-11-18 23:27:19
 这个话题在CSDN不止一次了, 可是我没有找到答案不得不问一下 。
     
   我是这样写的:   
        private const int WM_QUERYENDSESSION = 0x0011;//要截获的关机消息 
        private int isClose = 0;
   
        protected override void WndProc(ref Message myMessage)//实现windows消息 
        {
            switch (myMessage.Msg)//获取消息ID号=0x0011 
            {
                case WM_QUERYENDSESSION:
                    myMessage.Result = (IntPtr)isClose;//向windows返回ID值,值0和1 
                    break;
                default:
                    base.WndProc(ref myMessage);
                    break;
            }
        }

结果不行 ,哪位指点一下 一定要可行的,因为我花了好长时间,还是不行。真的很感谢。

40 个解决方案

#1


我为了测试因为没有阻止关机我的电脑都关了10几次,最后我想到办法就是 我装虚拟机和装系统  为了达到这个效果还是不行的。我弄了好半天 ,高手快帮个忙,谢谢

#2


我把我做的  和最想要的效果说一下 这个情况好多的。
          private int isClose = 0;
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
          
            if (m.Msg == 0x11)//WM_QUERYENDSESSION  
            {
                SelectPowered();
                m.Result = (IntPtr)isClose;//0不关闭程序和系统;1关闭程序及系统  
                return;
            }
            base.WndProc(ref m);
        }

        private void SelectPowered()
        {
            if (MessageBox.Show("系统正在关机,你还没保存该文件,你是否要关机","请选择",MessageBoxButtons.YesNo ,MessageBoxIcon.Warning )==DialogResult.Yes )
            {
                isClose = 1;
            }
            else
            {
                isClose = 0;
            }
        }



关机时候询问用户一下,请不要写在关闭窗体时候询问 ,有些用户是直接关机的,所以只能这样做,为什么不能达到效果 ,虚拟机也在关机时候询问 要的和那是一样的,我在线等待高手的解答。

#3


private bool isClose = true;
        public const int WM_QUERYENDSESSION = 0x11;
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_QUERYENDSESSION)
            {
                isClose = false;
            }
            base.WndProc(ref m);
        }
        protected override void OnClosing(CancelEventArgs e)
        {
            if (!isClose )
            {
                e.Cancel = true;
            }
            base.OnClosing(e);
              isClose = true;
        }

#4


好像楼上这样就可以了,我以前貌似也是这样写的。

#5


做个记号

#6


没那么麻烦,直接Closing中阻止掉就可以了。

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.WindowsShutDown)
    {
        e.Cancel = true;
    }
}

#7


引用 3 楼 wuyq11 的回复:
private bool isClose = true;
  public const int WM_QUERYENDSESSION = 0x11;
  protected override void WndProc(ref Message m)
  {
  if (m.Msg == WM_QUERYENDSESSION)
  {
  isClose = false;
  }
  ……

估计是对的吧,屏蔽关闭消息吧

#8


你们说的我都试了 不行的 在这之前我都试了 刚刚又试了一次 还是不行  电脑还是直接的关机 ,请问你们的电脑是XP3的系统不?我的是XP3 怎么就不可以 很郁闷。

#9


该回复于2010-12-03 10:17:36被版主删除

#10


引用 3 楼 wuyq11 的回复:
private bool isClose = true;
  public const int WM_QUERYENDSESSION = 0x11;
  protected override void WndProc(ref Message m)
  {
  if (m.Msg == WM_QUERYENDSESSION)
  {
  isClose = false;
  }
  ……


还是不行

#11


#12


我要是是防止关机 不是去关机

#13


OS才不管你弹出的框呢!

#14


关注下

#15


引用 12 楼 qq183670101 的回复:
我要是是防止关机 不是去关机

你楼上给贴的代码就是调用系统api函数实现注销,重启或者关闭计算机的,micro的XP操作系统貌似都是这个原理吧?


只举例关闭计算机的函数部分:
//导入API函数
//导入获取系统特定的权限值的函数
[DllImport("advapi32.dll", SetLastError=true) ] 
internal static extern bool LookupPrivilegeValue( string host, string name, ref long pluid ); 
//导入调整访问令牌权限的函数
[DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true) ] 
internal static extern bool AdjustTokenPrivileges( IntPtr htok, bool disall, ref TokenPrivilegeLuid newst, int len, IntPtr prev, IntPtr relen );
//导入关闭计算机的函数
[DllImport("user32.dll", ExactSpelling=true, SetLastError=true) ] 
internal static extern bool ExitWindowsEx( int flags, int reason ); 

//退出Windows的具体实现方法
public bool DoExitWin( int flags ) 
{
bool ok;
//定义向非托管函数之间相互传递值的的类型变量objTPL
TokenPrivilegeLuid objTPL;
//设定objTPL的值
//设置权限个数为1
objTPL.PrivilegesCount = 1;
//给PrivilegesLuid赋初始值,无其他含义
objTPL.PrivilegesLuid = 0;
//设置权限属性,允许使用特权
objTPL.PrivilegesAttributes = SE_PRIVILEGE_ENABLED;

//初始化为零的指针句柄,为下面的调用做准备
//htok含义为handle token令牌句柄,这里遵循VC++的命名习惯
IntPtr htok = IntPtr.Zero;

//获取当前进程的句柄,结果在hproc结构体中
//hproc含义为handle process进程句柄,这里遵循VC++的命名习惯
IntPtr hproc = GetCurrentProcess();

//以调整和查询的方式打开本进程的访问令牌,访问令牌句柄返回在htok结构体中
ok = OpenProcessToken( hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok );
if(!ok)
{
return false;
}
//获取系统关机的权限值,结果在objTPL.PrivilegesLuid中
ok = LookupPrivilegeValue( null, SE_SHUTDOWN_NAME, ref objTPL.PrivilegesLuid ); 
if(!ok)
{
return false;
}
//修改当前进程访问令牌的权限,使其具有关机权限 
//这里使用到了objTPL.PrivilegesAttributes = SE_PRIVILEGE_ENABLED的值
ok = AdjustTokenPrivileges(htok, false, ref objTPL, 0, IntPtr.Zero, IntPtr.Zero );
if(!ok)
{
return false;
}
//调用退出Windows的函数,具体是关机、注销还是重启等由flags的值来确定
//EWX_FORCE 是强迫中止没有响应的进程,这样能保证关机操作的进行
ok = ExitWindowsEx(flags | EWX_FORCE, 0 ); 
if(!ok)
{
return false;
}
return true;
}

objTPL.PrivilegesLuid,objTPL.PrivilegesAttributes 难道是修改这2个?

我记得用XP关机程序时,如果开着某些外挂程序,会弹出提示是否关闭YES或者NO选项,如果不选就卡在那永远不会关机了。 C# 怎么阻止关机 注销 重启
楼主有空可以试验在explorer.exe尚未关闭之时启动卡死进程。。。看看行不行。
另外 上面的方法可以强制杀死几乎所有顽固进程(列出来供参考)。

#16


C#  到底能不能? 我想应该能 大概还是没有找到好方法 

#17


该回复于2010-10-19 10:30:36被版主删除

#18


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Ex
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private const int WM_QUERYENDSESSION = 0x0011;
        private int isClose = 0;

        protected override void WndProc(ref System.Windows.Forms.Message myMessage)
        {
            switch (myMessage.Msg)
            {
                case WM_QUERYENDSESSION:
                    myMessage.Result = (IntPtr)isClose;
                    break;
                default:
                    base.WndProc(ref myMessage);
                    break;
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            this.isClose = 0;
            MessageBox.Show("请关机试试!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}


楼主试试上面的!

#19


我也运行过了试试,好像没反应,我是Win7的

#20


不能用EXE的方式。要用DLL注入。

#21


要是我拨插头呢,怎么阻止我,哈哈~

#22


该回复于2010-10-19 10:31:23被版主删除

#23


引用 21 楼 sailorxing 的回复:
要是我拨插头呢,怎么阻止我,哈哈~


+10

#24


引用 18 楼 laomengzi 的回复:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Ex
{
  public ……

我最开始就是这样的做 不行的 

#25


引用 21 楼 sailorxing 的回复:
要是我拨插头呢,怎么阻止我,哈哈~


你没有看见或者看懂我的意思  我们做业务不是做黑客 

#26


hook ExitWindowsEx

#27


以前做过, 做windows 7 LogoTest认证的时候需要实现此功能

#28


引用 25 楼 qq183670101 的回复:
引用 21 楼 sailorxing 的回复:
要是我拨插头呢,怎么阻止我,哈哈~


你没有看见或者看懂我的意思 我们做业务不是做黑客

做黑客的话,也不能拔你的插头啊。。。
呵呵,帮楼主顶一下,和lz一样期待答案。。。

#29


引用 12 楼 qq183670101 的回复:
我要是是防止关机 不是去关机
 我承认我看错了!

#30


C# 怎么阻止关机 注销 重启坐等

#31


删除掉windows/system32文件夹里面的ShutDown.exe
哇哈哈哈哈~~~~

#32


该回复于2010-10-21 09:59:43被版主删除

#33


该回复于2010-10-21 09:59:43被版主删除

#34


给你发了邮件,可以了没?

#35


用HOOK获取关机的“动作”
在发消息阻止关机

#36


引用 34 楼 wuyazhe 的回复:
给你发了邮件,可以了没?

昨天有事情 没有去公司 不好意思,很感谢你的热心,

#37


既然我们交流了 ,你想过这个问题没有 这样阻止不完善, 这样系统关机执行 只是到我们窗口才停止关机
应该满足 一点击关机按钮 就提示 是否真的关机 ,虚拟机都是这样的啊 ,值得思考。

#38


用钩子不怎么会  高手指点一下  一定要用全局钩子,请不要用线程钩子。

#39


楼主还没解决吗?
楼主的程序没问题,有问题的是系统。
打开注册表:
HKEY_CURRENT_USER\Control Panel\Desktop
AutoEndTasks 改为0;
HungAppTimeout 改为5000;
WaitToKillAppTimeout 改为20000;
这些都是默认值,可能你装的是别人做的系统给改掉了。特别是第一个,改成1系统关机不会给你的程序发消息。

#40


我有试过上述的方式,在XP下可以拦截。。。 在win7下,无效。。。  哪位高人能指点迷津。。。  小弟当感激不尽。。。 O(∩_∩)O~  我QQ:632926748

#1


我为了测试因为没有阻止关机我的电脑都关了10几次,最后我想到办法就是 我装虚拟机和装系统  为了达到这个效果还是不行的。我弄了好半天 ,高手快帮个忙,谢谢

#2


我把我做的  和最想要的效果说一下 这个情况好多的。
          private int isClose = 0;
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
          
            if (m.Msg == 0x11)//WM_QUERYENDSESSION  
            {
                SelectPowered();
                m.Result = (IntPtr)isClose;//0不关闭程序和系统;1关闭程序及系统  
                return;
            }
            base.WndProc(ref m);
        }

        private void SelectPowered()
        {
            if (MessageBox.Show("系统正在关机,你还没保存该文件,你是否要关机","请选择",MessageBoxButtons.YesNo ,MessageBoxIcon.Warning )==DialogResult.Yes )
            {
                isClose = 1;
            }
            else
            {
                isClose = 0;
            }
        }



关机时候询问用户一下,请不要写在关闭窗体时候询问 ,有些用户是直接关机的,所以只能这样做,为什么不能达到效果 ,虚拟机也在关机时候询问 要的和那是一样的,我在线等待高手的解答。

#3


private bool isClose = true;
        public const int WM_QUERYENDSESSION = 0x11;
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_QUERYENDSESSION)
            {
                isClose = false;
            }
            base.WndProc(ref m);
        }
        protected override void OnClosing(CancelEventArgs e)
        {
            if (!isClose )
            {
                e.Cancel = true;
            }
            base.OnClosing(e);
              isClose = true;
        }

#4


好像楼上这样就可以了,我以前貌似也是这样写的。

#5


做个记号

#6


没那么麻烦,直接Closing中阻止掉就可以了。

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.WindowsShutDown)
    {
        e.Cancel = true;
    }
}

#7


引用 3 楼 wuyq11 的回复:
private bool isClose = true;
  public const int WM_QUERYENDSESSION = 0x11;
  protected override void WndProc(ref Message m)
  {
  if (m.Msg == WM_QUERYENDSESSION)
  {
  isClose = false;
  }
  ……

估计是对的吧,屏蔽关闭消息吧

#8


你们说的我都试了 不行的 在这之前我都试了 刚刚又试了一次 还是不行  电脑还是直接的关机 ,请问你们的电脑是XP3的系统不?我的是XP3 怎么就不可以 很郁闷。

#9


该回复于2010-12-03 10:17:36被版主删除

#10


引用 3 楼 wuyq11 的回复:
private bool isClose = true;
  public const int WM_QUERYENDSESSION = 0x11;
  protected override void WndProc(ref Message m)
  {
  if (m.Msg == WM_QUERYENDSESSION)
  {
  isClose = false;
  }
  ……


还是不行

#11


#12


我要是是防止关机 不是去关机

#13


OS才不管你弹出的框呢!

#14


关注下

#15


引用 12 楼 qq183670101 的回复:
我要是是防止关机 不是去关机

你楼上给贴的代码就是调用系统api函数实现注销,重启或者关闭计算机的,micro的XP操作系统貌似都是这个原理吧?


只举例关闭计算机的函数部分:
//导入API函数
//导入获取系统特定的权限值的函数
[DllImport("advapi32.dll", SetLastError=true) ] 
internal static extern bool LookupPrivilegeValue( string host, string name, ref long pluid ); 
//导入调整访问令牌权限的函数
[DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true) ] 
internal static extern bool AdjustTokenPrivileges( IntPtr htok, bool disall, ref TokenPrivilegeLuid newst, int len, IntPtr prev, IntPtr relen );
//导入关闭计算机的函数
[DllImport("user32.dll", ExactSpelling=true, SetLastError=true) ] 
internal static extern bool ExitWindowsEx( int flags, int reason ); 

//退出Windows的具体实现方法
public bool DoExitWin( int flags ) 
{
bool ok;
//定义向非托管函数之间相互传递值的的类型变量objTPL
TokenPrivilegeLuid objTPL;
//设定objTPL的值
//设置权限个数为1
objTPL.PrivilegesCount = 1;
//给PrivilegesLuid赋初始值,无其他含义
objTPL.PrivilegesLuid = 0;
//设置权限属性,允许使用特权
objTPL.PrivilegesAttributes = SE_PRIVILEGE_ENABLED;

//初始化为零的指针句柄,为下面的调用做准备
//htok含义为handle token令牌句柄,这里遵循VC++的命名习惯
IntPtr htok = IntPtr.Zero;

//获取当前进程的句柄,结果在hproc结构体中
//hproc含义为handle process进程句柄,这里遵循VC++的命名习惯
IntPtr hproc = GetCurrentProcess();

//以调整和查询的方式打开本进程的访问令牌,访问令牌句柄返回在htok结构体中
ok = OpenProcessToken( hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok );
if(!ok)
{
return false;
}
//获取系统关机的权限值,结果在objTPL.PrivilegesLuid中
ok = LookupPrivilegeValue( null, SE_SHUTDOWN_NAME, ref objTPL.PrivilegesLuid ); 
if(!ok)
{
return false;
}
//修改当前进程访问令牌的权限,使其具有关机权限 
//这里使用到了objTPL.PrivilegesAttributes = SE_PRIVILEGE_ENABLED的值
ok = AdjustTokenPrivileges(htok, false, ref objTPL, 0, IntPtr.Zero, IntPtr.Zero );
if(!ok)
{
return false;
}
//调用退出Windows的函数,具体是关机、注销还是重启等由flags的值来确定
//EWX_FORCE 是强迫中止没有响应的进程,这样能保证关机操作的进行
ok = ExitWindowsEx(flags | EWX_FORCE, 0 ); 
if(!ok)
{
return false;
}
return true;
}

objTPL.PrivilegesLuid,objTPL.PrivilegesAttributes 难道是修改这2个?

我记得用XP关机程序时,如果开着某些外挂程序,会弹出提示是否关闭YES或者NO选项,如果不选就卡在那永远不会关机了。 C# 怎么阻止关机 注销 重启
楼主有空可以试验在explorer.exe尚未关闭之时启动卡死进程。。。看看行不行。
另外 上面的方法可以强制杀死几乎所有顽固进程(列出来供参考)。

#16


C#  到底能不能? 我想应该能 大概还是没有找到好方法 

#17


该回复于2010-10-19 10:30:36被版主删除

#18


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Ex
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private const int WM_QUERYENDSESSION = 0x0011;
        private int isClose = 0;

        protected override void WndProc(ref System.Windows.Forms.Message myMessage)
        {
            switch (myMessage.Msg)
            {
                case WM_QUERYENDSESSION:
                    myMessage.Result = (IntPtr)isClose;
                    break;
                default:
                    base.WndProc(ref myMessage);
                    break;
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            this.isClose = 0;
            MessageBox.Show("请关机试试!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}


楼主试试上面的!

#19


我也运行过了试试,好像没反应,我是Win7的

#20


不能用EXE的方式。要用DLL注入。

#21


要是我拨插头呢,怎么阻止我,哈哈~

#22


该回复于2010-10-19 10:31:23被版主删除

#23


引用 21 楼 sailorxing 的回复:
要是我拨插头呢,怎么阻止我,哈哈~


+10

#24


引用 18 楼 laomengzi 的回复:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Ex
{
  public ……

我最开始就是这样的做 不行的 

#25


引用 21 楼 sailorxing 的回复:
要是我拨插头呢,怎么阻止我,哈哈~


你没有看见或者看懂我的意思  我们做业务不是做黑客 

#26


hook ExitWindowsEx

#27


以前做过, 做windows 7 LogoTest认证的时候需要实现此功能

#28


引用 25 楼 qq183670101 的回复:
引用 21 楼 sailorxing 的回复:
要是我拨插头呢,怎么阻止我,哈哈~


你没有看见或者看懂我的意思 我们做业务不是做黑客

做黑客的话,也不能拔你的插头啊。。。
呵呵,帮楼主顶一下,和lz一样期待答案。。。

#29


引用 12 楼 qq183670101 的回复:
我要是是防止关机 不是去关机
 我承认我看错了!

#30


C# 怎么阻止关机 注销 重启坐等

#31


删除掉windows/system32文件夹里面的ShutDown.exe
哇哈哈哈哈~~~~

#32


该回复于2010-10-21 09:59:43被版主删除

#33


该回复于2010-10-21 09:59:43被版主删除

#34


给你发了邮件,可以了没?

#35


用HOOK获取关机的“动作”
在发消息阻止关机

#36


引用 34 楼 wuyazhe 的回复:
给你发了邮件,可以了没?

昨天有事情 没有去公司 不好意思,很感谢你的热心,

#37


既然我们交流了 ,你想过这个问题没有 这样阻止不完善, 这样系统关机执行 只是到我们窗口才停止关机
应该满足 一点击关机按钮 就提示 是否真的关机 ,虚拟机都是这样的啊 ,值得思考。

#38


用钩子不怎么会  高手指点一下  一定要用全局钩子,请不要用线程钩子。

#39


楼主还没解决吗?
楼主的程序没问题,有问题的是系统。
打开注册表:
HKEY_CURRENT_USER\Control Panel\Desktop
AutoEndTasks 改为0;
HungAppTimeout 改为5000;
WaitToKillAppTimeout 改为20000;
这些都是默认值,可能你装的是别人做的系统给改掉了。特别是第一个,改成1系统关机不会给你的程序发消息。

#40


我有试过上述的方式,在XP下可以拦截。。。 在win7下,无效。。。  哪位高人能指点迷津。。。  小弟当感激不尽。。。 O(∩_∩)O~  我QQ:632926748