Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > Общие вопросы .NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.04.2009, 05:25   #1
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию Перезагрузка/выключение/блокирование машины на C#

Очень часто звучит вопрос: как программно перезагрузить компьютер, как выключить и т.п.. Иногда такой вопрос начинает мучать и C# программистов
Единственный путь тут - использование WinAPI.
Я написал простой и удобный, как мне кажется, класс для выполнения всех вышеописанных действий.
Решил поделится, дабы никто из обитателей этой ветки не изобретал велосипеда, перерывая гугл

Код:
using System.Runtime.InteropServices;

    class reboot
    {
        //импортируем API функцию InitiateSystemShutdown
        [DllImport("advapi32.dll", EntryPoint = "InitiateSystemShutdownEx")]
        static extern int InitiateSystemShutdown(string lpMachineName, string lpMessage, int dwTimeout, bool bForceAppsClosed, bool bRebootAfterShutdown);
        //импортируем API функцию AdjustTokenPrivileges
        [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);
        //импортируем API функцию GetCurrentProcess
        [DllImport("kernel32.dll", ExactSpelling = true)]
        internal static extern IntPtr GetCurrentProcess();
        //импортируем API функцию OpenProcessToken
        [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
        internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
        //импортируем API функцию LookupPrivilegeValue
        [DllImport("advapi32.dll", SetLastError = true)]
        internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
        //импортируем API функцию LockWorkStation
        [DllImport("user32.dll", EntryPoint = "LockWorkStation")]
        static extern bool LockWorkStation();
        //объявляем структуру TokPriv1Luid для работы с привилегиями
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct TokPriv1Luid
        {
            public int Count;
            public long Luid;
            public int Attr;
        }
        //объявляем необходимые, для API функций, константые значения, согласно MSDN
        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";
        //функция SetPriv для повышения привилегий процесса
        private void SetPriv()
        {
            TokPriv1Luid tkp; //экземпляр структуры TokPriv1Luid 
            IntPtr htok = IntPtr.Zero;
            //открываем "интерфейс" доступа для своего процесса
            if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok))
            {
                //заполняем поля структуры
                tkp.Count = 1;
                tkp.Attr = SE_PRIVILEGE_ENABLED;
                tkp.Luid = 0;
                //получаем системный идентификатор необходимой нам привилегии
                LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tkp.Luid);
                //повышем привилигеию своему процессу
                AdjustTokenPrivileges(htok, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero);
            }
        }
        //публичный метод для перезагрузки/выключения машины
        public int halt(bool RSh, bool Force)
        {
            SetPriv(); //получаем привилегия
            //вызываем функцию InitiateSystemShutdown, передавая ей необходимые параметры
            return InitiateSystemShutdown(null, null, 0, Force, RSh);           
        }
        //публичный метод для блокировки операционной системы
        public int Lock()
        {
            if (LockWorkStation())
                return 1;
            else
                return 0;
        }
Собственно класс имеет два метода:
Lock() - вызов этого метода приведет к блокированию ос (но не выходу из системы!)
halt(bool RSh, bool Force) - вызов этого метода приводит к перезагрузке/выключению, вот возможные режимы:

Код:
halt(true, false) //мягкая перезагрузка
halt(true, true) //жесткая перезагрузка
halt(false, false) //мягкое выключение
halt(false, true) //жесткое выключение
Надеюсь мой класс будет кому то полезен
oleg kutkov вне форума Ответить с цитированием
Старый 01.08.2009, 00:12   #2
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Просьба к модерам, а нельзя бы это закрепить, что бы не терялось ?
oleg kutkov вне форума Ответить с цитированием
Старый 01.08.2009, 00:48   #3
MaTBeu
Eclipse Foundation
Старожил
 
Аватар для MaTBeu
 
Регистрация: 19.09.2007
Сообщений: 2,619
По умолчанию

Прикрепил.
MaTBeu вне форума Ответить с цитированием
Старый 01.08.2009, 01:37   #4
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Спасибо
oleg kutkov вне форума Ответить с цитированием
Старый 10.08.2009, 14:31   #5
Arhe
Пользователь
 
Регистрация: 21.02.2008
Сообщений: 28
По умолчанию

Очень интересно. А можешь объяснить подробно, как работает и зачем эта функция?

Код:
    //функция SetPriv для повышения привилегий процесса
        private void SetPriv()
        {
            TokPriv1Luid tkp; //экземпляр структуры TokPriv1Luid 
            IntPtr htok = IntPtr.Zero;
            //открываем "интерфейс" доступа для своего процесса
            if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok))
            {
                //заполняем поля структуры
                tkp.Count = 1;
                tkp.Attr = SE_PRIVILEGE_ENABLED;
                tkp.Luid = 0;
                //получаем системный идентификатор необходимой нам привилегии
                LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tkp.Luid);
                //повышем привилигеию своему процессу
                AdjustTokenPrivileges(htok, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero);
            }
        }
