Завершение работы Windows, перезагрузка, выход пользователя из системы
Использование функций WinAPI позволяет добавлять в свои приложения даже такую функциональность, как завершение работы системы и ее перезагрузка. Создайте новое Windows- приложение и назовите его StartTurnOff. Добавляем на форму пять кнопок и устанавливаем следующие значения формы и кнопок:
BackgroundImage | Code\Glava5\StartTurnOff\Image\Window.bmp |
FormBorderStyle | None |
Size | 314; 400 |
StartPosition | CenterScreen |
Name | BtnCancel |
Location | 243; 169 |
Size | 61; 19 |
Text | Отмена |
Name | btnCancel2 |
Location | 245; 369 |
Size | 61; 19 |
Text | Отмена |
Name | BtnTurnOff |
Image | Code\Glava5\StartTurnOff\Image\TurnOff.bmp |
Location | 140; 80 |
Size | 34; 34 |
Text |
Name | BtnRestart |
Image | Code\Glava5\StartTurnOff\Image\Restart.bmp |
Location | 238; 81 |
Size | 34; 34 |
Text |
Name | BtnUserOut |
Image | Code\Glava5\StartTurnOff\Image\UserOut.bmp |
Location | 198; 280 |
Size | 34; 34 |
Text |
Добавляем класс WinAPIClass:
Листинг 5.8.
(html, txt)
В коде формы добавляем обработчики кнопок:
Листинг 5.9.
(html, txt)
При запуске приложения появляется совмещенное окно завершения работы и смены пользователя (рис. 5.6). Кнопки "Выключение", "Перезагрузка" и "Выход" лучше всего проверять, завершив работу со средой Visual Studio .NET.
Рис. 5.6. Приложение StartTurnOff
На диске, прилагаемом к книге, вы найдете приложение StartTurnOff (Code\Glava5\StartTurnOff).
#endregion // Дополнительные переменные public const int SE_PRIVILEGE_ENABLED = 2; public const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; public const int ANYSIZE_ARRAY = 1; public const int TOKEN_QUERY = 8; public const int TOKEN_ADJUST_PRIVILEGES = 32;//0x00000020;
// Структура, используемая для передачи в метод AdjustTokenPrivileges // в качестве необходимой привилегии. [StructLayout(LayoutKind.Sequential, Pack=1)] internal struct TokPriv1Luid { // Количество привилегий в наборе. public int Count; public long Luid; // Тип привилегии. public int Attr; }
/// <summary> /// Возвращение указателя на текущий процесс. /// </summary> /// <returns></returns> [DllImport("kernel32.dll", ExactSpelling=true) ] internal static extern IntPtr GetCurrentProcess(); /// <summary> /// Открывание процесса access token, который содержит информацию о ///безопасности текущего пользователя, /// привязанного к заданному процессу. /// </summary> /// <param name="h">Указатель на процесс.</param> /// <param name="acc">Тип access token.</param> /// <param name="phtok">Указатель на access token.</param> /// <returns></returns> [DllImport("advapi32.dll", ExactSpelling=true) ] internal static extern bool OpenProcessToken( IntPtr h, int acc, ref IntPtr phtok ); /// <summary> /// Возвращение значения переменной в текущей сессии ОС. /// </summary> /// <param name="host">Название системы. Если значение null, ///поиск осуществляется /// в локальной системе.</param> /// <param name="name">Название переменной.</param> /// <param name="pluid">Указатель на значение переменной.</param> /// <returns></returns> [DllImport("advapi32.dll") ] internal static extern bool LookupPrivilegeValue( string host, string name, ref long pluid ); /// <summary> /// Включение указанной привилегии. /// </summary> /// <param name="htok">Указатель на access token</param> /// <param name="disall">Необходимость выключения всех привилегий.</param> /// <param name="newst">Новое значение привилегии. Если предыдущее /// значение установлено в true, /// то это значение не учитывается.</param> /// <param name="len">Размер буфера для следующего значения.</param> /// <param name="prev">Предыдущая привилегия.</param> /// <param name="relen">Указатель на размер полученных привилегий.</param> /// <returns></returns> [DllImport("advapi32.dll", ExactSpelling=true) ] internal static extern bool AdjustTokenPrivileges( IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen ); } }
Листинг 5.8.
В коде формы добавляем обработчики кнопок:
private void btnCancel_Click(object sender, System.EventArgs e) { this.Close(); }
private void btnUserOut_Click(object sender, System.EventArgs e) { WinAPIClass.ExitWindowsEx((uint)WinAPIClass.ShutdownType.LogOf, "Win Api test"); }
private void btnTurnOff_Click(object sender, System.EventArgs e) { RestartOrShotDown(WinAPIClass.ShutdownType.Shutdown); }
private void btnRestart_Click(object sender, System.EventArgs e) { RestartOrShotDown(WinAPIClass.ShutdownType.Reboot); } void RestartOrShotDown(WinAPIClass.ShutdownType type) { WinAPIClass.TokPriv1Luid tp; IntPtr hproc = WinAPIClass.GetCurrentProcess(); IntPtr hToken = IntPtr.Zero; WinAPIClass.OpenProcessToken( hproc, WinAPIClass.TOKEN_ADJUST_PRIVILEGES | WinAPIClass.TOKEN_QUERY, ref hToken ); tp.Count = 1; tp.Luid = 0; tp.Attr = WinAPIClass.SE_PRIVILEGE_ENABLED; WinAPIClass.LookupPrivilegeValue(null, WinAPIClass.SE_SHUTDOWN_NAME, ref tp.Luid ); WinAPIClass.AdjustTokenPrivileges(hToken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero ); WinAPIClass.ExitWindowsEx((uint)type, "Win Api test");
}
private void btnCancel2_Click(object sender, System.EventArgs e) { this.Close(); }
Листинг 5.9.
При запуске приложения появляется совмещенное окно завершения работы и смены пользователя (рис. 5.6). Кнопки "Выключение", "Перезагрузка" и "Выход" лучше всего проверять, завершив работу со средой Visual Studio .NET.
Рис. 5.6. Приложение StartTurnOff
На диске, прилагаемом к книге, вы найдете приложение StartTurnOff (Code\Glava5\StartTurnOff).