Russian Qt Forum
Май 01, 2024, 17:07 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Системные команды Windows  (Прочитано 2923 раз)
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« : Апрель 26, 2014, 20:08 »

Делаю планировщик, подумал скинуть часть его функциональности Улыбающийся
Пока искал как делать выключение, перезагрузку, переход в спящий режим и прочее, прочее, уйму времени потратил, не говоря уже о разбирательстве в примерах и документациях, да и, вообще, я велосипедизм не признаю Улыбающийся

Вот что сделал:
Код:
#ifndef WINSYSTEMCOMMAND_H
#define WINSYSTEMCOMMAND_H

#include <QString>

namespace WinSystemCommand
{
    enum Command
    {
        Force,         // Выключает питание компьютера(компьютер должен поддерживать данную функцию).
        PowerOff,      // Перезагружает систему.
        Reboot,        // Форсировать выключение компьютера. Если задан этот флаг, то Windows не посылает сообщения WM_QUERYENDSESSION и WM_ENDSESSION выполняющимся приложениям. Следовательно, эти приложения не смогут сделать запросов пользователю о сохранении данных и могут потерять последние изменения документов, с которыми они работали. Так что использовать этот флаг надо очень осторожно, только в каких-то аварийных ситуациях.
        Shutdown,      // Завершает работу компьютера до того места, где он может быть безопасно выключен: сброшенны все файловые буферы на диск, завершает работу всех процессов.
        LogOff,        // Завершает сессию текущего пользователя.
        Hibernate,     // Спящий режим.
        Suspend,       // Ждущий режим.
        ScreenOff      // Выключение дисплея.
    };

    bool execute( Command command );
    QString getTextError( Command command );
}

#endif // WINSYSTEMCOMMAND_H

Код:
#include "winsystemcommand.h"
#include <windows.h>
#include <QObject>

namespace WinSystemCommand
{
    // Функция для выполнение команд, требущий определенных привилегий
    bool systemControl( Command command )
    {
        HANDLE hToken; // указатель на идентификатор процесса
        TOKEN_PRIVILEGES tkp; // указатель на идентифицирующую структуру
        // получение идентификатора текущего процесса, для получения прав на отключение
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
            return FALSE;

        // Полчение LUID
        LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
        tkp.PrivilegeCount = 1; // установка одной привилегии
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

        //Установка привилегии отключения для этого процесса.
        AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);

        // Если ошибка то выход.
        if (GetLastError() != ERROR_SUCCESS)
            return FALSE;

        bool successful = false;

        // Ниже используются функции, требующие определенных привилегий
        switch ( command )
        {
        case PowerOff:
            successful = ExitWindowsEx( EWX_POWEROFF, 0 ); // выключение питания компьютера
            break;

        case Reboot:
            successful = ExitWindowsEx( EWX_REBOOT, 0 ); // перезагрузка
            break;

        case Shutdown:
            successful = ExitWindowsEx( EWX_SHUTDOWN, 0 ); // завершение сеанса
            break;

        case Hibernate:
            successful = SetSystemPowerState( FALSE, FALSE ); // cпящий режим
            break;

        case Suspend:
            successful = SetSystemPowerState( TRUE, FALSE ); // ждущий режим
            break;
        }

        // Отменить привилегии отключения.
        tkp.Privileges[0].Attributes = 0;
        AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);

        return successful;
    }

    bool execute( Command command )
    {
        bool successful = true;

        switch ( command )
        {
        case Force:
            successful = ExitWindowsEx( EWX_FORCE, 0 );
            break;

        case PowerOff:
        case Reboot:
        case Shutdown:
        case Hibernate:
        case Suspend:
            successful = systemControl( command );
            break;

        case LogOff:
            successful = ExitWindowsEx( EWX_LOGOFF, 0 );
            break;

        case ScreenOff:
            SendMessageW( HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2 );
            successful = true;
            break;
        }

        return successful;
    }

    QString getTextError( Command command )
    {
        QString message;

        switch ( command )
        {
        case Force:
            message = QObject::tr( "Unable to turn off the computer" ); // Не удалось выключить питание компьютера
            break;

        case PowerOff:
            message = QObject::tr( "Unable to turn off your computer" ); // Не удалось выключить компьютер
            break;

        case Reboot:
            message = QObject::tr( "Unable to restart the computer" ); // Не удалось перезагрузить компьютер
            break;

        case Shutdown:
            message = QObject::tr( "Failed to complete the session" ); // Не удалось завершить сеанс
            break;

        case Hibernate:
            message = QObject::tr( "Unable to go to sleep" ); // Не удалось перейти в режим сна
            break;

        case Suspend:
            message = QObject::tr( "Unable to switch to standby" ); // Не удалось перейти в режим ожидания
            break;

        case LogOff:
            message = QObject::tr( "Failed to change the user" ); // Не удалось сменить пользователя
            break;
        }

        return message;
    }
}

Вот хотим мы отключить экран (включится снова, если подвигать мышкой или что то на клаве нажать), то:
Код:
WinSystemCommand::Command command = WinSystemCommand::ScreenOff;
bool successful = WinSystemCommand::execute( command  );
if ( !successful )
{
     const QString & message = WinSystemCommand::getTextError( command );
     QMessageBox::warning( this, tr( "Warning" ), message );
}

Код пространства WinSystemCommand, конечно, не идеален, есть, на мой взгляд, в нем огрехи, но работает Улыбающийся

Исходный код планировщика на гите, кому будет интересно здесь

[https://github.com/gil9red/SystemControl]Или эт
« Последнее редактирование: Май 14, 2014, 17:49 от gil9red » Записан

Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.045 секунд. Запросов: 22.