Skip to content

Commit 57c4b89

Browse files
committed
锁定后自动执行关机、休眠
1 parent fc555b0 commit 57c4b89

File tree

12 files changed

+294
-15
lines changed

12 files changed

+294
-15
lines changed

src/ComputerLock/App.xaml.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ private void Init()
6060
services.AddSingleton<SystemKeyHook>();
6161
services.AddSingleton<HotkeyTools>();
6262
services.AddSingleton<ThemeSwitchService>();
63+
services.AddSingleton<PowerManager>();
6364
services.AddSingleton<IWindowsMessageBox, WindowsMessageBox>();
6465
services.AddSingleton<IGlobalLockService, GlobalLockService>();
6566
services.AddKeyedSingleton<IScreenLockService, PasswordScreenLockService>(ScreenUnlockMethods.Password);

src/ComputerLock/Components/Settings/LockSettings.razor

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@
1414
Dense="true" />
1515

1616
<div>
17-
<MudText Typo="Typo.subtitle2" Class="input-title">@(Lang["AutoLock"])</MudText>
17+
<MudText Typo="Typo.subtitle2" Class="input-title">@($"{Lang["AutoLock"]}{Lang["MinSetTip"]}")</MudText>
1818
<MudNumericField T="int"
1919
Label=""
2020
Value="@(AppSettings.AutoLockMinute)"
2121
Min="0"
2222
Variant="Variant.Outlined"
2323
Margin="Margin.Dense"
2424
Class="max-width-fix"
25+
Style="width:120px;"
26+
Adornment="Adornment.End"
27+
AdornmentText="@(Lang["Min"])"
2528
ValueChanged="AutoLockChanged" />
26-
<MudText Typo="Typo.caption" Class="input-tip">
27-
@(Lang["AutoLockTip"])
28-
</MudText>
2929
</div>
3030

3131
<HotkeyInput Title="@(Lang["LockHotkey"])"
@@ -65,6 +65,34 @@
6565
Color="Color.Secondary"
6666
Class="ml-2">@(Lang["SuggestedToEnable"])</MudChip>
6767
</div>
68+
69+
<div>
70+
<MudText Typo="Typo.subtitle2" Class="input-title">@($"{Lang["AutoPower"]}{Lang["MinSetTip"]}")</MudText>
71+
<MudStack Row="true" Spacing="2" AlignItems="AlignItems.Center">
72+
<MudNumericField T="int"
73+
Label=""
74+
Value="@(AppSettings.AutoPowerMinute)"
75+
Min="0"
76+
Variant="Variant.Outlined"
77+
Margin="Margin.Dense"
78+
Class="max-width-fix"
79+
Style="width:120px;"
80+
Adornment="Adornment.End"
81+
AdornmentText="@(Lang["MinAfter"])"
82+
ValueChanged="AutoPowerChanged" />
83+
84+
<MudChipSet T="PowerActionType"
85+
CheckMark
86+
Size="Size.Small"
87+
Disabled="@(AppSettings.AutoPowerSecond==0)"
88+
SelectedValue="AppSettings.AutoPowerActionType"
89+
SelectedValueChanged="PowerActionTypeChanged"
90+
SelectionMode="SelectionMode.SingleSelection">
91+
<MudChip Value="@PowerActionType.Shutdown" SelectedColor="Color.Secondary" Variant="Variant.Outlined">关机</MudChip>
92+
<MudChip Value="@PowerActionType.Hibernate" SelectedColor="Color.Secondary" Variant="Variant.Outlined">休眠</MudChip>
93+
</MudChipSet>
94+
</MudStack>
95+
</div>
6896
</MudStack>
6997
</MudPaper>
7098

src/ComputerLock/Components/Settings/LockSettings.razor.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ public partial class LockSettings
2323
[Inject]
2424
private HotkeyHook HotkeyHook { get; set; } = null!;
2525

26-
2726
[Inject]
2827
private ILogger Logger { get; set; } = null!;
2928

