本文和大家分享一下使用C#编写实现关机的方法。一般关机用Shutdown便已足够,在xp下运行中输入shutdown -f -s -t 0便是0秒关机。在windows 7下则也可以输入shutdown -s -p 在C#中
ProcessStartInfo shutdown = new ProcessStartInfo(); shutdown.FileName = "shutdown.exe"; shutdown.Arguments = "-f -s -t 0"; Process.Start(shutdown);
但是这都是调用系统的关机程序来关机,那我们的进程可不可以自己关机呢?答案是肯定的。 系统关机需要若干步骤,前几步大概都是退出进程,退出用户之类的系统操作,和关机这个主题关系不大。不执行顶多损失未保存数据,但是有的时候关机本身比较重要,需要优先执行,那么就要提到windows的关闭系统的函数NtShutdownSystem(); 要让自己的进程执行关机操作,首先要让自己的进程有关机的权限,系统的权限种类在MSDN的Privilege Constants中有详细叙述,具体定义在windows sdk的winNT.h文件中7806行的位置。 关机所需的权限是SeShutdownPrivilege,我们在C++中可以这样获得 if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) { TOKEN_PRIVILEGES tkp; LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0); CloseHandle(hToken); } 在也可以使用API来改变权限,这个例子用C#来写 [DllImport("ntdll.dll")] private static extern void RtlAdjustPrivilege(int Privilege, bool Enable, bool Thread, out bool OldValue);其中Privilege是权限的枚举值,Enable是表示开启还是关闭, Thread表示是改变当前线程权限还是改变整个进程权限,最后一个输出是原来此权限的值。 SeShutdownPrivilege的枚举值是19,那么执行如下代码就可以让此线程获得关机的能力 bool a;RtlAdjustPrivilege(19, true, false, out a); 关闭系统的话调用NtShutdownSystem即可,此函数不载于MSDN中,其描述可见MSDN未载之API,摘录如下 NTSYSAPI NTSTATUSNTAPINtShutdownSystem( IN SHUTDOWN_ACTION Action ); 其中Shutdown_action是一个枚举 其枚举类型为 enum SHUTDOWN_ACTION { ShutdownNoReboot, ShutdownReboot, ShutdownPowerOff} 相应的,调用此API的C++代码为
代码 DWORD (__stdcall *NtShutdownSystem)(SHUTDOWN_ACTION); HMODULE hMod; hMod = LoadLibraryA("ntdll.dll"); if(hMod) { NtShutdownSystem = (DWORD(__stdcall *)(SHUTDOWN_ACTION))GetProcAddress(hMod, "NtShutdownSystem"); NtShutdownSystem(ShutdownNoReboot); } C#代码为 [DllImport("NTDLL.dll")] public static extern int NtShutdownSystem(SHUTDOWN_ACTION action);NtShutdownSystem(SHUTDOWN_ACTION.ShutdownNoReboot);NtShutdownSystem其实算比较正常的关机,毕竟还是执行了关闭硬盘,清空页面文件和缓冲区等操作,WINNT还提供一个API,可以使我们设置电源状态,这个API就是NtSetSystemPowerState NtSetSystemPowerState这个API不载于MSDN也不载于NTInternal,但是网上仍然能找到这个API的描述,这个API是这样的 NTSYSAPINTSTATUSNTAPINtSetSystemPowerState(IN POWER_ACTION SystemAction,IN SYSTEM_POWER_STATE MinSystemState,IN ULONG Flags); 其中POWER_ACTION表示关机动作,SYSTEM_POWER_STATE表示系统电源状态,Flags则表示系统关机原因。这三者在MSDN中都有详细记载,Flags的值则在Windows SDK的Reason.h中定义。 他们的值是这样的 代码 enum SYSTEM_POWER_STATE { PowerSystemUnspecified = 0, PowerSystemWorking = 1, PowerSystemSleeping1 = 2, PowerSystemSleeping2 = 3, PowerSystemSleeping3 = 4, PowerSystemHibernate = 5, PowerSystemShutdown = 6, PowerSystemMaximum = 7 } enum POWER_ACTION { PowerActionNone = 0, PowerActionReserved, PowerActionSleep, PowerActionHibernate, PowerActionShutdown, PowerActionShutdownReset, PowerActionShutdownOff, PowerActionWarmEject } 在C#中调用NtSetSystemPowerState来关机的代码如下 代码 [DllImport("NTDLL.dll")] public static extern int NtSetSystemPowerState(POWER_ACTION action, SYSTEM_POWER_STATE status, uint flag);... NtSetSystemPowerState(POWER_ACTION.PowerActionShutdownOff, SYSTEM_POWER_STATE.PowerSystemShutdown, 0x80000000); 如此便可以实现快速的关机了。但是除此之外,我想windows的关机方法还有很多,应该有更加便捷的关机方法,来为日常应用提供方便。文本中提到的关机方法,在Windows7和XP下测试通过,在2000以上的系统中,应该都可以起作用。
|