如何在C# WinForm应用程序中关闭Windows会话并关闭计算机?
在C# WinForm中实现Windows会话注销与关机操作
要实现关闭Windows会话(注销)或直接关机,.NET框架本身没有提供直接的API,需要通过P/Invoke调用Win32系统函数来完成,核心是处理系统权限和调用对应的系统操作函数。
核心实现步骤
导入Win32 API函数
需要用到调整权限的AdjustTokenPrivileges、会话注销的ExitWindowsEx,以及关机/重启的InitiateSystemShutdownEx。提升程序权限
执行关机、重启这类系统操作需要程序拥有SE_SHUTDOWN_NAME特权,所以要先调整进程令牌权限。实现具体操作方法
分别封装注销、关机、重启的方法,在WinForm控件事件中调用即可。
完整代码示例
using System; using System.Runtime.InteropServices; using System.Windows.Forms; namespace WinFormShutdownDemo { public partial class MainForm : Form { // 导入Win32 API [DllImport("advapi32.dll", SetLastError = true)] private static extern bool AdjustTokenPrivileges(IntPtr tokenHandle, bool disableAllPrivileges, ref TOKEN_PRIVILEGES newState, int bufferLength, IntPtr previousState, IntPtr returnLength); [DllImport("advapi32.dll", SetLastError = true)] private static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref LUID lpLuid); [DllImport("user32.dll", SetLastError = true)] private static extern bool ExitWindowsEx(uint uFlags, uint dwReason); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern bool InitiateSystemShutdownEx(string lpMachineName, string lpMessage, uint dwTimeout, bool bForceAppsClosed, bool bRebootAfterShutdown, uint dwReason); // 权限相关结构体 private struct LUID { public uint LowPart; public int HighPart; } private struct TOKEN_PRIVILEGES { public uint PrivilegeCount; public LUID Luid; public uint Attributes; } // 常量定义 private const uint SE_PRIVILEGE_ENABLED = 0x00000002; private const uint TOKEN_ADJUST_PRIVILEGES = 0x0020; private const uint TOKEN_QUERY = 0x0008; private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; private const uint EWX_LOGOFF = 0x00000000; // 注销 private const uint EWX_FORCE = 0x00000004; // 强制关闭应用 public MainForm() { InitializeComponent(); } // 提升关机权限 private bool EnableShutdownPrivilege() { if (!OpenProcessToken(System.Diagnostics.Process.GetCurrentProcess().Handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out IntPtr tokenHandle)) return false; TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES(); tp.PrivilegeCount = 1; tp.Attributes = SE_PRIVILEGE_ENABLED; if (!LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid)) return false; bool result = AdjustTokenPrivileges(tokenHandle, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); Marshal.Close(tokenHandle); return result; } // 注销当前会话 private void LogoffSystem() { if (EnableShutdownPrivilege()) { ExitWindowsEx(EWX_LOGOFF | EWX_FORCE, 0); } else { MessageBox.Show("无法获取注销权限,请以管理员身份运行程序"); } } // 关闭计算机 private void ShutdownSystem() { if (EnableShutdownPrivilege()) { // 第二个参数是关机提示消息,null则不显示;第三个参数是超时时间(毫秒),0表示立即关机 InitiateSystemShutdownEx(null, "应用程序将关闭计算机", 0, true, false, 0); } else { MessageBox.Show("无法获取关机权限,请以管理员身份运行程序"); } } // 注销按钮点击事件 private void btnLogoff_Click(object sender, EventArgs e) { LogoffSystem(); } // 关机按钮点击事件 private void btnShutdown_Click(object sender, EventArgs e) { ShutdownSystem(); } } }
注意事项
- 程序需要以管理员身份运行,否则会因权限不足导致操作失败。可以在项目属性的“安全性”选项卡中设置为完全信任应用,或者手动右键以管理员身份启动。
EWX_FORCE参数会强制关闭所有未响应的应用,避免因程序未退出而阻止关机/注销操作。- 可以根据需求调整
InitiateSystemShutdownEx的参数,比如设置关机提示消息和超时时间。
内容的提问来源于stack exchange,提问作者Yaya0306
相关产品推荐
相关产品推荐

