Windows XP下关机方法整理

记得暑假的时候偶无聊写了一个MyClock的小恶作剧软件,当时用到了关机.其实之前我一直以为关机嘛,不就是ExitWindowEx就可以了嘛,其实事情没那么简单,XP下的关机需要一个提升权限(Privilege)的过程.我简单整理了一下,WindowsXP下关机至少有下面几种方法:
一: 最简单的方法是
shutdown -s -t 0
关于shutdown的具体用法如下:
用法: shutdown [-i | -l | -s | -r | -a] [-f] [-m /computername] [-t xx] [-c "comment"] [-d up:xx:yy]
没有参数     显示此消息(与 ? 相同)
-i               显示 GUI 界面,必须是第一个选项
-l               注销(不能与选项 -m 一起使用)
-s               关闭此计算机
-r               关闭并重启动此计算机
-a               放弃系统关机
-m /computername     远程计算机关机/重启动/放弃
-t xx             设置关闭的超时为 xx 秒
-c "comment"         关闭注释(最大 127 个字符)
-f               强制运行的应用程序关闭而没有警告
-d [p]:xx:yy       关闭原因代码
            u 是用户代码
            p 是一个计划的关闭代码
            xx 是一个主要原因代码(小于 256 的正整数)
            yy 是一个次要原因代码(小于 65536 的正整数)
-f:强行关闭应用程序
-m /计算机名:控制远程计算机
-i:显示图形用户界面,但必须是Shutdown的第一个选项
-l:注销当前用户
-r:关机并重启
-t时间:设置关机倒计时
-c "消息内容":输入关机对话框中的消息内容(不能超127个字符

(关于如何在程序中去调用我想大家已经清楚了,C/C++中可以使用system,C#里面的可以参加我写rundll32的问题)
方法二: 利用ExitWindowEx
这个在XP下需要有一个提升权限的过程, 我用C#写了一下:

[StructLayout(LayoutKind.Sequential, Pack  =   1 )]
        
internal   struct  TokPriv1Luid
        
{
            
public int Count;
            
public long Luid;
            
public int Attr;
        }


        [DllImport(
" kernel32.dll " , ExactSpelling  =   true )]
        
internal   static   extern  IntPtr GetCurrentProcess();

        [DllImport(
" advapi32.dll " , ExactSpelling  =   true , SetLastError  =   true )]
        
internal   static   extern   bool  OpenProcessToken(IntPtr h,  int  acc,  ref  IntPtr phtok);

        [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  TokPriv1Luid newst,  int  len, IntPtr prev, IntPtr relen);

        [DllImport(
" user32.dll " , ExactSpelling  =   true , SetLastError  =   true )]
        
internal   static   extern   bool  ExitWindowsEx( int  flg,  int  rea);

        
internal   const   int  SE_PRIVILEGE_ENABLED  =   0x00000002 ;
        
internal   const   int  TOKEN_QUERY  =   0x00000008 ;
        
internal   const   int  TOKEN_ADJUST_PRIVILEGES  =   0x00000020 ;
        
internal   const   string  SE_SHUTDOWN_NAME  =   " SeShutdownPrivilege " ;
        
internal   const   int  EWX_LOGOFF  =   0x00000000 ;
        
internal   const   int  EWX_SHUTDOWN  =   0x00000001 ;
        
internal   const   int  EWX_REBOOT  =   0x00000002 ;
        
internal   const   int  EWX_FORCE  =   0x00000004 ;
        
internal   const   int  EWX_POWEROFF  =   0x00000008 ;
        
internal   const   int  EWX_FORCEIFHUNG  =   0x00000010 ;

调用如下:

             bool  ok;
            TokPriv1Luid tp;
            IntPtr hproc 
=  GetCurrentProcess();
            IntPtr htok 
=  IntPtr.Zero;
            ok 
=  OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES  |  TOKEN_QUERY,  ref  htok);
            tp.Count 
=   1 ;
            tp.Luid 
=   0 ;
            tp.Attr 
=  SE_PRIVILEGE_ENABLED;
            ok 
=  LookupPrivilegeValue( null , SE_SHUTDOWN_NAME,  ref  tp.Luid);
            ok 
=  AdjustTokenPrivileges(htok,  false ref  tp,  0 , IntPtr.Zero, IntPtr.Zero);
            ok 
=  ExitWindowsEx(EWX_POWEROFF, EWX_FORCE);

 

方法三: 使用InitiateSystemShutdown
和ExitWindowEx一样, 它也需要提升权限
只需将

ok  =  ExitWindowsEx(EWX_POWEROFF, EWX_FORCE);


一句替换成

ok  =  InitiateSystemShutdown( null null 0 false false );


别忘了加上声明:

 [DllImport( " Advapi32.dll " )]
        
internal   static    extern   bool  InitiateSystemShutdown(   string  lpMachineName,   string  lpMessage,   ulong  dwTimeout,   bool  bForceAppsClosed,   bool  bRebootAfterShutdown);

方法四: 这个方法是最有趣的了,利用ntdll.dll里面未公开的原生API进行2s关机,无须提升权限就可以了.
网上有人用IDA进行分析的文章, 有兴趣可以找找,反正我是看不懂了,- -#
好了, 这里有个小插曲,就是在C#中调用这个Native API,可能水平还是不够, 在调用过程老是出错.没办法,
想了一个阴招, 用VC编写dll, C#去调用, 呵呵, 最终结果不错哟!
下面先建立一个Win32 DLL Project 项目,然后把下面的函数拷贝到cpp当中编译,OK,dll就出来了

#include  < windows.h >

extern   " C "  __declspec(dllexport)  void  ShutdownWindow1( void )
{
 
const int SE_SHUTDOWN_PRIVILEGE  =           0x13;
 typedef 
int (*RtlAdjustPrivilege)(int,boolbool,int*);
 typedef 
int (*ZwShutdownSystem)(int);
 
int en = 0;
 HMODULE module 
= LoadLibrary("ntdll.dll");
 RtlAdjustPrivilege rtl 
= (RtlAdjustPrivilege)GetProcAddress(module, "RtlAdjustPrivilege");
 ZwShutdownSystem shutdown 
= (ZwShutdownSystem)GetProcAddress(module,"ZwShutdownSystem");
    
int nRet=rtl(SE_SHUTDOWN_PRIVILEGE,TRUE,TRUE,&en);
    
if(nRet==0x0C000007C)
        nRet 
= rtl(SE_SHUTDOWN_PRIVILEGE,TRUE,FALSE,&en);    
    nRet
=shutdown(2);
}


然后把dll拷贝到C#工程的Release/Debug的文件目录下, 加上下面的话就OK了, 2s关机, So Cool!

[DllImport( " ShutdownDll.dll " ,CallingConvention = CallingConvention.Cdecl)]
        
public   static   extern   void  ShutdownWindow();

 

调用 ShutdownWindow();

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值