Я прописывал ребут просто, импортировал dll и вызвал функцию.
Код:
 private void button3_Click(object sender, EventArgs e)
        {
            InitiateSystemShutdownEx("127.0.0.1", "Reboot", 5, true, true, 1);           
        }
Код:
[DllImport("advapi32.dll", EntryPoint = "InitiateSystemShutdownEx")]
        public static extern int InitiateSystemShutdownEx(string lpMachineName, string lpMessage, int dwTimeout, bool bForceAppsClosed, bool bRebootAfterShutdown, int dwReason);
Arhe вне форума Ответить с цитированием
Старый 10.08.2009, 15:03   #6
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Цитата:
Сообщение от Arhe Посмотреть сообщение
Очень интересно. А можешь объяснить подробно, как работает и зачем эта функция?

Код:
    //функция SetPriv для повышения привилегий процесса
        private void SetPriv()
        {
            TokPriv1Luid tkp; //экземпляр структуры TokPriv1Luid 
            IntPtr htok = IntPtr.Zero;
            //открываем "интерфейс" доступа для своего процесса
            if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok))
            {
                //заполняем поля структуры
                tkp.Count = 1;
                tkp.Attr = SE_PRIVILEGE_ENABLED;
                tkp.Luid = 0;
                //получаем системный идентификатор необходимой нам привилегии
                LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tkp.Luid);
                //повышем привилигеию своему процессу
                AdjustTokenPrivileges(htok, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero);
            }
        }
Функция SetPriv() нужна для повышения системных привилегий процесса. Это обеспечивает гарантированное выполнение команды выключения\перезагрузки. Без повышения привилегий, просто может ничего не происходить.
Функция работает следующим образом.
Для управления конкретными привилегиями в WinAPI существует специальная структура TokPriv1Luid. Заполняя ее поля так
Код:
tkp.Count = 1;
 tkp.Attr = SE_PRIVILEGE_ENABLED;
tkp.Luid = 0;
Мы указываем на необходимость ВКЛЮЧЕНИЯ привелегии. Какой именно, в данном случае не указывается.
Но перед тем как управлять привилегиями процесса, необходимо получить особый указатель на процесс - IntPtr.
В данной строчке мы получаем указатель на наш процесс:
Код:
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok)
Привилегии в системе могут быть самые разнообразные, на нужна одна - позволяющая производить перезагрузку/выключение, ее имя - SeShutdownPrivilege (подробнее о всех привилегиях можно почитать в MSDN). Для того, что бы получить возможность работать с этой привилегией - нужно получить ее идентификатор:
Код:
LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tkp.Luid);
Ну и на конец, когда мы заполнили структуру "выключателя", получили идентификатор привилегии - применям все это к уже известному идентификатору процесса:
Код:
AdjustTokenPrivileges(htok, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero);
oleg kutkov вне форума Ответить с цитированием
Старый 10.08.2009, 15:07   #7
Arhe
Пользователь
 
Регистрация: 21.02.2008
Сообщений: 28
По умолчанию

Большое Спасибо!
Arhe вне форума Ответить с цитированием
Старый 23.12.2009, 20:56   #8
poroshochek
 
Регистрация: 23.12.2009
Сообщений: 8
По умолчанию

Цитата:
tkp.Count = 1;
tkp.Attr = SE_PRIVILEGE_ENABLED;
tkp.Luid = 0;
а почему 0 и 1??
poroshochek вне форума Ответить с цитированием
Старый 15.04.2010, 09:51   #9
Aexx
Программист тьмы
Форумчанин
 
Аватар для Aexx
 
Регистрация: 02.09.2009
Сообщений: 227
По умолчанию

А как насчет WMI?
Класс Win32_OperatingSystem, методы Reboot(), Shutdown(), Win32Shutdown(Flags)
Aexx вне форума Ответить с цитированием
Старый 27.04.2010, 23:17   #10
(IICuX)
Пользователь
 
Регистрация: 27.04.2010
Сообщений: 22
По умолчанию

а чем cmd не устраивает?
(IICuX) вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Блокирование ALT+F4 Killbrum Win Api 5 14.03.2009 12:23
Выключение и перезагрузка Патрон Win Api 8 26.03.2008 16:24
Выключение/Перезагрузка в Vista Veiron Общие вопросы Delphi 5 13.01.2008 09:35
блокирование функции Fireleo Win Api 5 29.07.2007 17:04
выключение, перезагрузка компьютера ATL Win Api 4 16.05.2007 01:57