Делаю планировщик, подумал скинуть часть его функциональности :)
Пока искал как делать выключение, перезагрузку, переход в спящий режим и прочее, прочее, уйму времени потратил, не говоря уже о разбирательстве в примерах и документациях, да и, вообще, я велосипедизм не признаю :)
Вот что сделал:
#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/Scheduler)
[https://github.com/gil9red/SystemControl]Или это[/url]