http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 4371|回复: 1

[C#语言基础] C# 重启计算机的问题

[复制链接]
发表于 2012-10-15 14:31:34 | 显示全部楼层 |阅读模式
C# 程序重启计算机的方法很多,网上也有不少这方面的文章,不过很多网上提供的方法在某些情况下无法获取重启计算机的权限导致重启失败。本文对这些方法做一些简单的讨论。
作者:eaglet
  网上介绍最多的两种方法分别是:
[C#] 纯文本查看 复制代码
System.Diagnostics.Process.Start("shutdown",@"/r");
和

    [DllImport("user32.dll")]
        static extern bool ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason);

        [STAThread]
        static void Main(string[] args)
        {
            ExitWindowsEx(ExitWindows.LogOff, ShutdownReason.MajorOther & ShutdownReason.MinorOther);
            //这个语句将实现计算机注销操作   
         }

这两种方法在通常情况下工作是没有问题的,但在某些特殊情况下,比如桌面被其它用户锁定时就无法重启计算机。本人在实际工作中遇到过当当前屏幕被远程控制软件锁定后,我做的后台守护进程试图重启计算机,结果用上述两种方法都无法成功。分析原因,应该是远程控制软件用另外的帐号锁定了屏幕(通常应该是windows service 或者 network service),这时守护进程用当前帐号重启计算机就因为没有权限而失败。
要解决这个问题,我们必须要给进程赋予足够的权限才行,于是我在调用 ExitWindowsEx 前运行了如下代码来赋予当前进程关闭计算机权限
[C#] 纯文本查看 复制代码
//give current process SeShutdownPrivilege

        TokPriv1Luid tp;
        IntPtr hproc = GetCurrentProcess();

        IntPtr htok = IntPtr.Zero;

        if (!OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok))
        {
            throw new Exception("Open Process Token fail");
        }

        tp.Count = 1;

        tp.Luid = 0;

        tp.Attr = SE_PRIVILEGE_ENABLED;

        if (!LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid))
        {
            throw new Exception("Lookup Privilege Value fail");
        }

        if (!AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero))
        {
            throw new Exception("Adjust Token Privileges fail");
        }

上面代码为当前进程赋予了关闭计算机的权限。这里需要注意的是上述代码要执行成功同样需要足够的权限,通常当前进程需要以拥有至少是系统管理员权限的账户运行。如果没有足够权限,需要用程序模拟系统管理员权限,模拟其它帐号权限的问题不在本文讨论范围内。
加上如上代码后,在其他用户锁定机器后,重启计算机成功。
下面给出完整代码
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;

namespace Apicomputer
{
    public class ExitWindows
    {
        #region win32 api
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        private struct TokPriv1Luid
        {
            public int Count;
            public long Luid;
            public int Attr;
        }

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

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

        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

        [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
            ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

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

        #endregion
        private const int SE_PRIVILEGE_ENABLED = 0x00000002;
        private const int TOKEN_QUERY = 0x00000008;
        private const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
        private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
        #region Exit Windows Flags
        private const int EWX_LOGOFF = 0x00000000;
        private const int EWX_SHUTDOWN = 0x00000001;
        private const int EWX_REBOOT = 0x00000002;
        private const int EWX_FORCE = 0x00000004;
        private const int EWX_POWEROFF = 0x00000008;
        private const int EWX_FORCEIFHUNG = 0x00000010;
        #endregion

        public static void DoExitWin(int flg)
        {
            //give current process SeShutdownPrivilege

            TokPriv1Luid tp;
            IntPtr hproc = GetCurrentProcess();
            IntPtr htok = IntPtr.Zero;
            if (!OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok))
            {
                throw new Exception("Open Process Token fail");
            }
            tp.Count = 1;
            tp.Luid = 0;
            tp.Attr = SE_PRIVILEGE_ENABLED;
            if (!LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid))
            {
                throw new Exception("Lookup Privilege Value fail");
            }
            if (!AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero))
            {
                throw new Exception("Adjust Token Privileges fail");
            }
            //Exit windows
            if (!ExitWindowsEx(flg, 0))
            {
                throw new Exception("Exit Windows fail");
            }
        }
        /// <summary>
        /// Reboot computer
        /// </summary>
        /// <param name="force">force reboot</param>
        public static void Reboot(bool force)
        {
            if (force)
            {
                DoExitWin(EWX_REBOOT | EWX_FORCE);
            }
            else
            {
                DoExitWin(EWX_REBOOT | EWX_FORCEIFHUNG);
            }
        }

        /// <summary>
        /// Reboot computer force if hung
        /// </summary>
        public static void Reboot()
        {
            Reboot(false);
        }

        /// <summary>
        /// Shut down computer
        /// </summary>
        /// <param name="force">force shut down</param>
        public static void Shutdown(bool force)
        {
            if (force)
            {
                DoExitWin(EWX_SHUTDOWN | EWX_FORCE);
            }
            else
            {
                DoExitWin(EWX_SHUTDOWN | EWX_FORCEIFHUNG);
            }
        }

        /// <summary>
        /// Shut down computer force if hung
        /// </summary>
        public static void Shutdown()
        {
            Shutdown(false);
        }

        /// <summary>
        /// Log off
        /// </summary>
        /// <param name="force">force logoff</param>
        public static void Logoff(bool force)
        {
            if (force)
            {
                DoExitWin(EWX_LOGOFF | EWX_FORCE);
            }
            else
            {
                DoExitWin(EWX_LOGOFF | EWX_FORCEIFHUNG);
            }
        }

        /// <summary>
        /// logoff computer force if hung
        /// </summary>
        public static void Logoff()
        {
            Logoff(false);
        }
    }
}

使用方法
[C#] 纯文本查看 复制代码
//重新启动电脑
        private void button1_Click(object sender, EventArgs e)
        {
            ExitWindows.Reboot();
        }


1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
发表于 2014-7-28 15:31:10 | 显示全部楼层
强烈支持楼主ing……
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-11-15 20:51

© 2014-2021

快速回复 返回顶部 返回列表