29+
[Inject]
30+
private PowerManager PowerManager { get; set; } = null!;
3031
private void SaveSettings()
3132
{
3233
AppSettingsProvider.SaveSettings(AppSettings);
@@ -44,7 +45,6 @@ private void AutoLockChanged(int autoLockMinute)
4445
SaveSettings();
4546
GlobalLockService.UpdateAutoLockSettings();
4647
}
47-
4848
private Task SetLockHotkey(string hotkey)
4949
{
5050
AppSettings.LockHotkeyString = hotkey;
@@ -90,4 +90,21 @@ public void UnregisterLockHotkey()
9090
//MessageBoxUtils.ShowError($"取消快捷键失败:{ex.Message}");
9191
}
9292
}
93+
94+
private void AutoPowerChanged(int autoPowerMinute)
95+
{
96+
AppSettings.AutoPowerSecond = autoPowerMinute * 60;
97+
SaveSettings();
98+
}
99+
100+
private void PowerActionTypeChanged(PowerActionType powerActionType)
101+
{
102+
if (powerActionType == PowerActionType.Hibernate && !PowerManager.IsHibernateSupported())
103+
{
104+
Snackbar.Add("系统可能未启用休眠功能,该功能可能无效。", Severity.Error);
105+
return;
106+
}
107+
AppSettings.AutoPowerActionType = powerActionType;
108+
SaveSettings();
109+
}
93110
}

src/ComputerLock/Configuration/AppSettings.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,19 @@ public void Initialize(HotkeyTools hotkeyTools)
155155
/// 启用软件渲染
156156
/// </summary>
157157
public bool IsEnableSoftwareRendering { get; set; } = true;
158-
}
158+
159+
/// <summary>
160+
/// 锁定后执行关机/休眠(秒)
161+
/// </summary>
162+
public int AutoPowerSecond { get; set; } = 0;
163+
164+
/// <summary>
165+
/// 锁定后执行关机/休眠(分钟)
166+
/// </summary>
167+
public int AutoPowerMinute => AutoPowerSecond / 60;
168+
169+
/// <summary>
170+
/// 锁定后自动执行的电源操作类型
171+
/// </summary>
172+
public PowerActionType AutoPowerActionType { get; set; } = PowerActionType.Shutdown;
173+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace ComputerLock.Enums;
9+
10+
/// <summary>
11+
/// 电源操作类型
12+
/// </summary>
13+
public enum PowerActionType
14+
{
15+
/// <summary>
16+
/// 关机
17+
/// </summary>
18+
[Description("关机")]
19+
Shutdown = 1,
20+
21+
/// <summary>
22+
/// 休眠
23+
/// </summary>
24+
[Description("休眠")]
25+
Hibernate = 2
26+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
namespace ComputerLock.Platforms;
2+
internal class PowerManager
3+
{
4+
private void AdjustPrivileges()
5+
{
6+
WinApi.OpenProcessToken(System.Diagnostics.Process.GetCurrentProcess().Handle,
7+
WinApi.TOKEN_ADJUST_PRIVILEGES | WinApi.TOKEN_QUERY, out IntPtr htok);
8+
9+
WinApi.LookupPrivilegeValue(null, WinApi.SE_SHUTDOWN_NAME, out var luid);
10+
11+
var tp = new WinApi.TOKEN_PRIVILEGES
12+
{
13+
PrivilegeCount = 1,
14+
Privileges = new WinApi.LUID_AND_ATTRIBUTES[1]
15+
};
16+
tp.Privileges[0].Luid = luid;
17+
tp.Privileges[0].Attributes = WinApi.SE_PRIVILEGE_ENABLED;
18+
19+
WinApi.AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
20+
}
21+
22+
public void Shutdown()
23+
{
24+
AdjustPrivileges();
25+
WinApi.ExitWindowsEx(WinApi.EWX_SHUTDOWN, 0);
26+
}
27+
28+
public void Hibernate()
29+
{
30+
AdjustPrivileges();
31+
WinApi.SetSuspendState(true, true, true);
32+
}
33+
34+
public bool IsHibernateSupported()
35+
{
36+
// 简单检查系统是否支持休眠
37+
string? sysDrive = Environment.GetEnvironmentVariable("SystemDrive");
38+
if (sysDrive == null)
39+
{
40+
return false;
41+
}
42+
string hiberFile = System.IO.Path.Combine(sysDrive, "hiberfil.sys");
43+
if (!System.IO.File.Exists(hiberFile))
44+
{
45+
return false;
46+
}
47+
return true;
48+
}
49+
}

src/ComputerLock/Platforms/WinApi.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,52 @@ public struct LastInputInfo
8787
public static extern bool GetLastInputInfo(ref LastInputInfo plii);
8888

8989
#endregion
90+
91+
#region 电源相关
92+
93+
[DllImport("user32.dll", SetLastError = true)]
94+
public static extern bool ExitWindowsEx(uint uFlags, uint dwReason);
95+
96+
[DllImport("powrprof.dll", SetLastError = true)]
97+
[return: MarshalAs(UnmanagedType.Bool)]
98+
public static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);
99+
100+
[DllImport("advapi32.dll", SetLastError = true)]
101+
public static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);
102+
103+
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
104+
public static extern bool LookupPrivilegeValue(string? lpSystemName, string lpName, out LUID lpLuid);
105+
106+
[DllImport("advapi32.dll", SetLastError = true)]
107+
public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, uint BufferLength, IntPtr PreviousState, IntPtr ReturnLength);
108+
109+
[StructLayout(LayoutKind.Sequential)]
110+
public struct LUID
111+
{
112+
public uint LowPart;
113+
public int HighPart;
114+
}
115+
116+
[StructLayout(LayoutKind.Sequential)]
117+
public struct TOKEN_PRIVILEGES
118+
{
119+
public uint PrivilegeCount;
120+
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
121+
public LUID_AND_ATTRIBUTES[] Privileges;
122+
}
123+
124+
[StructLayout(LayoutKind.Sequential)]
125+
public struct LUID_AND_ATTRIBUTES
126+
{
127+
public LUID Luid;
128+
public uint Attributes;
129+
}
130+
131+
public const uint EWX_SHUTDOWN = 0x00000001;
132+
public const uint TOKEN_QUERY = 0x0008;
133+
public const uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
134+
public const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
135+
public const uint SE_PRIVILEGE_ENABLED = 0x00000002;
136+
137+
#endregion
90138
}

