mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-16 01:40:46 +08:00
feat: winapi 关机/睡眠/休眠
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=WSA/@EntryIndexedValue">WSA</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=XYAZ/@EntryIndexedValue">XYAZ</s:String>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=acast/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=advapi/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Aero/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Affero/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=aguard/@EntryIndexedValue">True</s:Boolean>
|
||||
@@ -92,6 +93,7 @@
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pallas/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=pidl/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pormpt/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=powrprof/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ppidl/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Prts/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=pwfi/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
144
src/MaaWpfGui/Utilities/PowerManagement.cs
Normal file
144
src/MaaWpfGui/Utilities/PowerManagement.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
// <copyright file="PowerManagement.cs" company="MaaAssistantArknights">
|
||||
// MaaWpfGui - A part of the MaaCoreArknights project
|
||||
// Copyright (C) 2021 MistEO and Contributors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License v3.0 only as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Serilog;
|
||||
|
||||
namespace MaaWpfGui.Utilities
|
||||
{
|
||||
public class PowerManagement
|
||||
{
|
||||
private static readonly ILogger _logger = Log.ForContext<PowerManagement>();
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern bool ExitWindowsEx(uint uFlags, uint dwReason);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError = true)]
|
||||
private static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, uint BufferLengthInBytes, IntPtr PreviousState, IntPtr ReturnLengthInBytes);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError = true)]
|
||||
private static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern IntPtr GetCurrentProcess();
|
||||
|
||||
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
|
||||
private static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);
|
||||
|
||||
[DllImport("powrprof.dll", SetLastError = true, ExactSpelling = true)]
|
||||
private static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
private struct TOKEN_PRIVILEGES
|
||||
{
|
||||
public int PrivilegeCount;
|
||||
public LUID Luid;
|
||||
public int Attributes;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct LUID
|
||||
{
|
||||
public uint LowPart;
|
||||
public int HighPart;
|
||||
}
|
||||
|
||||
private const int SE_PRIVILEGE_ENABLED = 0x00000002;
|
||||
private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
|
||||
private const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
|
||||
private const int TOKEN_QUERY = 0x0008;
|
||||
private const int EWX_SHUTDOWN = 0x00000001;
|
||||
private const int EWX_FORCE = 0x00000004;
|
||||
|
||||
public static bool Shutdown()
|
||||
{
|
||||
IntPtr hToken = IntPtr.Zero;
|
||||
TOKEN_PRIVILEGES tkp;
|
||||
|
||||
try
|
||||
{
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken))
|
||||
{
|
||||
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
if (!LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, out tkp.Luid))
|
||||
{
|
||||
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
tkp.PrivilegeCount = 1;
|
||||
tkp.Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
if (!AdjustTokenPrivileges(hToken, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero))
|
||||
{
|
||||
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
if (Marshal.GetLastWin32Error() != 0)
|
||||
{
|
||||
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0))
|
||||
{
|
||||
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"Shutdown error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (hToken != IntPtr.Zero)
|
||||
{
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Hibernate()
|
||||
{
|
||||
try
|
||||
{
|
||||
return SetSuspendState(true, true, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"Hibernate error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Sleep()
|
||||
{
|
||||
try
|
||||
{
|
||||
return SetSuspendState(false, true, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"Sleep error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,12 +197,16 @@ namespace MaaWpfGui.ViewModels.UI
|
||||
// 休眠提示
|
||||
AddLog(LocalizationHelper.GetString("HibernatePrompt"), UiLogColor.Error);
|
||||
|
||||
/*
|
||||
// 休眠不能加时间参数,https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues/1133
|
||||
Process.Start("shutdown.exe", "-h");
|
||||
*/
|
||||
PowerManagement.Hibernate();
|
||||
}
|
||||
|
||||
void DoShutDown()
|
||||
async void DoShutDown()
|
||||
{
|
||||
/*
|
||||
Process.Start("shutdown.exe", "-s -t 60");
|
||||
|
||||
// 关机询问
|
||||
@@ -211,6 +215,17 @@ namespace MaaWpfGui.ViewModels.UI
|
||||
{
|
||||
Process.Start("shutdown.exe", "-a");
|
||||
}
|
||||
*/
|
||||
if (await TimerCanceledAsync(
|
||||
LocalizationHelper.GetString("Shutdown"),
|
||||
LocalizationHelper.GetString("AboutToShutdown"),
|
||||
LocalizationHelper.GetString("Cancel"),
|
||||
60))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PowerManagement.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,7 +447,11 @@ namespace MaaWpfGui.ViewModels.UI
|
||||
Instances.MainWindowManager?.Show();
|
||||
}
|
||||
|
||||
if (await TimerCanceledAsync())
|
||||
if (await TimerCanceledAsync(
|
||||
LocalizationHelper.GetString("ForceScheduledStart"),
|
||||
LocalizationHelper.GetString("ForceScheduledStartTip"),
|
||||
LocalizationHelper.GetString("Cancel"),
|
||||
10))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -456,13 +475,13 @@ namespace MaaWpfGui.ViewModels.UI
|
||||
LinkStart();
|
||||
}
|
||||
|
||||
private static async Task<bool> TimerCanceledAsync()
|
||||
private static async Task<bool> TimerCanceledAsync(string content = "", string tipContent = "", string buttonContent="", int seconds = 10)
|
||||
{
|
||||
var delay = TimeSpan.FromSeconds(10);
|
||||
var delay = TimeSpan.FromSeconds(seconds);
|
||||
var dialogUserControl = new Views.UserControl.TextDialogWithTimerUserControl(
|
||||
LocalizationHelper.GetString("ForceScheduledStart"),
|
||||
LocalizationHelper.GetString("ForceScheduledStartTip"),
|
||||
LocalizationHelper.GetString("Cancel"),
|
||||
content,
|
||||
tipContent,
|
||||
buttonContent,
|
||||
delay.TotalMilliseconds);
|
||||
var dialog = HandyControl.Controls.Dialog.Show(dialogUserControl, nameof(Views.UI.RootView));
|
||||
var canceled = false;
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:styles="clr-namespace:MaaWpfGui.Styles"
|
||||
x:Name="ErrorViewWindow"
|
||||
Icon="../../newlogo.ico"
|
||||
Title="{DynamicResource Error}"
|
||||
Width="600"
|
||||
Height="480"
|
||||
MinWidth="400"
|
||||
MinHeight="200"
|
||||
Icon="../../newlogo.ico"
|
||||
ResizeMode="CanResize"
|
||||
Topmost="True"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
|
||||
Reference in New Issue
Block a user