ExitWindowsEx VB声明 Declare Function ExitWindowsEx Lib "user32" Alias "ExitWindowsEx" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long 说明 退出windows,并用特定的选项重新启动 返回值 Long,非零表示成功,零表示失败。会设置GetLastError 参数表 参数 类型及说明 uFlags Long,指定下述一个或多个标志(用OR运算符合并到一起) EWX_FORCE 强迫中止没有响应的进程 EWX_LOGOFF 中止进程,然后注销 EWX_SHUTDOWN 关掉系统电源(如果可能的话,ATX电源就可以) EWX_REBOOT 重新引导系统 EWX_SHUTDOWN 关闭系统 dwReserved Long,保留,设为零 注解 这个函数调用后会立刻返回,系统关闭过程是在后台进行的。注意先中止自己的应用程序,使关闭过程更显平顺。当然,您的进程必须有足够的优先权,否则也不能执行这种操作
以下文章中演示了在Windows NT 4.0/Windows 2000上调用ExitWindowsEx API的方法,并且包含了如何获得SE_SHUTDOWN_NAME权限的方法,您可以参考: PRB: ExitWindowsEx API Does Not Reboot Windows NT http://support.microsoft.com/directory/article.asp?ID=KB;EN-US;Q176695 在WindowsNT/2000/XP中,您无法直接通过ExitWindowsEx关闭计算机,而必须先调用AdjustTokenPrivileges 函数使得SE_SHUTDOWN_NAME的privilege为有效,请参考以下文章,他说明了如何关闭Windows NT/2000/XP:
PRB: ExitWindowsEx API Does Not Reboot Windows NT (Q176695) http://support.microsoft.com/default.aspx?scid=kb;en-us;Q176695
问题一,可能是你的声明有问题,uint类型不等于c# long类型,你试试如下的声明: [ DllImport("user32") ] public static extern long ExitWindowsEx(uint uFlags, long dwReserved ) ;
[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; private System.Windows.Forms.Button button1; internal const int EWX_FORCEIFHUNG = 0x00000010; private void DoExitWin( int flg ) { 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( flg, 0 ); } 然后调用 DoExitWin 就可以了 问题解决 谢谢大家
Declare Function ExitWindowsEx Lib "user32" Alias "ExitWindowsEx" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long
说明
退出windows,并用特定的选项重新启动
返回值
Long,非零表示成功,零表示失败。会设置GetLastError
参数表
参数 类型及说明
uFlags Long,指定下述一个或多个标志(用OR运算符合并到一起)
EWX_FORCE 强迫中止没有响应的进程
EWX_LOGOFF 中止进程,然后注销
EWX_SHUTDOWN 关掉系统电源(如果可能的话,ATX电源就可以)
EWX_REBOOT 重新引导系统
EWX_SHUTDOWN 关闭系统
dwReserved Long,保留,设为零
注解
这个函数调用后会立刻返回,系统关闭过程是在后台进行的。注意先中止自己的应用程序,使关闭过程更显平顺。当然,您的进程必须有足够的优先权,否则也不能执行这种操作
http://support.microsoft.com/directory/article.asp?ID=KB;EN-US;Q176695 在WindowsNT/2000/XP中,您无法直接通过ExitWindowsEx关闭计算机,而必须先调用AdjustTokenPrivileges 函数使得SE_SHUTDOWN_NAME的privilege为有效,请参考以下文章,他说明了如何关闭Windows NT/2000/XP:
PRB: ExitWindowsEx API Does Not Reboot Windows NT (Q176695)
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q176695
[ DllImport("user32") ]
public static extern long ExitWindowsEx(uint uFlags, long dwReserved ) ;
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;
private System.Windows.Forms.Button button1;
internal const int EWX_FORCEIFHUNG = 0x00000010; private void DoExitWin( int flg )
{
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( flg, 0 );
}
然后调用 DoExitWin 就可以了
问题解决
谢谢大家