src/ComputerLock/Resources/Lang.Designer.cs

Lines changed: 29 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ComputerLock/Resources/Lang.en.resx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,16 @@
412412
<data name="Lock_Group_Tips" xml:space="preserve">
413413
<value>Unlock Tips</value>
414414
</data>
415-
<data name="AutoLockTip" xml:space="preserve">
416-
<value>Minutes (0 to disable)</value>
415+
<data name="MinSetTip" xml:space="preserve">
416+
<value>(0 to disable)</value>
417+
</data>
418+
<data name="Min" xml:space="preserve">
419+
<value>min</value>
420+
</data>
421+
<data name="AutoPower" xml:space="preserve">
422+
<value>Automatically Execute After Locking</value>
423+
</data>
424+
<data name="MinAfter" xml:space="preserve">
425+
<value>min</value>
417426
</data>
418427
</root>

src/ComputerLock/Resources/Lang.resx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,16 @@
430430
<data name="Lock_Group_Tips" xml:space="preserve">
431431
<value />
432432
</data>
433-
<data name="AutoLockTip" xml:space="preserve">
433+
<data name="MinSetTip" xml:space="preserve">
434+
<value></value>
435+
</data>
436+
<data name="Min" xml:space="preserve">
437+
<value></value>
438+
</data>
439+
<data name="AutoPower" xml:space="preserve">
440+
<value></value>
441+
</data>
442+
<data name="MinAfter" xml:space="preserve">
434443
<value></value>
435444
</data>
436445
</root>

0 commit comments

Comments
 (0)