mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 03:37:59 +01:00
dev
This commit is contained in:
@@ -1,350 +0,0 @@
|
||||
# PowerToys Awake - Comprehensive Documentation
|
||||
|
||||
## Table of Contents
|
||||
1. [Overview](#overview)
|
||||
2. [Key Features](#key-features)
|
||||
3. [Installation](#installation)
|
||||
4. [Command Line Usage](#command-line-usage)
|
||||
5. [GUI Usage](#gui-usage)
|
||||
6. [Operating Modes](#operating-modes)
|
||||
7. [Configuration File](#configuration-file)
|
||||
8. [Examples](#examples)
|
||||
9. [Advanced Usage](#advanced-usage)
|
||||
10. [Troubleshooting](#troubleshooting)
|
||||
11. [Technical Details](#technical-details)
|
||||
|
||||
## Overview
|
||||
|
||||
PowerToys Awake is a utility designed to keep your computer awake without permanently modifying system power settings. It prevents the computer from sleeping and can optionally keep the monitor on, providing a convenient alternative to changing system power configurations.
|
||||
|
||||
**Application Name**: `Awake.exe` (part of PowerToys)
|
||||
**Full Name**: PowerToys Awake
|
||||
**Build Version**: TILLSON_11272024
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Temporary Override**: Prevents system sleep without permanent power setting changes
|
||||
- **Display Control**: Option to keep monitor on or allow it to turn off
|
||||
- **Multiple Modes**: Support for indefinite, timed, expirable, and passive modes
|
||||
- **Command Line Interface**: Full programmatic control via command-line parameters
|
||||
- **Process Binding**: Bind Awake to another process's lifecycle
|
||||
- **System Tray Integration**: Easy access through Windows system tray
|
||||
- **PowerToys Integration**: Seamless integration with PowerToys settings
|
||||
|
||||
## Installation
|
||||
|
||||
Awake is included as part of Microsoft PowerToys. Install PowerToys from:
|
||||
- Microsoft Store
|
||||
- GitHub Releases: https://github.com/microsoft/PowerToys/releases
|
||||
- Windows Package Manager: `winget install Microsoft.PowerToys`
|
||||
|
||||
## Command Line Usage
|
||||
|
||||
### Basic Syntax
|
||||
```
|
||||
Awake.exe [OPTIONS]
|
||||
```
|
||||
|
||||
### Available Options
|
||||
|
||||
| Option | Short | Description | Type | Default |
|
||||
|--------|-------|-------------|------|---------|
|
||||
| `--use-pt-config` | `-c` | Use PowerToys configuration file for managing state | Boolean | false |
|
||||
| `--display-on` | `-d` | Keep the display awake | Boolean | true |
|
||||
| `--time-limit` | `-t` | Time interval in seconds to keep computer awake | Integer | 0 |
|
||||
| `--pid` | `-p` | Bind to a specific process ID | Integer | 0 |
|
||||
| `--expire-at` | `-e` | Expire at specific date/time | DateTime String | - |
|
||||
| `--use-parent-pid` | `-u` | Bind to parent process | Boolean | false |
|
||||
|
||||
### Parameter Details
|
||||
|
||||
#### `--use-pt-config` / `-c`
|
||||
- **Purpose**: Use PowerToys configuration file for state management
|
||||
- **Behavior**: When enabled, ignores other command-line parameters
|
||||
- **Usage**: `Awake.exe -c`
|
||||
|
||||
#### `--display-on` / `-d`
|
||||
- **Purpose**: Controls whether the display stays on
|
||||
- **Values**: `true` (keep display on) or `false` (allow display to turn off)
|
||||
- **Usage**: `Awake.exe -d false`
|
||||
|
||||
#### `--time-limit` / `-t`
|
||||
- **Purpose**: Keep computer awake for specified seconds
|
||||
- **Range**: 0 to 4,294,967,295 seconds
|
||||
- **Note**: 0 means indefinite
|
||||
- **Usage**: `Awake.exe -t 3600` (1 hour)
|
||||
|
||||
#### `--pid` / `-p`
|
||||
- **Purpose**: Bind Awake to another process
|
||||
- **Behavior**: Awake terminates when the target process ends
|
||||
- **Usage**: `Awake.exe -p 1234`
|
||||
|
||||
#### `--expire-at` / `-e`
|
||||
- **Purpose**: Set expiration date and time
|
||||
- **Format**: ISO 8601 date/time format
|
||||
- **Usage**: `Awake.exe -e "2025-07-07T15:30:00"`
|
||||
|
||||
#### `--use-parent-pid` / `-u`
|
||||
- **Purpose**: Bind to the parent process of Awake
|
||||
- **Behavior**: Automatically determines parent PID
|
||||
- **Usage**: `Awake.exe -u`
|
||||
|
||||
## GUI Usage
|
||||
|
||||
Access Awake through the PowerToys system tray icon:
|
||||
|
||||
1. **Right-click** the PowerToys tray icon
|
||||
2. **Navigate** to Awake submenu
|
||||
3. **Select** desired mode:
|
||||
- Off (Passive)
|
||||
- Keep awake indefinitely
|
||||
- Keep awake for interval
|
||||
- Keep awake until expiration
|
||||
|
||||
### PowerToys Settings
|
||||
|
||||
Open PowerToys Settings → Awake to configure:
|
||||
- **Enable/Disable** Awake module
|
||||
- **Mode Selection**: Passive, Indefinite, Timed, Expirable
|
||||
- **Display Settings**: Keep screen on/off
|
||||
- **Time Configuration**: Hours and minutes for timed mode
|
||||
- **Expiration Settings**: Date and time for expirable mode
|
||||
|
||||
## Operating Modes
|
||||
|
||||
### 1. Passive Mode (`PASSIVE`)
|
||||
- **Description**: Uses system's default power plan
|
||||
- **Command**: `Awake.exe -c` (with passive mode in config)
|
||||
- **Behavior**: No keep-awake functionality active
|
||||
|
||||
### 2. Indefinite Mode (`INDEFINITE`)
|
||||
- **Description**: Keeps computer awake indefinitely
|
||||
- **Command**: `Awake.exe -t 0` or `Awake.exe` (default)
|
||||
- **Behavior**: Prevents sleep until manually stopped
|
||||
|
||||
### 3. Timed Mode (`TIMED`)
|
||||
- **Description**: Keeps computer awake for specified duration
|
||||
- **Command**: `Awake.exe -t <seconds>`
|
||||
- **Behavior**: Automatically returns to passive mode after timeout
|
||||
|
||||
### 4. Expirable Mode (`EXPIRABLE`)
|
||||
- **Description**: Keeps computer awake until specific date/time
|
||||
- **Command**: `Awake.exe -e "YYYY-MM-DDTHH:MM:SS"`
|
||||
- **Behavior**: Automatically returns to passive mode at expiration
|
||||
|
||||
## Configuration File
|
||||
|
||||
When using `--use-pt-config`, Awake reads settings from PowerToys configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"properties": {
|
||||
"keepDisplayOn": true,
|
||||
"mode": 1,
|
||||
"intervalHours": 2,
|
||||
"intervalMinutes": 30,
|
||||
"expirationDateTime": "2025-07-07T15:30:00-07:00",
|
||||
"customTrayTimes": {
|
||||
"30 minutes": 1800,
|
||||
"1 hour": 3600,
|
||||
"2 hours": 7200
|
||||
}
|
||||
},
|
||||
"name": "Awake",
|
||||
"version": "1.0"
|
||||
}
|
||||
```
|
||||
|
||||
### Mode Values
|
||||
- `0`: PASSIVE
|
||||
- `1`: INDEFINITE
|
||||
- `2`: TIMED
|
||||
- `3`: EXPIRABLE
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```powershell
|
||||
# Keep computer awake indefinitely with display on
|
||||
Awake.exe
|
||||
|
||||
# Keep computer awake for 1 hour (3600 seconds)
|
||||
Awake.exe -t 3600
|
||||
|
||||
# Keep computer awake for 30 minutes without display
|
||||
Awake.exe -t 1800 -d false
|
||||
|
||||
# Keep computer awake until specific time
|
||||
Awake.exe -e "2025-07-07T17:00:00"
|
||||
|
||||
# Use PowerToys configuration
|
||||
Awake.exe --use-pt-config
|
||||
```
|
||||
|
||||
### Process Binding
|
||||
|
||||
```powershell
|
||||
# Bind to specific process ID
|
||||
Awake.exe -p 1234
|
||||
|
||||
# Bind to parent process
|
||||
Awake.exe -u
|
||||
|
||||
# Bind to PowerToys runner with display control
|
||||
Awake.exe -p 5678 -d true
|
||||
```
|
||||
|
||||
### Advanced Scenarios
|
||||
|
||||
```powershell
|
||||
# Long-running development session (8 hours)
|
||||
Awake.exe -t 28800 -d false
|
||||
|
||||
# Presentation mode (keep display on indefinitely)
|
||||
Awake.exe -t 0 -d true
|
||||
|
||||
# Overnight process (expire at 8 AM next day)
|
||||
Awake.exe -e "2025-07-08T08:00:00"
|
||||
|
||||
# Bind to Visual Studio process
|
||||
$vsProcess = Get-Process "devenv" | Select-Object -First 1
|
||||
Awake.exe -p $vsProcess.Id
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Custom Tray Times
|
||||
|
||||
Configure custom time shortcuts in PowerToys settings:
|
||||
|
||||
```json
|
||||
"customTrayTimes": {
|
||||
"Quick break": 900, // 15 minutes
|
||||
"Lunch break": 3600, // 1 hour
|
||||
"Meeting": 5400, // 1.5 hours
|
||||
"Long task": 14400 // 4 hours
|
||||
}
|
||||
```
|
||||
|
||||
### Integration with Scripts
|
||||
|
||||
```powershell
|
||||
# PowerShell script to start/stop Awake
|
||||
function Start-AwakeSession {
|
||||
param(
|
||||
[int]$Hours = 0,
|
||||
[int]$Minutes = 30,
|
||||
[bool]$KeepDisplay = $true
|
||||
)
|
||||
|
||||
$seconds = ($Hours * 3600) + ($Minutes * 60)
|
||||
$displayArg = if ($KeepDisplay) { "true" } else { "false" }
|
||||
|
||||
Start-Process "Awake.exe" -ArgumentList "-t", $seconds, "-d", $displayArg
|
||||
}
|
||||
|
||||
# Usage
|
||||
Start-AwakeSession -Hours 2 -Minutes 15 -KeepDisplay $false
|
||||
```
|
||||
|
||||
### Batch File Examples
|
||||
|
||||
```batch
|
||||
@echo off
|
||||
REM Quick 30-minute session
|
||||
"C:\Program Files\PowerToys\Awake.exe" -t 1800
|
||||
|
||||
REM All-day work session until 6 PM
|
||||
"C:\Program Files\PowerToys\Awake.exe" -e "2025-07-07T18:00:00"
|
||||
|
||||
REM Bind to current PowerShell session
|
||||
for /f "tokens=2" %%i in ('tasklist /fi "imagename eq powershell.exe" /fo csv ^| findstr /v "PID"') do (
|
||||
"C:\Program Files\PowerToys\Awake.exe" -p %%i
|
||||
goto :done
|
||||
)
|
||||
:done
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### 1. Awake Already Running
|
||||
**Error**: "PowerToys.Awake is already running! Exiting the application."
|
||||
**Solution**: Only one instance can run at a time. Close existing instance first.
|
||||
|
||||
#### 2. Invalid Time Limit
|
||||
**Error**: Time limit parsing error
|
||||
**Solution**: Ensure value is between 0 and 4,294,967,295 seconds.
|
||||
|
||||
#### 3. Invalid PID
|
||||
**Error**: PID parsing error
|
||||
**Solution**: Verify the process ID exists and is valid.
|
||||
|
||||
#### 4. Invalid Date Format
|
||||
**Error**: Date/time parsing error
|
||||
**Solution**: Use ISO 8601 format: "YYYY-MM-DDTHH:MM:SS"
|
||||
|
||||
#### 5. Group Policy Restrictions
|
||||
**Error**: "Group policy setting disables the tool"
|
||||
**Solution**: Contact system administrator to enable PowerToys Awake.
|
||||
|
||||
### Debug Information
|
||||
|
||||
Awake logs information to:
|
||||
- **Location**: `%LOCALAPPDATA%\Microsoft\PowerToys\Awake\Logs`
|
||||
- **File Format**: Timestamped log files
|
||||
- **Content**: Startup, mode changes, errors, exit events
|
||||
|
||||
### System Requirements
|
||||
|
||||
- **OS**: Windows 10 version 2004 (build 19041) or later
|
||||
- **Architecture**: x64, ARM64
|
||||
- **Dependencies**: .NET runtime (included with PowerToys)
|
||||
- **Permissions**: Standard user (no administrator required for basic functionality)
|
||||
|
||||
## Technical Details
|
||||
|
||||
### Power Management
|
||||
|
||||
Awake uses Windows Power Management APIs:
|
||||
- **SetThreadExecutionState**: Prevents system sleep
|
||||
- **ES_CONTINUOUS**: Maintains execution state
|
||||
- **ES_SYSTEM_REQUIRED**: Prevents system sleep
|
||||
- **ES_DISPLAY_REQUIRED**: Prevents display sleep
|
||||
|
||||
### System Integration
|
||||
|
||||
- **Mutex**: `PowerToys.Awake` prevents multiple instances
|
||||
- **Event Handling**: `AwakeExitEvent` for clean shutdown
|
||||
- **Tray Icons**: Different icons for each mode
|
||||
- **File Watcher**: Monitors configuration file changes
|
||||
|
||||
### Exit Conditions
|
||||
|
||||
Awake terminates when:
|
||||
1. Manual exit via tray menu or Ctrl+C
|
||||
2. Time limit reached (timed mode)
|
||||
3. Expiration time reached (expirable mode)
|
||||
4. Bound process terminates (PID binding)
|
||||
5. PowerToys shutdown signal
|
||||
6. System shutdown/restart
|
||||
|
||||
### Performance Impact
|
||||
|
||||
- **CPU Usage**: Minimal (~0% when idle)
|
||||
- **Memory Usage**: ~10-20 MB
|
||||
- **Battery Impact**: Prevents sleep-related power savings
|
||||
- **Network**: No network activity required
|
||||
|
||||
## Version Information
|
||||
|
||||
- **Current Build**: TILLSON_11272024
|
||||
- **Assembly Version**: Retrieved at runtime
|
||||
- **PowerToys Integration**: Full integration with PowerToys settings
|
||||
- **Telemetry**: Basic usage telemetry (configurable in PowerToys settings)
|
||||
|
||||
---
|
||||
|
||||
*For the latest updates and documentation, visit the [PowerToys GitHub repository](https://github.com/microsoft/PowerToys).*
|
||||
1
deps/cziplib
vendored
Submodule
1
deps/cziplib
vendored
Submodule
Submodule deps/cziplib added at 81314fff0a
@@ -901,6 +901,60 @@ public:
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
virtual std::wstring describe() override
|
||||
{
|
||||
try
|
||||
{
|
||||
auto baseDescription = PowertoyModuleIface::describe();
|
||||
auto descriptionObject = winrt::Windows::Data::Json::JsonObject::Parse(winrt::hstring(baseDescription));
|
||||
auto methodsArray = descriptionObject.GetNamedArray(L"methods");
|
||||
|
||||
winrt::Windows::Data::Json::JsonObject launchMethod;
|
||||
launchMethod.SetNamedValue(L"name", winrt::Windows::Data::Json::JsonValue::CreateStringValue(L"launch"));
|
||||
launchMethod.SetNamedValue(L"description", winrt::Windows::Data::Json::JsonValue::CreateStringValue(L"Open Advanced Paste UI"));
|
||||
methodsArray.Append(launchMethod);
|
||||
|
||||
return descriptionObject.Stringify().c_str();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return PowertoyModuleIface::describe();
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::wstring invoke(const wchar_t* method, const wchar_t* jsonParams) override
|
||||
{
|
||||
if (method != nullptr && wcscmp(method, L"launch") == 0)
|
||||
{
|
||||
if (!is_enabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
enable();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return L"{\"ok\":false,\"error\":\"EnableFailed\"}";
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
m_process_manager.start();
|
||||
m_process_manager.bring_to_front();
|
||||
m_process_manager.send_message(CommonSharedConstants::ADVANCED_PASTE_SHOW_UI_MESSAGE);
|
||||
Trace::AdvancedPaste_Invoked(L"AdvancedPasteUI");
|
||||
return L"{\"ok\":true}";
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return L"{\"ok\":false,\"error\":\"LaunchFailed\"}";
|
||||
}
|
||||
}
|
||||
|
||||
return PowertoyModuleIface::invoke(method, jsonParams);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
|
||||
@@ -169,7 +169,10 @@
|
||||
<AdditionalIncludeDirectories>..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(CoreLibraryDependencies);%(AdditionalDependencies);advapi32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(CoreLibraryDependencies);%(AdditionalDependencies);advapi32.lib;Shlwapi.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(CoreLibraryDependencies);%(AdditionalDependencies);advapi32.lib;Shlwapi.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(CoreLibraryDependencies);%(AdditionalDependencies);advapi32.lib;Shlwapi.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(CoreLibraryDependencies);%(AdditionalDependencies);advapi32.lib;Shlwapi.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
@@ -222,4 +225,4 @@
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -305,6 +305,8 @@ typedef const char* (__stdcall *describe_fn)(void);
|
||||
__declspec(dllexport) int __stdcall PT_GetModule(IPTModule** out);
|
||||
```
|
||||
|
||||
PowerToys ships a helper implementation in `PowertoyModuleIface`. Each module inherits default `describe` / `invoke` implementations so that, at a minimum, a `navigateToSettings` verb is exposed. Modules can override those members to add richer metadata or behaviors, but no module can opt out of providing at least the settings deep link.
|
||||
|
||||
9.2 Method routing
|
||||
|
||||
* Module receives method and params JSON; validate and route to a function:
|
||||
@@ -858,4 +860,4 @@ Each module exposes a capabilities blob via Describe():
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.CmdPal.Ext.PowerToys.Helper;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
@@ -13,6 +14,12 @@ internal sealed class PowerToysModuleEntry
|
||||
|
||||
public void NavigateToSettingsPage()
|
||||
{
|
||||
var moduleKey = Module.ModuleKey();
|
||||
if (PowerToysRpcClient.TryInvoke(moduleKey, "navigateToSettings"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OpenSettings(Module);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,4 +97,44 @@ public static class PowerToysResourcesHelper
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
}
|
||||
|
||||
public static string ModuleKey(this SettingsWindow module)
|
||||
{
|
||||
return module switch
|
||||
{
|
||||
SettingsWindow.Dashboard => "Dashboard",
|
||||
SettingsWindow.Overview => "Overview",
|
||||
SettingsWindow.AlwaysOnTop => "AlwaysOnTop",
|
||||
SettingsWindow.Awake => "Awake",
|
||||
SettingsWindow.ColorPicker => "ColorPicker",
|
||||
SettingsWindow.CmdNotFound => "CmdNotFound",
|
||||
SettingsWindow.LightSwitch => "LightSwitch",
|
||||
SettingsWindow.FancyZones => "FancyZones",
|
||||
SettingsWindow.FileLocksmith => "FileLocksmith",
|
||||
SettingsWindow.Run => "Run",
|
||||
SettingsWindow.ImageResizer => "ImageResizer",
|
||||
SettingsWindow.KBM => "KBM",
|
||||
SettingsWindow.MouseUtils => "MouseUtils",
|
||||
SettingsWindow.MouseWithoutBorders => "MouseWithoutBorders",
|
||||
SettingsWindow.Peek => "Peek",
|
||||
SettingsWindow.PowerAccent => "PowerAccent",
|
||||
SettingsWindow.PowerLauncher => "PowerLauncher",
|
||||
SettingsWindow.PowerPreview => "PowerPreview",
|
||||
SettingsWindow.PowerRename => "PowerRename",
|
||||
SettingsWindow.FileExplorer => "FileExplorer",
|
||||
SettingsWindow.ShortcutGuide => "ShortcutGuide",
|
||||
SettingsWindow.Hosts => "Hosts",
|
||||
SettingsWindow.MeasureTool => "MeasureTool",
|
||||
SettingsWindow.PowerOCR => "PowerOcr",
|
||||
SettingsWindow.Workspaces => "Workspaces",
|
||||
SettingsWindow.RegistryPreview => "RegistryPreview",
|
||||
SettingsWindow.CropAndLock => "CropAndLock",
|
||||
SettingsWindow.EnvironmentVariables => "EnvironmentVariables",
|
||||
SettingsWindow.AdvancedPaste => "AdvancedPaste",
|
||||
SettingsWindow.NewPlus => "NewPlus",
|
||||
SettingsWindow.CmdPal => "CmdPal",
|
||||
SettingsWindow.ZoomIt => "ZoomIt",
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.PowerToys.Helper;
|
||||
|
||||
internal static class PowerToysRpcClient
|
||||
{
|
||||
private const string PipeName = "PowerToys.CmdPal.Rpc";
|
||||
|
||||
public static bool TryInvoke(string module, string method, object? parameters = null, int timeoutMs = 5000)
|
||||
{
|
||||
var request = new RpcRequest
|
||||
{
|
||||
Module = module,
|
||||
Method = method,
|
||||
Parameters = parameters ?? new { },
|
||||
TimeoutMs = timeoutMs,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
using var pipe = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut, PipeOptions.None);
|
||||
pipe.Connect(timeoutMs);
|
||||
|
||||
var payload = JsonSerializer.SerializeToUtf8Bytes(request, PowerToysRpcClientContext.Default.RpcRequest);
|
||||
using (var writer = new BinaryWriter(pipe, Encoding.UTF8, leaveOpen: true))
|
||||
{
|
||||
writer.Write(payload.Length);
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
pipe.Write(payload, 0, payload.Length);
|
||||
pipe.Flush();
|
||||
|
||||
using var reader = new BinaryReader(pipe, Encoding.UTF8, leaveOpen: true);
|
||||
var responseLength = reader.ReadInt32();
|
||||
if (responseLength <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var buffer = new byte[responseLength];
|
||||
var totalRead = 0;
|
||||
while (totalRead < responseLength)
|
||||
{
|
||||
var read = pipe.Read(buffer, totalRead, responseLength - totalRead);
|
||||
if (read == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
totalRead += read;
|
||||
}
|
||||
|
||||
using var document = JsonDocument.Parse(buffer);
|
||||
return document.RootElement.TryGetProperty("ok", out var okProperty) && okProperty.GetBoolean();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class RpcRequest
|
||||
{
|
||||
[JsonPropertyName("version")]
|
||||
public string Version { get; init; } = "1.0";
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; init; } = Guid.NewGuid().ToString();
|
||||
|
||||
[JsonPropertyName("module")]
|
||||
public string Module { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("method")]
|
||||
public string Method { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("params")]
|
||||
public object Parameters { get; init; } = new { };
|
||||
|
||||
[JsonPropertyName("timeoutMs")]
|
||||
public int TimeoutMs { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.PowerToys.Helper;
|
||||
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Default)]
|
||||
[JsonSerializable(typeof(PowerToysRpcClient.RpcRequest))]
|
||||
internal sealed partial class PowerToysRpcClientContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
@@ -20,8 +20,6 @@
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\Microsoft.CmdPal.Ext.PowerToys\PowerToysExtensionAssets.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\Microsoft.CmdPal.UI\Assets\Stable\SplashScreen.scale-200.png">
|
||||
<Link>Assets\SplashScreen.scale-200.png</Link>
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <compare>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cwchar>
|
||||
#include <windows.h>
|
||||
|
||||
#include <common/utils/gpo.h>
|
||||
#include <common/utils/process_path.h>
|
||||
|
||||
/*
|
||||
DLL Interface for PowerToys. The powertoy_create() (see below) must return
|
||||
@@ -37,6 +45,13 @@
|
||||
class PowertoyModuleIface
|
||||
{
|
||||
public:
|
||||
struct CmdPalCommand
|
||||
{
|
||||
std::wstring name;
|
||||
std::wstring method;
|
||||
std::wstring description;
|
||||
};
|
||||
|
||||
/* Describes a hotkey which can trigger an action in the PowerToy */
|
||||
struct Hotkey
|
||||
{
|
||||
@@ -155,6 +170,86 @@ public:
|
||||
return powertoys_gpo::gpo_rule_configured_not_configured;
|
||||
}
|
||||
|
||||
virtual std::wstring describe()
|
||||
{
|
||||
auto moduleName = std::wstring(get_name());
|
||||
auto moduleKey = std::wstring(get_key());
|
||||
std::wstring description = L"{\"name\":\"" + moduleKey + L"\",";
|
||||
description += L"\"displayName\":\"" + moduleName + L"\",";
|
||||
description += L"\"methods\":[";
|
||||
description += L"{\"name\":\"navigateToSettings\",\"description\":\"Open " + moduleName + L" settings\"},";
|
||||
description += L"{\"name\":\"enable\",\"description\":\"Enable the module\"},";
|
||||
description += L"{\"name\":\"disable\",\"description\":\"Disable the module\"}";
|
||||
description += L"]}";
|
||||
return description;
|
||||
}
|
||||
|
||||
virtual std::wstring invoke(const wchar_t* method, const wchar_t* /*jsonParams*/)
|
||||
{
|
||||
if (method != nullptr && wcscmp(method, L"navigateToSettings") == 0)
|
||||
{
|
||||
const auto moduleKey = std::wstring(get_key());
|
||||
const auto exePath = get_module_folderpath() + L"\\PowerToys.exe";
|
||||
if (!std::filesystem::exists(exePath))
|
||||
{
|
||||
return L"{\"ok\":false,\"error\":\"PowerToysExeNotFound\"}";
|
||||
}
|
||||
|
||||
std::wstring args = L"--open-settings=" + moduleKey;
|
||||
std::wstring commandLine = L"\"" + exePath + L"\" " + args;
|
||||
std::vector<wchar_t> commandLineBuffer(commandLine.begin(), commandLine.end());
|
||||
commandLineBuffer.push_back(L'\0');
|
||||
|
||||
STARTUPINFO startupInfo{};
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
PROCESS_INFORMATION processInformation{};
|
||||
|
||||
if (CreateProcessW(exePath.c_str(),
|
||||
commandLineBuffer.data(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
FALSE,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&startupInfo,
|
||||
&processInformation))
|
||||
{
|
||||
CloseHandle(processInformation.hProcess);
|
||||
CloseHandle(processInformation.hThread);
|
||||
return L"{\"ok\":true}";
|
||||
}
|
||||
|
||||
return L"{\"ok\":false,\"error\":\"LaunchFailed\"}";
|
||||
}
|
||||
else if (method != nullptr && wcscmp(method, L"enable") == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
enable();
|
||||
return L"{\"ok\":true,\"result\":{\"enabled\":true}}";
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return L"{\"ok\":false,\"error\":\"EnableFailed\"}";
|
||||
}
|
||||
}
|
||||
else if (method != nullptr && wcscmp(method, L"disable") == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
disable();
|
||||
return L"{\"ok\":true,\"result\":{\"enabled\":false}}";
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return L"{\"ok\":false,\"error\":\"DisableFailed\"}";
|
||||
}
|
||||
}
|
||||
|
||||
return L"{\"ok\":false,\"error\":\"Method.NotFound\"}";
|
||||
}
|
||||
|
||||
// Some actions like AdvancedPaste generate new inputs, which we don't want to catch again.
|
||||
// The flag was purposefully chose to not collide with other keyboard manager flags.
|
||||
const static inline ULONG_PTR CENTRALIZED_KEYBOARD_HOOK_DONT_TRIGGER_FLAG = 0x110;
|
||||
|
||||
327
src/runner/cmdpal_rpc_server.cpp
Normal file
327
src/runner/cmdpal_rpc_server.cpp
Normal file
@@ -0,0 +1,327 @@
|
||||
#include "pch.h"
|
||||
#include "cmdpal_rpc_server.h"
|
||||
|
||||
#include "powertoy_module.h"
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
using namespace winrt::Windows::Data::Json;
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr wchar_t PIPE_NAME[] = LR"(\\.\pipe\PowerToys.CmdPal.Rpc)";
|
||||
|
||||
std::string ToUtf8(const winrt::hstring& value)
|
||||
{
|
||||
return winrt::to_string(value);
|
||||
}
|
||||
|
||||
winrt::hstring ToHString(const std::string& value)
|
||||
{
|
||||
return winrt::to_hstring(value);
|
||||
}
|
||||
}
|
||||
|
||||
CmdPalRpcServer::CmdPalRpcServer() = default;
|
||||
|
||||
CmdPalRpcServer::~CmdPalRpcServer()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
void CmdPalRpcServer::Start()
|
||||
{
|
||||
if (m_running.exchange(true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_worker = std::thread([this]() { Run(); });
|
||||
}
|
||||
|
||||
void CmdPalRpcServer::Stop()
|
||||
{
|
||||
if (!m_running.exchange(false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger the server loop to exit by briefly connecting to the pipe.
|
||||
for (int attempt = 0; attempt < 5; ++attempt)
|
||||
{
|
||||
auto pipe = CreateFileW(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (pipe != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(pipe);
|
||||
break;
|
||||
}
|
||||
|
||||
auto error = GetLastError();
|
||||
if (error == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
else if (error == ERROR_PIPE_BUSY)
|
||||
{
|
||||
WaitNamedPipeW(PIPE_NAME, 200);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_worker.joinable())
|
||||
{
|
||||
m_worker.join();
|
||||
}
|
||||
}
|
||||
|
||||
void CmdPalRpcServer::Run()
|
||||
{
|
||||
while (m_running.load())
|
||||
{
|
||||
HANDLE pipe = CreateNamedPipeW(PIPE_NAME,
|
||||
PIPE_ACCESS_DUPLEX,
|
||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
||||
PIPE_UNLIMITED_INSTANCES,
|
||||
64 * 1024,
|
||||
64 * 1024,
|
||||
0,
|
||||
nullptr);
|
||||
|
||||
if (pipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Logger::error(L"CmdPalRpcServer: failed to create pipe. Error: {}", GetLastError());
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOL connected = ConnectNamedPipe(pipe, nullptr) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
|
||||
if (!connected)
|
||||
{
|
||||
CloseHandle(pipe);
|
||||
continue;
|
||||
}
|
||||
|
||||
HandleClient(pipe);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdPalRpcServer::HandleClient(HANDLE pipe)
|
||||
{
|
||||
auto closePipe = wil::scope_exit([pipe]() {
|
||||
FlushFileBuffers(pipe);
|
||||
DisconnectNamedPipe(pipe);
|
||||
CloseHandle(pipe);
|
||||
});
|
||||
|
||||
while (m_running.load())
|
||||
{
|
||||
uint32_t length = 0;
|
||||
DWORD bytesRead = 0;
|
||||
if (!ReadFile(pipe, &length, sizeof(length), &bytesRead, nullptr) || bytesRead == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::string payload;
|
||||
payload.resize(length);
|
||||
DWORD totalRead = 0;
|
||||
while (totalRead < length)
|
||||
{
|
||||
DWORD chunkRead = 0;
|
||||
if (!ReadFile(pipe, payload.data() + totalRead, length - totalRead, &chunkRead, nullptr) || chunkRead == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
totalRead += chunkRead;
|
||||
}
|
||||
|
||||
auto response = ProcessMessage(payload);
|
||||
uint32_t responseLength = static_cast<uint32_t>(response.size());
|
||||
DWORD bytesWritten = 0;
|
||||
if (!WriteFile(pipe, &responseLength, sizeof(responseLength), &bytesWritten, nullptr))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (responseLength > 0)
|
||||
{
|
||||
DWORD totalWritten = 0;
|
||||
while (totalWritten < responseLength)
|
||||
{
|
||||
DWORD chunkWritten = 0;
|
||||
if (!WriteFile(pipe, response.data() + totalWritten, responseLength - totalWritten, &chunkWritten, nullptr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
totalWritten += chunkWritten;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string CmdPalRpcServer::ProcessMessage(const std::string& message)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto request = JsonObject::Parse(ToHString(message));
|
||||
std::wstring id;
|
||||
if (auto idValue = request.TryLookup(L"id"))
|
||||
{
|
||||
if (idValue.ValueType() == JsonValueType::String)
|
||||
{
|
||||
id = idValue.GetString().c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (!request.HasKey(L"module") || !request.HasKey(L"method"))
|
||||
{
|
||||
return BuildErrorResponse(id, L"Bad.Request", L"Missing module or method");
|
||||
}
|
||||
|
||||
auto moduleName = request.Lookup(L"module").GetString();
|
||||
auto methodName = request.Lookup(L"method").GetString();
|
||||
|
||||
if (moduleName == L"core" && methodName == L"listModules")
|
||||
{
|
||||
return ListModulesResponse(id);
|
||||
}
|
||||
|
||||
return ProcessModuleRequest(request, id);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return BuildErrorResponse(L"", L"Bad.Request", L"Malformed JSON");
|
||||
}
|
||||
}
|
||||
|
||||
std::string CmdPalRpcServer::ProcessModuleRequest(const JsonObject& request, const std::wstring& id)
|
||||
{
|
||||
std::wstring moduleKey = request.Lookup(L"module").GetString().c_str();
|
||||
auto methodName = request.Lookup(L"method").GetString();
|
||||
|
||||
auto& loadedModules = modules();
|
||||
auto moduleIt = loadedModules.find(moduleKey);
|
||||
if (moduleIt == loadedModules.end())
|
||||
{
|
||||
return BuildErrorResponse(id, L"Module.NotFound", L"Requested module is not available");
|
||||
}
|
||||
|
||||
std::wstring params = L"{}";
|
||||
if (auto paramsValue = request.TryLookup(L"params"))
|
||||
{
|
||||
params = paramsValue.Stringify().c_str();
|
||||
}
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
std::wstring moduleResponse;
|
||||
try
|
||||
{
|
||||
moduleResponse = moduleIt->second->invoke(methodName.c_str(), params.c_str());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return BuildErrorResponse(id, L"Module.Failure", L"Module threw an exception");
|
||||
}
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count();
|
||||
|
||||
JsonObject response;
|
||||
if (!id.empty())
|
||||
{
|
||||
response.SetNamedValue(L"id", JsonValue::CreateStringValue(id));
|
||||
}
|
||||
response.SetNamedValue(L"elapsedMs", JsonValue::CreateNumberValue(static_cast<double>(elapsed)));
|
||||
|
||||
try
|
||||
{
|
||||
auto moduleJsonValue = JsonValue::Parse(winrt::hstring(moduleResponse.c_str()));
|
||||
bool ok = true;
|
||||
if (moduleJsonValue.ValueType() == JsonValueType::Object)
|
||||
{
|
||||
auto moduleObject = moduleJsonValue.GetObject();
|
||||
if (moduleObject.HasKey(L"ok"))
|
||||
{
|
||||
ok = moduleObject.GetNamedBoolean(L"ok");
|
||||
}
|
||||
}
|
||||
|
||||
response.SetNamedValue(L"ok", JsonValue::CreateBooleanValue(ok));
|
||||
if (ok)
|
||||
{
|
||||
response.SetNamedValue(L"result", moduleJsonValue);
|
||||
}
|
||||
else if (moduleJsonValue.ValueType() == JsonValueType::Object)
|
||||
{
|
||||
auto moduleObject = moduleJsonValue.GetObject();
|
||||
if (moduleObject.HasKey(L"error"))
|
||||
{
|
||||
response.SetNamedValue(L"error", moduleObject.Lookup(L"error"));
|
||||
}
|
||||
else
|
||||
{
|
||||
response.SetNamedValue(L"error", moduleJsonValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.SetNamedValue(L"error", moduleJsonValue);
|
||||
}
|
||||
|
||||
return ToUtf8(response.Stringify());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return BuildErrorResponse(id, L"Module.Failure", L"Module returned invalid JSON");
|
||||
}
|
||||
}
|
||||
|
||||
std::string CmdPalRpcServer::ListModulesResponse(const std::wstring& id)
|
||||
{
|
||||
JsonObject response;
|
||||
if (!id.empty())
|
||||
{
|
||||
response.SetNamedValue(L"id", JsonValue::CreateStringValue(id));
|
||||
}
|
||||
response.SetNamedValue(L"ok", JsonValue::CreateBooleanValue(true));
|
||||
|
||||
JsonArray modulesArray;
|
||||
for (auto& entry : modules())
|
||||
{
|
||||
try
|
||||
{
|
||||
auto describeJson = JsonValue::Parse(winrt::hstring(entry.second->describe()));
|
||||
if (describeJson.ValueType() == JsonValueType::Object)
|
||||
{
|
||||
modulesArray.Append(describeJson.GetObject());
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
JsonObject fallback;
|
||||
fallback.SetNamedValue(L"name", JsonValue::CreateStringValue(entry.first));
|
||||
modulesArray.Append(fallback);
|
||||
}
|
||||
}
|
||||
|
||||
JsonObject payload;
|
||||
payload.SetNamedValue(L"modules", modulesArray);
|
||||
response.SetNamedValue(L"result", payload);
|
||||
|
||||
return ToUtf8(response.Stringify());
|
||||
}
|
||||
|
||||
std::string CmdPalRpcServer::BuildErrorResponse(const std::wstring& id, const std::wstring_view code, const std::wstring_view message)
|
||||
{
|
||||
JsonObject response;
|
||||
if (!id.empty())
|
||||
{
|
||||
response.SetNamedValue(L"id", JsonValue::CreateStringValue(id));
|
||||
}
|
||||
response.SetNamedValue(L"ok", JsonValue::CreateBooleanValue(false));
|
||||
JsonObject error;
|
||||
error.SetNamedValue(L"code", JsonValue::CreateStringValue(winrt::hstring(code.data(), static_cast<uint32_t>(code.size()))));
|
||||
error.SetNamedValue(L"message", JsonValue::CreateStringValue(winrt::hstring(message.data(), static_cast<uint32_t>(message.size()))));
|
||||
response.SetNamedValue(L"error", error);
|
||||
return ToUtf8(response.Stringify());
|
||||
}
|
||||
32
src/runner/cmdpal_rpc_server.h
Normal file
32
src/runner/cmdpal_rpc_server.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <winrt/Windows.Data.Json.h>
|
||||
#include <Windows.h>
|
||||
|
||||
class CmdPalRpcServer
|
||||
{
|
||||
public:
|
||||
CmdPalRpcServer();
|
||||
~CmdPalRpcServer();
|
||||
|
||||
CmdPalRpcServer(const CmdPalRpcServer&) = delete;
|
||||
CmdPalRpcServer& operator=(const CmdPalRpcServer&) = delete;
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
void Run();
|
||||
void HandleClient(HANDLE pipe);
|
||||
std::string ProcessMessage(const std::string& message);
|
||||
std::string ProcessModuleRequest(const winrt::Windows::Data::Json::JsonObject& request, const std::wstring& id);
|
||||
std::string ListModulesResponse(const std::wstring& id);
|
||||
std::string BuildErrorResponse(const std::wstring& id, const std::wstring_view code, const std::wstring_view message);
|
||||
|
||||
std::atomic_bool m_running{ false };
|
||||
std::thread m_worker;
|
||||
};
|
||||
@@ -35,7 +35,8 @@
|
||||
#include <Psapi.h>
|
||||
#include <RestartManager.h>
|
||||
#include "centralized_kb_hook.h"
|
||||
#include "centralized_hotkeys.h"
|
||||
#include "centralized_hotkeys.h"
|
||||
#include "cmdpal_rpc_server.h"
|
||||
|
||||
#if _DEBUG && _WIN64
|
||||
#include "unhandled_exception_handler.h"
|
||||
@@ -93,10 +94,10 @@ void open_menu_from_another_instance(std::optional<std::string> settings_window)
|
||||
SetForegroundWindow(hwnd_main); // Bring the settings window to the front
|
||||
}
|
||||
|
||||
int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow, bool openOobe, bool openScoobe, bool showRestartNotificationAfterUpdate)
|
||||
{
|
||||
Logger::info("Runner is starting. Elevated={} openOobe={} openScoobe={} showRestartNotificationAfterUpdate={}", isProcessElevated, openOobe, openScoobe, showRestartNotificationAfterUpdate);
|
||||
DPIAware::EnableDPIAwarenessForThisProcess();
|
||||
int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow, bool openOobe, bool openScoobe, bool showRestartNotificationAfterUpdate)
|
||||
{
|
||||
Logger::info("Runner is starting. Elevated={} openOobe={} openScoobe={} showRestartNotificationAfterUpdate={}", isProcessElevated, openOobe, openScoobe, showRestartNotificationAfterUpdate);
|
||||
DPIAware::EnableDPIAwarenessForThisProcess();
|
||||
|
||||
#if _DEBUG && _WIN64
|
||||
//Global error handlers to diagnose errors.
|
||||
@@ -104,9 +105,10 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||
//init_global_error_handlers();
|
||||
#endif
|
||||
Trace::RegisterProvider();
|
||||
start_tray_icon(isProcessElevated);
|
||||
set_tray_icon_visible(get_general_settings().showSystemTrayIcon);
|
||||
CentralizedKeyboardHook::Start();
|
||||
start_tray_icon(isProcessElevated);
|
||||
set_tray_icon_visible(get_general_settings().showSystemTrayIcon);
|
||||
CentralizedKeyboardHook::Start();
|
||||
CmdPalRpcServer cmdPalRpcServer;
|
||||
|
||||
int result = -1;
|
||||
try
|
||||
@@ -207,8 +209,9 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// Start initial powertoys
|
||||
start_enabled_powertoys();
|
||||
// Start initial powertoys
|
||||
start_enabled_powertoys();
|
||||
cmdPalRpcServer.Start();
|
||||
std::wstring product_version = get_product_version();
|
||||
Trace::EventLaunch(product_version, isProcessElevated);
|
||||
PTSettingsHelper::save_last_version_run(product_version);
|
||||
|
||||
@@ -65,7 +65,8 @@
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="powertoy_module.cpp" />
|
||||
<ClCompile Include="powertoy_module.cpp" />
|
||||
<ClCompile Include="cmdpal_rpc_server.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="restart_elevated.cpp" />
|
||||
<ClCompile Include="centralized_kb_hook.cpp" />
|
||||
@@ -87,7 +88,8 @@
|
||||
<ClInclude Include="centralized_kb_hook.h" />
|
||||
<ClInclude Include="settings_telemetry.h" />
|
||||
<ClInclude Include="UpdateUtils.h" />
|
||||
<ClInclude Include="powertoy_module.h" />
|
||||
<ClInclude Include="powertoy_module.h" />
|
||||
<ClInclude Include="cmdpal_rpc_server.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="restart_elevated.h" />
|
||||
<ClInclude Include="settings_window.h" />
|
||||
@@ -175,4 +177,4 @@
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user