mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-07-01 07:59:36 +02:00
Compare commits
47 Commits
copilot/cr
...
autoUpgrad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df1d6ea7e0 | ||
|
|
31e30280de | ||
|
|
5074588c9a | ||
|
|
df7a41b457 | ||
|
|
b0b073f088 | ||
|
|
c56258d2d3 | ||
|
|
236c241107 | ||
|
|
d6f61c8439 | ||
|
|
b387bbffdd | ||
|
|
5003c6c758 | ||
|
|
b2ef4c85bc | ||
|
|
24d56f0524 | ||
|
|
0089de33bd | ||
|
|
3e2914a0b2 | ||
|
|
3554f0884b | ||
|
|
ad60090096 | ||
|
|
de6a609d16 | ||
|
|
243255ecea | ||
|
|
1e1bd07087 | ||
|
|
32b4080007 | ||
|
|
47c1fb5418 | ||
|
|
8ee3d64667 | ||
|
|
51c9bc4930 | ||
|
|
ddff66c088 | ||
|
|
e28ed8a566 | ||
|
|
4f693778f2 | ||
|
|
e1ad13ab34 | ||
|
|
cea0497bb9 | ||
|
|
fd5be6d04e | ||
|
|
4dfdf46e0d | ||
|
|
1c4ecc23c6 | ||
|
|
5888f6eb7f | ||
|
|
152f64151b | ||
|
|
76b773b016 | ||
|
|
0da5602f68 | ||
|
|
565094abbe | ||
|
|
1314f68602 | ||
|
|
fbad0dce9c | ||
|
|
36a5b77e6c | ||
|
|
4ce451edd0 | ||
|
|
42924e71c7 | ||
|
|
addebb8126 | ||
|
|
3b6453c932 | ||
|
|
2c97e04019 | ||
|
|
d27594c4f7 | ||
|
|
ac28b1c29f | ||
|
|
ee70b3ceca |
26
.github/actions/spell-check/allow/code.txt
vendored
26
.github/actions/spell-check/allow/code.txt
vendored
@@ -19,6 +19,7 @@ OLIVEGREEN
|
||||
PALEBLUE
|
||||
PArgb
|
||||
Pbgra
|
||||
SRGBTo
|
||||
WHITEONBLACK
|
||||
|
||||
|
||||
@@ -48,7 +49,6 @@ nupkg
|
||||
petabyte
|
||||
resw
|
||||
resx
|
||||
runtimeconfig
|
||||
srt
|
||||
Stereolithography
|
||||
terabyte
|
||||
@@ -332,6 +332,7 @@ REGSTR
|
||||
INVOKEIDLIST
|
||||
MEMORYSTATUSEX
|
||||
ABE
|
||||
Mdt
|
||||
HTCAPTION
|
||||
POSCHANGED
|
||||
QUERYPOS
|
||||
@@ -341,6 +342,29 @@ WINEVENTPROC
|
||||
WORKERW
|
||||
FULLSCREENAPP
|
||||
|
||||
# COM/WinRT interface prefixes and type fragments
|
||||
BAlt
|
||||
BShift
|
||||
Cmanifest
|
||||
Cmodule
|
||||
Cuuid
|
||||
Dng
|
||||
IApplication
|
||||
IDisposable
|
||||
IEnum
|
||||
IFolder
|
||||
IInitialize
|
||||
IMemory
|
||||
IOle
|
||||
ipreview
|
||||
IProperty
|
||||
IShell
|
||||
ithumbnail
|
||||
IVirtual
|
||||
|
||||
# Test frameworks
|
||||
MSTEST
|
||||
|
||||
# PowerRename metadata pattern abbreviations (used in tests and regex patterns)
|
||||
DDDD
|
||||
FFF
|
||||
|
||||
2
.github/actions/spell-check/allow/names.txt
vendored
2
.github/actions/spell-check/allow/names.txt
vendored
@@ -178,7 +178,9 @@ Taras
|
||||
TBM
|
||||
Teutsch
|
||||
tilovell
|
||||
traies
|
||||
Triet
|
||||
udit
|
||||
urnotdfs
|
||||
vednig
|
||||
waaverecords
|
||||
|
||||
2
.github/actions/spell-check/excludes.txt
vendored
2
.github/actions/spell-check/excludes.txt
vendored
@@ -140,8 +140,6 @@
|
||||
^tools/project_template/ModuleTemplate/resource\.h$
|
||||
^tools/Verification scripts/Check preview handler registration\.ps1$
|
||||
ignore$
|
||||
^src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/.*$
|
||||
^src/common/CalculatorEngineCommon/exprtk\.hpp$
|
||||
src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownImagesPage.cs
|
||||
^src/modules/powerrename/unittests/testdata/avif_test\.avif$
|
||||
^src/modules/powerrename/unittests/testdata/heif_test\.heic$
|
||||
|
||||
43
.github/actions/spell-check/expect.txt
vendored
43
.github/actions/spell-check/expect.txt
vendored
@@ -35,6 +35,7 @@ Allman
|
||||
ALLOWUNDO
|
||||
ALLVIEW
|
||||
ALPHATYPE
|
||||
altkey
|
||||
AModifier
|
||||
amr
|
||||
ANDSCANS
|
||||
@@ -52,6 +53,7 @@ Apm
|
||||
APPBARDATA
|
||||
APPEXECLINK
|
||||
APPLICATIONFRAMEHOST
|
||||
apphost
|
||||
appmanifest
|
||||
APPMODEL
|
||||
APPNAME
|
||||
@@ -85,6 +87,7 @@ AUTOCHECKBOX
|
||||
AUTOHIDE
|
||||
AUTOHSCROLL
|
||||
AUTOMATIONPROPERTIES
|
||||
autopf
|
||||
AUTORADIOBUTTON
|
||||
Autorun
|
||||
AUTOTICKS
|
||||
@@ -239,6 +242,7 @@ CPower
|
||||
cpptools
|
||||
cppvsdbg
|
||||
cppwinrt
|
||||
createallsubdirs
|
||||
createdump
|
||||
CREATEPROCESS
|
||||
CREATESCHEDULEDTASK
|
||||
@@ -275,6 +279,7 @@ CYSMICON
|
||||
CYVIRTUALSCREEN
|
||||
Dac
|
||||
dacl
|
||||
DArchitectures
|
||||
datareader
|
||||
datatracker
|
||||
Dayof
|
||||
@@ -351,6 +356,7 @@ dlib
|
||||
dllhost
|
||||
dllmain
|
||||
Dmdo
|
||||
DMy
|
||||
DNLEN
|
||||
DONOTROUND
|
||||
DONTVALIDATEPATH
|
||||
@@ -455,6 +461,9 @@ fdx
|
||||
FErase
|
||||
fesf
|
||||
FFFF
|
||||
fffffffzzz
|
||||
FInc
|
||||
FFh
|
||||
Figma
|
||||
FILEEXPLORER
|
||||
FILEFLAGS
|
||||
@@ -467,6 +476,7 @@ FILEMUSTEXIST
|
||||
FILEOP
|
||||
FILEOPENDIALOGOPTIONS
|
||||
FILEOS
|
||||
filesandordirs
|
||||
FILESUBTYPE
|
||||
FILESYSPATH
|
||||
Filetime
|
||||
@@ -576,6 +586,7 @@ HIBYTE
|
||||
hicon
|
||||
HIDEWINDOW
|
||||
Hif
|
||||
highcontrast
|
||||
highlightbackground
|
||||
highlightthickness
|
||||
HIMAGELIST
|
||||
@@ -649,6 +660,7 @@ IEXPLORE
|
||||
IFACEMETHOD
|
||||
IFACEMETHODIMP
|
||||
IGNOREUNKNOWN
|
||||
ignoreversion
|
||||
IGo
|
||||
iid
|
||||
Iindex
|
||||
@@ -699,6 +711,8 @@ ipcmanager
|
||||
IPREVIEW
|
||||
irprops
|
||||
isbi
|
||||
ISCC
|
||||
isdl
|
||||
iss
|
||||
issecret
|
||||
ISSEPARATOR
|
||||
@@ -713,6 +727,7 @@ jobject
|
||||
JOBOBJECT
|
||||
jpe
|
||||
jpnime
|
||||
jrsoftware
|
||||
Jsons
|
||||
jsonval
|
||||
jxr
|
||||
@@ -849,6 +864,8 @@ MDL
|
||||
mdtext
|
||||
mdtxt
|
||||
mdwn
|
||||
measuretool
|
||||
mccs
|
||||
meme
|
||||
memicmp
|
||||
MENUITEMINFO
|
||||
@@ -892,6 +909,7 @@ MONITORINFOEX
|
||||
MONITORINFOEXW
|
||||
monitorinfof
|
||||
MOUSEACTIVATE
|
||||
mousecrosshairs
|
||||
MOUSEDATA
|
||||
MOUSEEVENTF
|
||||
MOUSEHWHEEL
|
||||
@@ -923,12 +941,15 @@ mstsc
|
||||
msvcp
|
||||
MT
|
||||
MTND
|
||||
multimonitor
|
||||
MULTIPLEUSE
|
||||
multizone
|
||||
muxc
|
||||
mvvm
|
||||
MVVMTK
|
||||
MWBEx
|
||||
mycompany
|
||||
myextension
|
||||
MYICON
|
||||
myorg
|
||||
myrepo
|
||||
@@ -1016,6 +1037,7 @@ NORMALDISPLAY
|
||||
NORMALUSER
|
||||
NOSEARCH
|
||||
NOSENDCHANGING
|
||||
notdefault
|
||||
NOTHOUSANDS
|
||||
NOTICKS
|
||||
NOTIFICATIONSDLL
|
||||
@@ -1106,6 +1128,7 @@ PCIDLIST
|
||||
PCTSTR
|
||||
PCWSTR
|
||||
PDEVMODE
|
||||
PDFs
|
||||
pdisp
|
||||
PDLL
|
||||
pdo
|
||||
@@ -1154,6 +1177,10 @@ Pokedex
|
||||
Popups
|
||||
POPUPWINDOW
|
||||
POSITIONITEM
|
||||
powerocr
|
||||
POWERBROADCAST
|
||||
powerdisplay
|
||||
POWERDISPLAYMODULEINTERFACE
|
||||
POWERRENAMECONTEXTMENU
|
||||
powerrenameinput
|
||||
POWERRENAMETEST
|
||||
@@ -1242,6 +1269,7 @@ Quarternary
|
||||
QUERYENDSESSION
|
||||
QUERYOPEN
|
||||
QUEUESYNC
|
||||
quicklinks
|
||||
QUNS
|
||||
RAII
|
||||
RAlt
|
||||
@@ -1262,6 +1290,7 @@ recents
|
||||
RECTDESTINATION
|
||||
rectp
|
||||
RECTSOURCE
|
||||
recursesubdirs
|
||||
recyclebin
|
||||
Redist
|
||||
Reencode
|
||||
@@ -1329,6 +1358,7 @@ rundll
|
||||
rungameid
|
||||
RUNLEVEL
|
||||
runtimeclass
|
||||
runtimeconfig
|
||||
runtimepack
|
||||
ruuid
|
||||
rvm
|
||||
@@ -1516,8 +1546,12 @@ STYLECHANGING
|
||||
subkeys
|
||||
sublang
|
||||
SUBMODULEUPDATE
|
||||
subresource
|
||||
suntimes
|
||||
swp
|
||||
sug
|
||||
Superbar
|
||||
SUPPRESSMSGBOXES
|
||||
sut
|
||||
svchost
|
||||
SVGIn
|
||||
@@ -1548,6 +1582,7 @@ sysmenu
|
||||
systemai
|
||||
SYSTEMAPPS
|
||||
SYSTEMMODAL
|
||||
systemroot
|
||||
SYSTEMTIME
|
||||
TARGETAPPHEADER
|
||||
targetentrypoint
|
||||
@@ -1583,6 +1618,7 @@ TILEDWINDOW
|
||||
TILLSON
|
||||
timedate
|
||||
timediff
|
||||
timespan
|
||||
timeutil
|
||||
TITLEBARINFO
|
||||
Titlecase
|
||||
@@ -1640,6 +1676,7 @@ uncompilable
|
||||
UNCPRIORITY
|
||||
UNDNAME
|
||||
UNICODETEXT
|
||||
uninsdeletekey
|
||||
uninstalls
|
||||
Uniquifies
|
||||
unitconverter
|
||||
@@ -1655,6 +1692,7 @@ UOI
|
||||
UPDATENOW
|
||||
updown
|
||||
UPGRADINGPRODUCTCODE
|
||||
upserts
|
||||
Uptool
|
||||
urld
|
||||
Usb
|
||||
@@ -1685,6 +1723,7 @@ VERIFYCONTEXT
|
||||
VERSIONINFO
|
||||
VERTRES
|
||||
VERTSIZE
|
||||
VERYSILENT
|
||||
VFT
|
||||
vget
|
||||
vgetq
|
||||
@@ -1733,11 +1772,11 @@ wdm
|
||||
wdp
|
||||
wdupenv
|
||||
webbrowsers
|
||||
webdev
|
||||
webpage
|
||||
websites
|
||||
wekyb
|
||||
wgpocpl
|
||||
WIC
|
||||
wic
|
||||
wifi
|
||||
winapi
|
||||
@@ -2135,7 +2174,7 @@ nodiscard
|
||||
nologo
|
||||
nomove
|
||||
nosize
|
||||
notopmost
|
||||
NOTOPMOST
|
||||
Notupdated
|
||||
notwindows
|
||||
nowarn
|
||||
|
||||
9
.github/actions/spell-check/patterns.txt
vendored
9
.github/actions/spell-check/patterns.txt
vendored
@@ -191,15 +191,6 @@ aka\.ms/[a-zA-Z0-9]+
|
||||
# #pragma lib
|
||||
^\s*#pragma comment\(lib, ".*?"\)
|
||||
|
||||
# UnitTests
|
||||
\[DataRow\(.*\)\]
|
||||
|
||||
# AdditionalDependencies
|
||||
<AdditionalDependencies>.*<
|
||||
|
||||
# the last line of mimetype="application/x-microsoft.net.object.bytearray.base64" things in .resx files
|
||||
^\s*[-a-zA-Z=;:/0-9+]*[-a-zA-Z;:/0-9+][-a-zA-Z=;:/0-9+]*=$
|
||||
|
||||
RegExp\(@?([`'"]).*?\g{-1}\)|(?:escapes|regEx):\s*(?:/.*/|([`'"]).*?\g{-1})|return/.*?/
|
||||
|
||||
# Questionably acceptable forms of `in to`
|
||||
|
||||
24
.github/policies/resourceManagement.yml
vendored
24
.github/policies/resourceManagement.yml
vendored
@@ -233,6 +233,30 @@ configuration:
|
||||
- addReply:
|
||||
reply: Hi! Thanks for making us aware of the problem. We raised the issue with our internal localization team. This issue should be fixed hopefully in the next version of PowerToys.
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Issue_Comment
|
||||
- commentContains:
|
||||
pattern: '\/need-monitor-info'
|
||||
isRegex: True
|
||||
- hasLabel:
|
||||
label: Product-Cursor Wrap
|
||||
- or:
|
||||
- activitySenderHasAssociation:
|
||||
association: Owner
|
||||
- activitySenderHasAssociation:
|
||||
association: Member
|
||||
- activitySenderHasAssociation:
|
||||
association: Collaborator
|
||||
then:
|
||||
- removeLabel:
|
||||
label: Needs-Triage
|
||||
- removeLabel:
|
||||
label: Needs-Team-Response
|
||||
- addLabel:
|
||||
label: Needs-Author-Feedback
|
||||
- addReply:
|
||||
reply: "To help debug your layout, please run [this script](https://github.com/microsoft/PowerToys/blob/main/src/modules/MouseUtils/CursorWrap/CursorWrapTests/Capture-MonitorLayout.ps1) and attach the generated JSON output to this thread.\n\nThis allows us to better understand the issue and investigate potential fixes."
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Issue_Comment
|
||||
- commentContains:
|
||||
|
||||
144
.github/scripts/generate-monaco-languages.js
vendored
144
.github/scripts/generate-monaco-languages.js
vendored
@@ -1,144 +0,0 @@
|
||||
/**
|
||||
* generate-monaco-languages.js
|
||||
*
|
||||
* Headless replacement for the manual generateLanguagesJson.html workflow.
|
||||
* Serves the Monaco directory on a local HTTP server, then uses Playwright
|
||||
* to open generateLanguagesJson.html and capture the generated JSON.
|
||||
*
|
||||
* Monaco's AMD loader requires a real browser DOM, so we use Playwright
|
||||
* instead of trying to load it in Node.js directly.
|
||||
*
|
||||
* Usage: node generate-monaco-languages.js <path-to-src/Monaco>
|
||||
*
|
||||
* Prerequisites: npx playwright install chromium
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const http = require("http");
|
||||
|
||||
const monacoDir = process.argv[2];
|
||||
if (!monacoDir) {
|
||||
console.error("Usage: node generate-monaco-languages.js <monaco-dir>");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const absMonacoDir = path.resolve(monacoDir);
|
||||
const outputPath = path.join(absMonacoDir, "monaco_languages.json");
|
||||
const htmlPath = path.join(absMonacoDir, "generateLanguagesJson.html");
|
||||
|
||||
if (!fs.existsSync(htmlPath)) {
|
||||
console.error(`generateLanguagesJson.html not found at: ${htmlPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// MIME types for serving Monaco files
|
||||
const MIME_TYPES = {
|
||||
".html": "text/html",
|
||||
".js": "application/javascript",
|
||||
".css": "text/css",
|
||||
".json": "application/json",
|
||||
".ttf": "font/ttf",
|
||||
".woff": "font/woff",
|
||||
".woff2": "font/woff2",
|
||||
".svg": "image/svg+xml",
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a simple static file server rooted at absMonacoDir.
|
||||
*/
|
||||
function createServer() {
|
||||
return http.createServer((req, res) => {
|
||||
const url = new URL(req.url, "http://localhost");
|
||||
// Resolve the file path relative to absMonacoDir, preventing path traversal
|
||||
const requestedPath = decodeURIComponent(url.pathname);
|
||||
const filePath = path.resolve(absMonacoDir, requestedPath.replace(/^\/+/, ""));
|
||||
|
||||
// Ensure the resolved path is within absMonacoDir (case-insensitive on Windows)
|
||||
const normalizedFile = process.platform === "win32" ? filePath.toLowerCase() : filePath;
|
||||
const normalizedBase = process.platform === "win32" ? absMonacoDir.toLowerCase() : absMonacoDir;
|
||||
if (!normalizedFile.startsWith(normalizedBase + path.sep) && normalizedFile !== normalizedBase) {
|
||||
res.writeHead(403);
|
||||
res.end("Forbidden");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(filePath) || fs.statSync(filePath).isDirectory()) {
|
||||
res.writeHead(404);
|
||||
res.end("Not found");
|
||||
return;
|
||||
}
|
||||
|
||||
const ext = path.extname(filePath).toLowerCase();
|
||||
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
||||
|
||||
const content = fs.readFileSync(filePath);
|
||||
res.writeHead(200, { "Content-Type": contentType });
|
||||
res.end(content);
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// Start local HTTP server
|
||||
const server = createServer();
|
||||
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||
const port = server.address().port;
|
||||
const baseUrl = `http://127.0.0.1:${port}`;
|
||||
console.log(`Local server started at ${baseUrl}`);
|
||||
|
||||
let browser;
|
||||
try {
|
||||
// Launch Playwright browser
|
||||
const { chromium } = require("playwright");
|
||||
browser = await chromium.launch({ headless: true });
|
||||
const context = await browser.newContext({
|
||||
// Accept downloads so we can capture the generated file
|
||||
acceptDownloads: true,
|
||||
});
|
||||
const page = await context.newPage();
|
||||
|
||||
// The generateLanguagesJson.html auto-triggers a download of the JSON.
|
||||
// We intercept that download event to capture the content.
|
||||
const downloadPromise = page.waitForEvent("download", { timeout: 30000 });
|
||||
|
||||
console.log("Loading generateLanguagesJson.html in headless browser...");
|
||||
await page.goto(`${baseUrl}/generateLanguagesJson.html`, {
|
||||
waitUntil: "networkidle",
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
// Wait for the download to be triggered
|
||||
const download = await downloadPromise;
|
||||
console.log(`Download triggered: ${download.suggestedFilename()}`);
|
||||
|
||||
// Save the downloaded file
|
||||
const downloadPath = await download.path();
|
||||
const content = fs.readFileSync(downloadPath, "utf-8");
|
||||
|
||||
// Validate the JSON before writing
|
||||
const parsed = JSON.parse(content);
|
||||
if (!parsed.list || !Array.isArray(parsed.list) || parsed.list.length === 0) {
|
||||
throw new Error(
|
||||
"Generated JSON is invalid: missing or empty 'list' property"
|
||||
);
|
||||
}
|
||||
|
||||
// Write to output
|
||||
fs.writeFileSync(outputPath, content, "utf-8");
|
||||
console.log(
|
||||
`monaco_languages.json written with ${parsed.list.length} languages.`
|
||||
);
|
||||
} finally {
|
||||
if (browser) {
|
||||
await browser.close();
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error("Error:", err.message || err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,328 +0,0 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Validates that a Monaco Editor update was performed correctly.
|
||||
|
||||
.DESCRIPTION
|
||||
Runs a series of checks against the Monaco Editor files in the repository
|
||||
to ensure the update is valid and no regressions were introduced.
|
||||
|
||||
Tests:
|
||||
- loader.js exists and contains version info
|
||||
- monaco_languages.json is valid JSON with expected structure
|
||||
- All expected built-in Monaco languages are present
|
||||
- All PowerToys custom languages are registered
|
||||
- Custom language extension mappings are present
|
||||
- Monaco directory structure is intact
|
||||
- No empty/corrupt core files
|
||||
|
||||
.PARAMETER RepoRoot
|
||||
The root of the PowerToys repository. Defaults to the repo root
|
||||
relative to this script.
|
||||
|
||||
.EXAMPLE
|
||||
./validate-monaco-update.tests.ps1
|
||||
./validate-monaco-update.tests.ps1 -RepoRoot "C:\src\PowerToys"
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter()]
|
||||
[string]$RepoRoot
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if (-not $RepoRoot) {
|
||||
$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot ".." ".." "..")).Path
|
||||
}
|
||||
|
||||
$monacoDir = Join-Path $RepoRoot "src" "Monaco"
|
||||
$monacoSrcDir = Join-Path $monacoDir "monacoSRC"
|
||||
$minDir = Join-Path $monacoSrcDir "min"
|
||||
$loaderJsPath = Join-Path $minDir "vs" "loader.js"
|
||||
$languagesJsonPath = Join-Path $monacoDir "monaco_languages.json"
|
||||
$specialLangsPath = Join-Path $monacoDir "monacoSpecialLanguages.js"
|
||||
$customLangsDir = Join-Path $monacoDir "customLanguages"
|
||||
|
||||
$testsPassed = 0
|
||||
$testsFailed = 0
|
||||
$testResults = @()
|
||||
|
||||
function Assert-Test {
|
||||
param(
|
||||
[string]$Name,
|
||||
[scriptblock]$Test
|
||||
)
|
||||
|
||||
try {
|
||||
$result = & $Test
|
||||
if ($result -eq $false) {
|
||||
throw "Assertion returned false"
|
||||
}
|
||||
$script:testsPassed++
|
||||
$script:testResults += [PSCustomObject]@{ Name = $Name; Status = "PASS"; Error = $null }
|
||||
Write-Host " [PASS] $Name" -ForegroundColor Green
|
||||
}
|
||||
catch {
|
||||
$script:testsFailed++
|
||||
$script:testResults += [PSCustomObject]@{ Name = $Name; Status = "FAIL"; Error = $_.Exception.Message }
|
||||
Write-Host " [FAIL] $Name" -ForegroundColor Red
|
||||
Write-Host " $($_.Exception.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "=== Monaco Editor Update Validation ===" -ForegroundColor Cyan
|
||||
Write-Host "Repository root: $RepoRoot"
|
||||
Write-Host ""
|
||||
|
||||
# ─── Test Group 1: Directory Structure ────────────────────────────────
|
||||
Write-Host "--- Directory Structure ---" -ForegroundColor Yellow
|
||||
|
||||
Assert-Test "Monaco directory exists" {
|
||||
Test-Path $monacoDir
|
||||
}
|
||||
|
||||
Assert-Test "monacoSRC directory exists" {
|
||||
Test-Path $monacoSrcDir
|
||||
}
|
||||
|
||||
Assert-Test "min directory exists" {
|
||||
Test-Path $minDir
|
||||
}
|
||||
|
||||
Assert-Test "vs subdirectory exists" {
|
||||
Test-Path (Join-Path $minDir "vs")
|
||||
}
|
||||
|
||||
Assert-Test "editor directory exists" {
|
||||
Test-Path (Join-Path $minDir "vs" "editor")
|
||||
}
|
||||
|
||||
Assert-Test "basic-languages directory exists" {
|
||||
Test-Path (Join-Path $minDir "vs" "basic-languages")
|
||||
}
|
||||
|
||||
Assert-Test "base directory exists" {
|
||||
Test-Path (Join-Path $minDir "vs" "base")
|
||||
}
|
||||
|
||||
Assert-Test "language directory exists" {
|
||||
Test-Path (Join-Path $minDir "vs" "language")
|
||||
}
|
||||
|
||||
Assert-Test "customLanguages directory exists" {
|
||||
Test-Path $customLangsDir
|
||||
}
|
||||
|
||||
# ─── Test Group 2: Core Files ─────────────────────────────────────────
|
||||
Write-Host "`n--- Core Files ---" -ForegroundColor Yellow
|
||||
|
||||
Assert-Test "loader.js exists" {
|
||||
Test-Path $loaderJsPath
|
||||
}
|
||||
|
||||
Assert-Test "loader.js is not empty" {
|
||||
(Get-Item $loaderJsPath).Length -gt 0
|
||||
}
|
||||
|
||||
Assert-Test "loader.js contains version string" {
|
||||
$content = Get-Content $loaderJsPath -Raw
|
||||
$content -match 'Version:\s*\d+\.\d+\.\d+'
|
||||
}
|
||||
|
||||
Assert-Test "editor.main.js exists" {
|
||||
Test-Path (Join-Path $minDir "vs" "editor" "editor.main.js")
|
||||
}
|
||||
|
||||
Assert-Test "editor.main.js is not empty" {
|
||||
(Get-Item (Join-Path $minDir "vs" "editor" "editor.main.js")).Length -gt 0
|
||||
}
|
||||
|
||||
Assert-Test "editor.main.css exists" {
|
||||
Test-Path (Join-Path $minDir "vs" "editor" "editor.main.css")
|
||||
}
|
||||
|
||||
Assert-Test "monacoSpecialLanguages.js exists" {
|
||||
Test-Path $specialLangsPath
|
||||
}
|
||||
|
||||
Assert-Test "generateLanguagesJson.html exists" {
|
||||
Test-Path (Join-Path $monacoDir "generateLanguagesJson.html")
|
||||
}
|
||||
|
||||
Assert-Test "index.html exists" {
|
||||
Test-Path (Join-Path $monacoDir "index.html")
|
||||
}
|
||||
|
||||
Assert-Test "customTokenThemeRules.js exists" {
|
||||
Test-Path (Join-Path $monacoDir "customTokenThemeRules.js")
|
||||
}
|
||||
|
||||
# ─── Test Group 3: monaco_languages.json ──────────────────────────────
|
||||
Write-Host "`n--- monaco_languages.json ---" -ForegroundColor Yellow
|
||||
|
||||
Assert-Test "monaco_languages.json exists" {
|
||||
Test-Path $languagesJsonPath
|
||||
}
|
||||
|
||||
Assert-Test "monaco_languages.json is not empty" {
|
||||
(Get-Item $languagesJsonPath).Length -gt 0
|
||||
}
|
||||
|
||||
$languagesJson = $null
|
||||
Assert-Test "monaco_languages.json is valid JSON" {
|
||||
$script:languagesJson = Get-Content $languagesJsonPath -Raw | ConvertFrom-Json
|
||||
$null -ne $script:languagesJson
|
||||
}
|
||||
|
||||
Assert-Test "JSON has 'list' property" {
|
||||
$null -ne $languagesJson.list
|
||||
}
|
||||
|
||||
Assert-Test "Language list is a non-empty array" {
|
||||
$languagesJson.list.Count -gt 0
|
||||
}
|
||||
|
||||
# Minimum expected languages from built-in Monaco
|
||||
# These are a core subset that should always be present
|
||||
$expectedBuiltinLanguages = @(
|
||||
"plaintext", "javascript", "typescript", "html", "css", "json",
|
||||
"xml", "markdown", "yaml", "python", "java", "csharp", "cpp",
|
||||
"go", "rust", "ruby", "php", "sql", "shell", "powershell",
|
||||
"dockerfile", "bat", "fsharp", "lua", "r", "swift", "kotlin",
|
||||
"scala", "perl", "dart", "ini", "vb"
|
||||
)
|
||||
|
||||
Assert-Test "Minimum language count check (at least 80 languages)" {
|
||||
$languagesJson.list.Count -ge 80
|
||||
}
|
||||
|
||||
$languageIds = $languagesJson.list | ForEach-Object { $_.id }
|
||||
|
||||
foreach ($lang in $expectedBuiltinLanguages) {
|
||||
Assert-Test "Built-in language '$lang' is present" {
|
||||
$lang -in $languageIds
|
||||
}
|
||||
}
|
||||
|
||||
# ─── Test Group 4: PowerToys Custom Languages ─────────────────────────
|
||||
Write-Host "`n--- PowerToys Custom Languages ---" -ForegroundColor Yellow
|
||||
|
||||
# Custom languages defined in monacoSpecialLanguages.js
|
||||
$expectedCustomLanguages = @(
|
||||
@{ Id = "reg"; Extensions = @(".reg") },
|
||||
@{ Id = "gitignore"; Extensions = @(".gitignore") },
|
||||
@{ Id = "srt"; Extensions = @(".srt") }
|
||||
)
|
||||
|
||||
foreach ($custom in $expectedCustomLanguages) {
|
||||
Assert-Test "Custom language '$($custom.Id)' is registered" {
|
||||
$custom.Id -in $languageIds
|
||||
}
|
||||
|
||||
foreach ($ext in $custom.Extensions) {
|
||||
Assert-Test "Custom language '$($custom.Id)' has extension '$ext'" {
|
||||
$lang = $languagesJson.list | Where-Object { $_.id -eq $custom.Id }
|
||||
if ($null -eq $lang) { throw "Language not found" }
|
||||
$ext -in $lang.extensions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Custom language definition files exist
|
||||
$expectedCustomFiles = @("reg.js", "gitignore.js", "srt.js")
|
||||
foreach ($file in $expectedCustomFiles) {
|
||||
Assert-Test "Custom language file '$file' exists" {
|
||||
Test-Path (Join-Path $customLangsDir $file)
|
||||
}
|
||||
}
|
||||
|
||||
# ─── Test Group 5: Custom Language Extensions ─────────────────────────
|
||||
Write-Host "`n--- Custom Language Extensions ---" -ForegroundColor Yellow
|
||||
|
||||
$expectedExtensions = @(
|
||||
@{ Id = "cppExt"; Extensions = @(".ino", ".pde") },
|
||||
@{ Id = "xmlExt"; Extensions = @(".wsdl", ".csproj", ".vcxproj", ".vbproj", ".fsproj", ".resx", ".resw") },
|
||||
@{ Id = "txtExt"; Extensions = @(".sln", ".log") },
|
||||
@{ Id = "razorExt"; Extensions = @(".razor") },
|
||||
@{ Id = "vbExt"; Extensions = @(".vbs") },
|
||||
@{ Id = "iniExt"; Extensions = @(".inf") },
|
||||
@{ Id = "shellExt"; Extensions = @(".ksh", ".zsh", ".bsh") }
|
||||
)
|
||||
|
||||
foreach ($ext in $expectedExtensions) {
|
||||
Assert-Test "Extension mapping '$($ext.Id)' is registered" {
|
||||
$ext.Id -in $languageIds
|
||||
}
|
||||
|
||||
# Spot-check at least one extension from each mapping
|
||||
$firstExt = $ext.Extensions[0]
|
||||
Assert-Test "Extension mapping '$($ext.Id)' has extension '$firstExt'" {
|
||||
$lang = $languagesJson.list | Where-Object { $_.id -eq $ext.Id }
|
||||
if ($null -eq $lang) { throw "Language not found" }
|
||||
$firstExt -in $lang.extensions
|
||||
}
|
||||
}
|
||||
|
||||
# ─── Test Group 6: Language Entry Structure ───────────────────────────
|
||||
Write-Host "`n--- Language Entry Structure ---" -ForegroundColor Yellow
|
||||
|
||||
Assert-Test "Every language has an 'id' field" {
|
||||
$missing = @($languagesJson.list | Where-Object { -not $_.id -or $_.id.Trim() -eq "" })
|
||||
$missing.Count -eq 0
|
||||
}
|
||||
|
||||
Assert-Test "No duplicate language IDs" {
|
||||
$ids = $languagesJson.list | ForEach-Object { $_.id }
|
||||
$uniqueIds = $ids | Select-Object -Unique
|
||||
$ids.Count -eq $uniqueIds.Count
|
||||
}
|
||||
|
||||
Assert-Test "JSON language with extensions has array-type extensions" {
|
||||
$withExtensions = @($languagesJson.list | Where-Object {
|
||||
($_.PSObject.Properties.Name -contains "extensions") -and ($null -ne $_.extensions)
|
||||
})
|
||||
$invalid = @($withExtensions | Where-Object { $_.extensions -isnot [array] })
|
||||
$invalid.Count -eq 0
|
||||
}
|
||||
|
||||
# ─── Test Group 7: Version Consistency ────────────────────────────────
|
||||
Write-Host "`n--- Version Consistency ---" -ForegroundColor Yellow
|
||||
|
||||
Assert-Test "All NLS files in editor directory have matching versions" {
|
||||
$editorDir = Join-Path $minDir "vs" "editor"
|
||||
$nlsFiles = Get-ChildItem -Path $editorDir -Filter "editor.main.nls*.js" -ErrorAction SilentlyContinue
|
||||
if ($nlsFiles.Count -eq 0) { throw "No NLS files found" }
|
||||
|
||||
$loaderContent = Get-Content $loaderJsPath -Raw
|
||||
$null = $loaderContent -match 'Version:\s*(\d+\.\d+\.\d+)'
|
||||
$loaderVersion = $Matches[1]
|
||||
|
||||
foreach ($nlsFile in $nlsFiles) {
|
||||
$content = Get-Content $nlsFile.FullName -Raw -ErrorAction SilentlyContinue
|
||||
if ($content -and $content -match 'Version:\s*(\d+\.\d+\.\d+)') {
|
||||
if ($Matches[1] -ne $loaderVersion) {
|
||||
throw "Version mismatch in $($nlsFile.Name): expected $loaderVersion, found $($Matches[1])"
|
||||
}
|
||||
}
|
||||
}
|
||||
$true
|
||||
}
|
||||
|
||||
# ─── Summary ──────────────────────────────────────────────────────────
|
||||
Write-Host ""
|
||||
Write-Host "=== Test Summary ===" -ForegroundColor Cyan
|
||||
Write-Host "Passed: $testsPassed" -ForegroundColor Green
|
||||
Write-Host "Failed: $testsFailed" -ForegroundColor $(if ($testsFailed -gt 0) { "Red" } else { "Green" })
|
||||
Write-Host "Total: $($testsPassed + $testsFailed)"
|
||||
|
||||
if ($testsFailed -gt 0) {
|
||||
Write-Host "`nFailed tests:" -ForegroundColor Red
|
||||
$testResults | Where-Object { $_.Status -eq "FAIL" } | ForEach-Object {
|
||||
Write-Host " - $($_.Name): $($_.Error)" -ForegroundColor Red
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "`nAll tests passed!" -ForegroundColor Green
|
||||
exit 0
|
||||
150
.github/scripts/update-monaco-editor.ps1
vendored
150
.github/scripts/update-monaco-editor.ps1
vendored
@@ -1,150 +0,0 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Updates the Monaco Editor in PowerToys to the latest (or specified) version.
|
||||
|
||||
.DESCRIPTION
|
||||
This script automates the Monaco Editor update process described in
|
||||
doc/devdocs/common/FilePreviewCommon.md:
|
||||
1. Downloads Monaco editor via npm
|
||||
2. Copies the min folder into src/Monaco/monacoSRC/
|
||||
3. Generates the monaco_languages.json file using Node.js (headless)
|
||||
|
||||
.PARAMETER Version
|
||||
The Monaco Editor npm version to install. Defaults to "latest".
|
||||
|
||||
.PARAMETER RepoRoot
|
||||
The root of the PowerToys repository. Defaults to the repo root relative to this script.
|
||||
|
||||
.EXAMPLE
|
||||
./update-monaco-editor.ps1
|
||||
./update-monaco-editor.ps1 -Version "0.50.0"
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter()]
|
||||
[string]$Version = "latest",
|
||||
|
||||
[Parameter()]
|
||||
[string]$RepoRoot
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if (-not $RepoRoot) {
|
||||
$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot ".." "..")).Path
|
||||
}
|
||||
|
||||
$monacoDir = Join-Path $RepoRoot "src" "Monaco"
|
||||
$monacoSrcDir = Join-Path $monacoDir "monacoSRC"
|
||||
$languagesJsonPath = Join-Path $monacoDir "monaco_languages.json"
|
||||
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "monaco-update-$([System.Guid]::NewGuid().ToString('N').Substring(0, 8))"
|
||||
|
||||
Write-Host "=== Monaco Editor Update Script ==="
|
||||
Write-Host "Repository root: $RepoRoot"
|
||||
Write-Host "Target version: $Version"
|
||||
Write-Host "Temp directory: $tempDir"
|
||||
|
||||
# Verify prerequisites
|
||||
$npmPath = Get-Command npm -ErrorAction SilentlyContinue
|
||||
if (-not $npmPath) {
|
||||
throw "npm is required but not found in PATH. Please install Node.js."
|
||||
}
|
||||
|
||||
$nodePath = Get-Command node -ErrorAction SilentlyContinue
|
||||
if (-not $nodePath) {
|
||||
throw "node is required but not found in PATH. Please install Node.js."
|
||||
}
|
||||
|
||||
# Verify repo structure
|
||||
if (-not (Test-Path $monacoDir)) {
|
||||
throw "Monaco directory not found at: $monacoDir"
|
||||
}
|
||||
|
||||
try {
|
||||
# Step 1: Download Monaco via npm
|
||||
Write-Host "`n--- Step 1: Downloading Monaco Editor ($Version) via npm ---"
|
||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||
|
||||
Push-Location $tempDir
|
||||
try {
|
||||
$versionSpec = if ($Version -eq "latest") { "monaco-editor@latest" } else { "monaco-editor@$Version" }
|
||||
npm init -y 2>&1 | Out-Null
|
||||
npm install $versionSpec 2>&1
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "npm install failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
}
|
||||
finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
$downloadedMinDir = Join-Path $tempDir "node_modules" "monaco-editor" "min"
|
||||
if (-not (Test-Path $downloadedMinDir)) {
|
||||
throw "Downloaded Monaco min directory not found at: $downloadedMinDir"
|
||||
}
|
||||
|
||||
# Detect the downloaded version from loader.js
|
||||
$loaderJsPath = Join-Path $downloadedMinDir "vs" "loader.js"
|
||||
if (-not (Test-Path $loaderJsPath)) {
|
||||
throw "loader.js not found in downloaded Monaco package"
|
||||
}
|
||||
|
||||
$loaderContent = Get-Content $loaderJsPath -Raw
|
||||
if ($loaderContent -match 'Version:\s*(\d+\.\d+\.\d+)') {
|
||||
$newVersion = $Matches[1]
|
||||
Write-Host "Downloaded Monaco version: $newVersion"
|
||||
}
|
||||
else {
|
||||
Write-Warning "Could not detect version from loader.js"
|
||||
$newVersion = $Version
|
||||
}
|
||||
|
||||
# Step 2: Replace monacoSRC/min folder
|
||||
Write-Host "`n--- Step 2: Replacing monacoSRC with new version ---"
|
||||
$targetMinDir = Join-Path $monacoSrcDir "min"
|
||||
|
||||
if (Test-Path $targetMinDir) {
|
||||
Write-Host "Removing existing min directory..."
|
||||
Remove-Item -Recurse -Force $targetMinDir
|
||||
}
|
||||
|
||||
Write-Host "Copying new min directory..."
|
||||
Copy-Item -Recurse -Force $downloadedMinDir $targetMinDir
|
||||
|
||||
# Step 3: Generate monaco_languages.json
|
||||
Write-Host "`n--- Step 3: Generating monaco_languages.json ---"
|
||||
$generateScript = Join-Path $PSScriptRoot "generate-monaco-languages.js"
|
||||
|
||||
# Ensure playwright is available (installed in workflow, but verify here)
|
||||
$playwrightCheck = npm list playwright 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "Installing playwright for headless browser..."
|
||||
npm install playwright@latest 2>&1
|
||||
npx playwright install chromium --with-deps 2>&1
|
||||
}
|
||||
|
||||
node $generateScript $monacoDir
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Failed to generate monaco_languages.json (exit code: $LASTEXITCODE)"
|
||||
}
|
||||
|
||||
if (-not (Test-Path $languagesJsonPath)) {
|
||||
throw "monaco_languages.json was not generated at: $languagesJsonPath"
|
||||
}
|
||||
|
||||
Write-Host "`n=== Monaco Editor update complete ==="
|
||||
Write-Host "Updated to version: $newVersion"
|
||||
Write-Host "Languages JSON: $languagesJsonPath"
|
||||
|
||||
# Output the new version for the workflow to use
|
||||
Write-Output "MONACO_VERSION=$newVersion"
|
||||
}
|
||||
finally {
|
||||
# Clean up temp directory
|
||||
if (Test-Path $tempDir) {
|
||||
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
4
.github/workflows/msstore-submissions.yml
vendored
4
.github/workflows/msstore-submissions.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
export $(echo 'anypass_just_to_unlock' | gnome-keyring-daemon --start --components=gpg,pkcs11,secrets,ssh)
|
||||
|
||||
- name: Log in to Azure
|
||||
uses: azure/login@v2
|
||||
uses: azure/login@v3
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
- uses: microsoft/setup-msstore-cli@v1
|
||||
|
||||
- name: Fetch Store Credential
|
||||
uses: azure/cli@v2
|
||||
uses: azure/cli@v3
|
||||
with:
|
||||
azcliversion: latest
|
||||
inlineScript: |-
|
||||
|
||||
13
.github/workflows/spelling2.yml
vendored
13
.github/workflows/spelling2.yml
vendored
@@ -93,7 +93,7 @@ jobs:
|
||||
steps:
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@c635c2f3f714eec2fcf27b643a1919b9a811ef2e # v0.0.25
|
||||
uses: check-spelling/check-spelling@cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c # v0.0.26
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
|
||||
@@ -135,6 +135,7 @@ jobs:
|
||||
cspell:cpp/compiler-msvc.txt
|
||||
cspell:python/common/extra.txt
|
||||
cspell:scala/scala.txt
|
||||
ignored: ignored-expect-variant
|
||||
|
||||
comment-push:
|
||||
name: Report (Push)
|
||||
@@ -147,10 +148,8 @@ jobs:
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@c635c2f3f714eec2fcf27b643a1919b9a811ef2e # v0.0.25
|
||||
uses: check-spelling/check-spelling@cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c # v0.0.26
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
checkout: true
|
||||
spell_check_this: microsoft/PowerToys@main
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
|
||||
@@ -166,10 +165,8 @@ jobs:
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@c635c2f3f714eec2fcf27b643a1919b9a811ef2e # v0.0.25
|
||||
uses: check-spelling/check-spelling@cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c # v0.0.26
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
@@ -193,7 +190,7 @@ jobs:
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
- name: apply spelling updates
|
||||
uses: check-spelling/check-spelling@c635c2f3f714eec2fcf27b643a1919b9a811ef2e # v0.0.25
|
||||
uses: check-spelling/check-spelling@cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c # v0.0.26
|
||||
with:
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
checkout: true
|
||||
|
||||
134
.github/workflows/update-monaco-editor.yml
vendored
134
.github/workflows/update-monaco-editor.yml
vendored
@@ -1,134 +0,0 @@
|
||||
# Update Monaco Editor
|
||||
#
|
||||
# Automates the Monaco Editor update process described in
|
||||
# doc/devdocs/common/FilePreviewCommon.md:
|
||||
# 1. Downloads the latest (or specified) Monaco Editor from npm
|
||||
# 2. Replaces src/Monaco/monacoSRC/min with the new version
|
||||
# 3. Regenerates monaco_languages.json
|
||||
# 4. Runs validation tests
|
||||
# 5. Creates a pull request with the changes
|
||||
#
|
||||
# Trigger manually via workflow_dispatch.
|
||||
|
||||
name: Update Monaco Editor
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Monaco Editor version (e.g. "0.50.0"). Leave empty for latest.'
|
||||
required: false
|
||||
default: ''
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-monaco:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install Playwright
|
||||
run: |
|
||||
npm install playwright@latest
|
||||
npx playwright install chromium --with-deps
|
||||
|
||||
- name: Get current Monaco version
|
||||
id: current_version
|
||||
shell: bash
|
||||
run: |
|
||||
CURRENT=$(grep -oP 'Version:\s*\K[\d.]+' src/Monaco/monacoSRC/min/vs/loader.js || echo "unknown")
|
||||
echo "version=$CURRENT" >> "$GITHUB_OUTPUT"
|
||||
echo "Current Monaco version: $CURRENT"
|
||||
|
||||
- name: Run Monaco update script
|
||||
id: update
|
||||
shell: pwsh
|
||||
env:
|
||||
INPUT_VERSION: ${{ inputs.version }}
|
||||
run: |
|
||||
$version = $env:INPUT_VERSION
|
||||
if ([string]::IsNullOrWhiteSpace($version)) {
|
||||
$version = 'latest'
|
||||
}
|
||||
$output = & ./.github/scripts/update-monaco-editor.ps1 -Version $version -RepoRoot $env:GITHUB_WORKSPACE
|
||||
# Extract version from output
|
||||
$versionLine = $output | Select-String -Pattern '^MONACO_VERSION=' | Select-Object -First 1
|
||||
if ($versionLine) {
|
||||
$newVersion = $versionLine.ToString().Split('=')[1]
|
||||
echo "new_version=$newVersion" >> $env:GITHUB_OUTPUT
|
||||
}
|
||||
|
||||
- name: Run validation tests
|
||||
shell: pwsh
|
||||
run: |
|
||||
./.github/scripts/tests/validate-monaco-update.tests.ps1 -RepoRoot $env:GITHUB_WORKSPACE
|
||||
|
||||
- name: Check for changes
|
||||
id: changes
|
||||
shell: bash
|
||||
run: |
|
||||
if git diff --quiet; then
|
||||
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
||||
echo "No changes detected - Monaco may already be up to date."
|
||||
else
|
||||
echo "has_changes=true" >> "$GITHUB_OUTPUT"
|
||||
CHANGED_FILES=$(git diff --stat | tail -1)
|
||||
echo "changed_files=$CHANGED_FILES" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Create pull request
|
||||
if: steps.changes.outputs.has_changes == 'true'
|
||||
# 3rd-party action pinned to commit hash per Microsoft security guidelines
|
||||
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: "Update Monaco Editor to ${{ steps.update.outputs.new_version }}"
|
||||
title: "Update Monaco Editor from ${{ steps.current_version.outputs.version }} to ${{ steps.update.outputs.new_version }}"
|
||||
body: |
|
||||
## Summary
|
||||
|
||||
Automated update of the Monaco Editor dependency.
|
||||
|
||||
**Previous version:** ${{ steps.current_version.outputs.version }}
|
||||
**New version:** ${{ steps.update.outputs.new_version }}
|
||||
|
||||
## Changes
|
||||
|
||||
- Updated `src/Monaco/monacoSRC/min/` with the new Monaco Editor release
|
||||
- Regenerated `src/Monaco/monaco_languages.json`
|
||||
|
||||
## Validation
|
||||
|
||||
The following automated checks passed:
|
||||
- ✅ `loader.js` contains valid version header
|
||||
- ✅ `monaco_languages.json` is valid JSON with expected structure
|
||||
- ✅ All expected built-in languages are present
|
||||
- ✅ All PowerToys custom languages (reg, gitignore, srt) are present
|
||||
- ✅ All custom language extensions are registered
|
||||
- ✅ Monaco directory structure is intact
|
||||
|
||||
## Manual Verification
|
||||
|
||||
Before merging, please verify:
|
||||
- [ ] File Explorer Dev File Preview works correctly
|
||||
- [ ] Peek module previews code files properly
|
||||
- [ ] Registry Preview module functions normally
|
||||
|
||||
## Reference
|
||||
|
||||
- [Monaco Editor update docs](doc/devdocs/common/FilePreviewCommon.md#update-monaco-editor)
|
||||
- [Monaco Editor releases](https://github.com/microsoft/monaco-editor/releases)
|
||||
branch: automated/update-monaco-editor
|
||||
delete-branch: true
|
||||
labels: |
|
||||
dependencies
|
||||
@@ -141,13 +141,13 @@
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariables.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariables.exe",
|
||||
|
||||
"PowerToys.ImageResizer.exe",
|
||||
"PowerToys.ImageResizer.dll",
|
||||
"WinUI3Apps\\PowerToys.ImageResizer.exe",
|
||||
"WinUI3Apps\\PowerToys.ImageResizer.dll",
|
||||
"WinUI3Apps\\PowerToys.ImageResizerCLI.exe",
|
||||
"WinUI3Apps\\PowerToys.ImageResizerCLI.dll",
|
||||
"PowerToys.ImageResizerExt.dll",
|
||||
"PowerToys.ImageResizerContextMenu.dll",
|
||||
"ImageResizerContextMenuPackage.msix",
|
||||
"WinUI3Apps\\PowerToys.ImageResizerExt.dll",
|
||||
"WinUI3Apps\\PowerToys.ImageResizerContextMenu.dll",
|
||||
"WinUI3Apps\\ImageResizerContextMenuPackage.msix",
|
||||
|
||||
"PowerToys.LightSwitchModuleInterface.dll",
|
||||
"LightSwitchService\\PowerToys.LightSwitchService.exe",
|
||||
@@ -217,7 +217,11 @@
|
||||
"PowerToys.PowerAccentModuleInterface.dll",
|
||||
"PowerToys.PowerAccentKeyboardService.dll",
|
||||
|
||||
"PowerToys.PowerDisplayModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.PowerDisplay.dll",
|
||||
"WinUI3Apps\\PowerToys.PowerDisplay.exe",
|
||||
"PowerDisplay.Lib.dll",
|
||||
"PowerDisplay.Models.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.PowerRenameExt.dll",
|
||||
"WinUI3Apps\\PowerToys.PowerRename.exe",
|
||||
|
||||
39
AGENTS.md
39
AGENTS.md
@@ -3,7 +3,7 @@ description: 'Top-level AI contributor guidance for developing PowerToys - a col
|
||||
applyTo: '**'
|
||||
---
|
||||
|
||||
# PowerToys – AI Contributor Guide
|
||||
# PowerToys – AI contributor guide
|
||||
|
||||
This is the top-level guidance for AI contributions to PowerToys. Keep changes atomic, follow existing patterns, and cite exact paths in PRs.
|
||||
|
||||
@@ -26,13 +26,15 @@ For architecture details and module types, see [Architecture Overview](doc/devdo
|
||||
## Conventions
|
||||
|
||||
For detailed coding conventions, see:
|
||||
|
||||
- [Coding Guidelines](doc/devdocs/development/guidelines.md) – Dependencies, testing, PR management
|
||||
- [Coding Style](doc/devdocs/development/style.md) – Formatting, C++/C#/XAML style rules
|
||||
- [Logging](doc/devdocs/development/logging.md) – C++ spdlog and C# Logger usage
|
||||
|
||||
### Component-Specific Instructions
|
||||
### Component-specific instructions
|
||||
|
||||
These instruction files are automatically applied when working in their respective areas:
|
||||
|
||||
- [Runner & Settings UI](.github/instructions/runner-settings-ui.instructions.md) – IPC contracts, schema migrations
|
||||
- [Common Libraries](.github/instructions/common-libraries.instructions.md) – ABI stability, shared code guidelines
|
||||
|
||||
@@ -44,7 +46,7 @@ These instruction files are automatically applied when working in their respecti
|
||||
- Windows 10 1803+ (April 2018 Update or newer)
|
||||
- Initialize submodules once: `git submodule update --init --recursive`
|
||||
|
||||
### Build Commands
|
||||
### Build commands
|
||||
|
||||
| Task | Command |
|
||||
|------|---------|
|
||||
@@ -52,7 +54,7 @@ These instruction files are automatically applied when working in their respecti
|
||||
| Build current folder | `tools\build\build.cmd` |
|
||||
| Build with options | `build.ps1 -Platform x64 -Configuration Release` |
|
||||
|
||||
### Build Discipline
|
||||
### Build discipline
|
||||
|
||||
1. One terminal per operation (build → test). Do not switch or open new ones mid-flow
|
||||
2. After making changes, `cd` to the project folder that changed (`.csproj`/`.vcxproj`)
|
||||
@@ -62,9 +64,10 @@ These instruction files are automatically applied when working in their respecti
|
||||
6. On failure, read the errors log: `build.<config>.<platform>.errors.log`
|
||||
7. Do not start tests or launch Runner until the build succeeds
|
||||
|
||||
### Build Logs
|
||||
### Build logs
|
||||
|
||||
Located next to the solution/project being built:
|
||||
|
||||
- `build.<configuration>.<platform>.errors.log` – errors only (check this first)
|
||||
- `build.<configuration>.<platform>.all.log` – full log
|
||||
- `build.<configuration>.<platform>.trace.binlog` – for MSBuild Structured Log Viewer
|
||||
@@ -73,18 +76,18 @@ For complete details, see [Build Guidelines](tools/build/BUILD-GUIDELINES.md).
|
||||
|
||||
## Tests
|
||||
|
||||
### Test Discovery
|
||||
### Test discovery
|
||||
|
||||
- Find test projects by product code prefix (e.g., `FancyZones`, `AdvancedPaste`)
|
||||
- Look for sibling folders or 1-2 levels up named `<Product>*UnitTests` or `<Product>*UITests`
|
||||
|
||||
### Running Tests
|
||||
### Running tests
|
||||
|
||||
1. **Build the test project first**, wait for exit code 0
|
||||
2. Run via VS Test Explorer (`Ctrl+E, T`) or `vstest.console.exe` with filters
|
||||
3. **Avoid `dotnet test`** in this repo – use VS Test Explorer or vstest.console.exe
|
||||
|
||||
### Test Types
|
||||
### Test types
|
||||
|
||||
| Type | Requirements | Setup |
|
||||
|------|--------------|-------|
|
||||
@@ -92,13 +95,13 @@ For complete details, see [Build Guidelines](tools/build/BUILD-GUIDELINES.md).
|
||||
| UI Tests | WinAppDriver v1.2.1, Developer Mode | Install from [WinAppDriver releases](https://github.com/microsoft/WinAppDriver/releases/tag/v1.2.1) |
|
||||
| Fuzz Tests | OneFuzz, .NET 8 | See [Fuzzing Tests](doc/devdocs/tools/fuzzingtesting.md) |
|
||||
|
||||
### Test Discipline
|
||||
### Test discipline
|
||||
|
||||
1. Add or adjust tests when changing behavior
|
||||
2. If tests skipped, state why (e.g., comment-only change, string rename)
|
||||
3. New modules handling file I/O or user input **must** implement fuzzing tests
|
||||
|
||||
### Special Requirements
|
||||
### Special requirements
|
||||
|
||||
- **Mouse Without Borders**: Requires 2+ physical computers (not VMs)
|
||||
- **Multi-monitor utilities**: Test with 2+ monitors, different DPI settings
|
||||
@@ -107,14 +110,14 @@ For UI test setup details, see [UI Tests](doc/devdocs/development/ui-tests.md).
|
||||
|
||||
## Boundaries
|
||||
|
||||
### Ask for Clarification When
|
||||
### Ask for clarification when
|
||||
|
||||
- Ambiguous spec after scanning relevant docs
|
||||
- Cross-module impact (shared enum/struct) is unclear
|
||||
- Security, elevation, or installer changes involved
|
||||
- GPO or policy handling modifications needed
|
||||
|
||||
### Areas Requiring Extra Care
|
||||
### Areas requiring extra care
|
||||
|
||||
| Area | Concern | Reference |
|
||||
|------|---------|-----------|
|
||||
@@ -123,7 +126,7 @@ For UI test setup details, see [UI Tests](doc/devdocs/development/ui-tests.md).
|
||||
| Installer files | Release impact | Careful review required |
|
||||
| Elevation/GPO logic | Security | Confirm no regression in policy handling |
|
||||
|
||||
### What NOT to Do
|
||||
### What not to do
|
||||
|
||||
- Don't merge incomplete features into main (use feature branches)
|
||||
- Don't break IPC/JSON contracts without updating both runner and settings-ui
|
||||
@@ -143,23 +146,27 @@ Before finishing, verify:
|
||||
|
||||
## Documentation Index
|
||||
|
||||
### Core Architecture
|
||||
### Core architecture
|
||||
|
||||
- [Architecture Overview](doc/devdocs/core/architecture.md)
|
||||
- [Runner](doc/devdocs/core/runner.md)
|
||||
- [Settings System](doc/devdocs/core/settings/readme.md)
|
||||
- [Module Interface](doc/devdocs/modules/interface.md)
|
||||
|
||||
### Development
|
||||
|
||||
- [Coding Guidelines](doc/devdocs/development/guidelines.md)
|
||||
- [Coding Style](doc/devdocs/development/style.md)
|
||||
- [Logging](doc/devdocs/development/logging.md)
|
||||
- [UI Tests](doc/devdocs/development/ui-tests.md)
|
||||
- [Fuzzing Tests](doc/devdocs/tools/fuzzingtesting.md)
|
||||
|
||||
### Build & Tools
|
||||
### Build & tools
|
||||
|
||||
- [Build Guidelines](tools/build/BUILD-GUIDELINES.md)
|
||||
- [Tools Overview](doc/devdocs/tools/readme.md)
|
||||
|
||||
### Instructions (Auto-Applied)
|
||||
### Instructions (auto-applied)
|
||||
|
||||
- [Runner & Settings UI](.github/instructions/runner-settings-ui.instructions.md)
|
||||
- [Common Libraries](.github/instructions/common-libraries.instructions.md)
|
||||
|
||||
121
COMMUNITY.md
121
COMMUNITY.md
@@ -1,84 +1,109 @@
|
||||
# Community
|
||||
|
||||
The PowerToys team is extremely grateful to have the support of an amazing active community. The work you do is incredibly important. PowerToys wouldn’t be near what it is without your help filing bugs, updating documentation, guiding the design, or writing features. We want to say thanks and to recognize your work. This is a living document dedicated to highlighting the high impact community members and their contributions.
|
||||
The PowerToys team is extremely grateful to have the support of an amazing active community. The work you do is incredibly important. PowerToys wouldn't be near what it is without your help filing bugs, updating documentation, guiding the design, or writing features. We want to say thanks and to recognize your work. This is a living document dedicated to highlighting the high impact community members and their contributions.
|
||||
|
||||
Names are in alphabetical order based on first name.
|
||||
Names are in alphabetical order, based on first name.
|
||||
|
||||
## High impact community members
|
||||
|
||||
### [@cgaarden](https://github.com/cgaarden) - [Christian Gaarden Gaardmark](https://www.onegreatworld.com)
|
||||
Christian contributed New+ utility
|
||||
### [@cgaarden](https://github.com/cgaarden) - [Christian Gaarden Gaardmark](https://www.onegreatworld.com)
|
||||
|
||||
Christian contributed the New+ utility
|
||||
|
||||
### [@CleanCodeDeveloper](https://github.com/CleanCodeDeveloper)
|
||||
|
||||
CleanCodeDeveloper helped do massive amounts of code stability and image resizer work.
|
||||
|
||||
### [@plante-msft](https://github.com/plante-msft) - Connor Plante
|
||||
|
||||
Connor was the creator of Workspaces and helped create Command Palette (PowerToys Run v2)
|
||||
|
||||
### [@damienleroy](https://github.com/damienleroy) - [Damien Leroy](https://www.linkedin.com/in/Damien-Leroy-b2734416a/)
|
||||
|
||||
Damien has helped out by developing and contributing the Quick Accent utility.
|
||||
|
||||
### [@daverayment](https://github.com/daverayment) - [David Rayment](https://www.linkedin.com/in/david-rayment-168b5251/)
|
||||
|
||||
Dave has helped improve the experience inside of Peek by adding in new features and fixing bugs.
|
||||
|
||||
### [@davidegiacometti](https://github.com/davidegiacometti) - [Davide Giacometti](https://www.linkedin.com/in/davidegiacometti/)
|
||||
|
||||
Davide has helped fix multiple bugs, added new utilities, features, as well as help us with the ARM64 effort by porting applications to .NET Core.
|
||||
|
||||
### [@ethanfangg](https://github.com/ethanfangg) - Ethan Fang
|
||||
|
||||
Ethan helped run PowerToys and worked on improving and prototyping out next generation PowerToys
|
||||
|
||||
### [@franky920920](https://github.com/franky920920) - [Franky Chen](https://frankychen.net)
|
||||
|
||||
Franky has helped triaging, discussing, and creating a substantial number of issues and contributed features/fixes to PowerToys.
|
||||
|
||||
### [@htcfreek](https://github.com/htcfreek) - Heiko
|
||||
|
||||
Heiko has helped triaging, discussing, and creating a substantial number of issues and contributed features/fixes to PowerToys.
|
||||
|
||||
### [@Jay-o-Way](https://github.com/Jay-o-Way) - Jay
|
||||
|
||||
Jay has helped triaging, discussing, creating a substantial number of issues and PRs.
|
||||
|
||||
### [@jefflord](https://github.com/Jjefflord) - Jeff Lord
|
||||
Jeff added in multiple new features into Keyboard manager, such as key chord support and launching apps. He also contributed multiple features/fixes to PowerToys.
|
||||
|
||||
Jeff added multiple new features to Keyboard Manager, such as key chord support and launching apps. He also contributed multiple features/fixes to PowerToys.
|
||||
|
||||
### [@snickler](https://github.com/snickler) - [Jeremy Sinclair](http://sinclairinat0r.com)
|
||||
Jeremy has helped drive large sums of the ARM64 support inside PowerToys
|
||||
|
||||
Jeremy has helped drive substantial ARM64 support within PowerToys.
|
||||
|
||||
### [@jiripolasek](https://github.com/jiripolasek) - [Jiří Polášek](https://github.com/jiripolasek)
|
||||
|
||||
Jiří has contributed a massive number of features and improvements to Command Palette, including drag & drop support, custom themes, Web Search enhancements, Remote Desktop extension fixes, and many UX improvements.
|
||||
|
||||
### [@TheJoeFin](https://github.com/TheJoeFin) - [Joe Finney](https://joefinapps.com)
|
||||
Joe has helped triaging, discussing, issues as well as fixing bugs and building features for Text Extractor.
|
||||
|
||||
Joe has helped with triaging, discussing issues as well as fixing bugs and building features for Text Extractor.
|
||||
|
||||
### [@joadoumie](https://github.com/joadoumie) - Jordi Adoumie
|
||||
|
||||
Jordi helped innovate amazing new features into Advanced Paste and helped create Command Palette (PowerToys Run v2)
|
||||
|
||||
|
||||
### [@jsoref](https://github.com/jsoref) - [Josh Soref](https://check-spelling.dev/)
|
||||
|
||||
Helping keep our spelling correct :)
|
||||
|
||||
### [@martinchrzan](https://github.com/martinchrzan/) - Martin Chrzan
|
||||
|
||||
Color Picker is from Martin.
|
||||
|
||||
### [@mikeclayton](https://github.com/mikeclayton) - [Michael Clayton](https://michael-clayton.com)
|
||||
|
||||
Michael contributed the [initial version](https://github.com/microsoft/PowerToys/issues/23216) of the Mouse Jump tool and [a number of updates](https://github.com/microsoft/PowerToys/pulls?q=is%3Apr+author%3Amikeclayton) based on his FancyMouse utility.
|
||||
|
||||
### [@Noraa-Junker](https://github.com/Noraa-Junker) - [Noraa Junker](https://noraajunker.ch)
|
||||
|
||||
Noraa has helped triaging, discussing, and creating a substantial number of issues and contributed features/fixes. Noraa was the primary person for helping build the File Explorer preview pane handler for developer files.
|
||||
|
||||
### [@pedrolamas](https://github.com/pedrolamas/) - Pedro Lamas
|
||||
Pedro helped create the thumbnail and File Explorer previewers for 3D files like STL and GCode. If you like 3D printing, these are very helpful.
|
||||
|
||||
Pedro helped create the thumbnail and File Explorer previewers for 3D files like STL and GCode. If you like 3D printing, these are very helpful.
|
||||
|
||||
### [@PesBandi](https://github.com/PesBandi/) - PesBandi
|
||||
|
||||
PesBandi has helped do massive amounts of Quick Accent and bug fixes.
|
||||
|
||||
### [@riverar](https://github.com/riverar) - [Rafael Rivera](https://withinrafael.com/)
|
||||
Rafael has helped do the [upgrade from CppWinRT 1.x to 2.0](https://github.com/microsoft/PowerToys/issues/1907). He directly provided feedback to the CppWinRT team for bugs from this migration as well.
|
||||
|
||||
Rafael has helped do the [upgrade from CppWinRT 1.x to 2.0](https://github.com/microsoft/PowerToys/issues/1907). He directly provided feedback to the CppWinRT team for bugs from this migration as well.
|
||||
|
||||
### [@royvou](https://github.com/royvou)
|
||||
|
||||
Roy has helped out contributing multiple features to PowerToys Run
|
||||
|
||||
### [@ThiefZero](https://github.com/ThiefZero)
|
||||
ThiefZero has helped out contributing a features to PowerToys Run such as the unit converter plugin
|
||||
|
||||
ThiefZero has helped contribute features to PowerToys Run, such as the unit converter plugin
|
||||
|
||||
### [@TobiasSekan](https://github.com/TobiasSekan) - Tobias Sekan
|
||||
|
||||
Tobias Sekan has helped out contributing features to PowerToys Run such as Settings plugin, Registry plugin
|
||||
|
||||
## Open source projects
|
||||
@@ -94,7 +119,8 @@ Their fork of Wox was the base of PowerToys Run.
|
||||
Initial base of jjw24's fork, which makes it the base of PowerToys Run.
|
||||
|
||||
### [Text-Grab](https://github.com/TheJoeFin/Text-Grab) - Joseph Finney
|
||||
Joe helped develop and contribute to the Text Extractor utility. It is directly based on his Text Grab application.
|
||||
|
||||
Joe helped develop and contribute to the Text Extractor utility. It is directly based on his Text Grab application.
|
||||
|
||||
## Microsoft community members
|
||||
|
||||
@@ -102,7 +128,7 @@ We would like to also directly call out some extremely helpful Microsoft employe
|
||||
|
||||
### [@betsegaw](https://github.com/betsegaw/) - [Betsegaw Tadele](http://www.dreamsofameaningfullife.com/)
|
||||
|
||||
Window Walker, inside PowerToys Run, is from Beta.
|
||||
Window Walker, inside PowerToys Run, is from Beta.
|
||||
|
||||
### [@TheMrJukes](https://github.com/TheMrJukes/) - Bret Anderson
|
||||
|
||||
@@ -125,6 +151,7 @@ PowerToys Awake is a tool to keep your computer awake.
|
||||
Randy contributed Registry Preview and some very early conversations about keyboard remapping.
|
||||
|
||||
### [@cinnamon-msft](https://github.com/cinnamon-msft) - Kayla Cinnamon
|
||||
|
||||
Kayla was a former lead for PowerToys and helped create multiple utilities, maintained the GitHub repo, and collaborated with the community to improve the overall product
|
||||
|
||||
### [@oldnewthing](https://github.com/oldnewthing) - Raymond Chen
|
||||
@@ -135,46 +162,48 @@ Find My Mouse is based on Raymond Chen's SuperSonar.
|
||||
|
||||
Crop And Lock is based on the original work of Robert Mikhayelyan, with Program Manager support from [@kevinguo305](https://github.com/kevinguo305) - Kevin Guo.
|
||||
|
||||
ZoomIt's Video Recording Session code is based on Robert Mikhayelyan's https://github.com/robmikh/capturevideosample code.
|
||||
ZoomIt's Video Recording Session code is based on Robert Mikhayelyan's <https://github.com/robmikh/capturevideosample> code.
|
||||
|
||||
### Microsoft InVEST team
|
||||
|
||||
This amazing team helped PowerToys develop PowerToys Run and Keyboard manager as well as update our Settings to v2. @alekhyareddy28, @arjunbalgovind, @jyuwono @laviusmotileng-ms, @ryanbodrug-microsoft, @saahmedm, @somil55, @traies, @udit3333
|
||||
This amazing team helped PowerToys develop PowerToys Run and Keyboard manager as well as update our Settings to v2. @alekhyareddy28, @arjunbalgovind, @jyuwono @laviusmotileng-ms, @ryanbodrug-microsoft, @saahmedm, @somil55, @traies, @udit3333
|
||||
|
||||
## Mouse Without Borders original contributors
|
||||
*Project creator: Truong Do (Đỗ Đức Trường)*
|
||||
|
||||
Project creator: Truong Do (Đỗ Đức Trường)
|
||||
|
||||
Other contributors:
|
||||
* Microsoft Garage: Quinn Hawkins, Michael Low, Joe Coplen, Nino Yuniardi, Gwyneth Marshall, David Andrews, Karen Luecking
|
||||
* Peter Hauge - Visual Studio
|
||||
* Bruce Dawson - Windows Fundamentals
|
||||
* Alan Myrvold - Office Security
|
||||
* Adrian Garside - WEX
|
||||
* Scott Bradner - Surface
|
||||
* Aleks Gershaft - Windows Azure
|
||||
* Chinh Huynh - Windows Azure
|
||||
* Long Nguyen - Data Center
|
||||
* Triet Le - Cloud Engineering
|
||||
* Luke Schoen - Excel
|
||||
* Bao Nguyen - Bing
|
||||
* Ross Nichols - Windows
|
||||
* Ryan Baltazar - Windows
|
||||
* Ed Essey - The Garage
|
||||
* Mario Madden - The Garage
|
||||
* Karthick Mahalingam - ACE
|
||||
* Pooja Kamra - ACE
|
||||
* Justin White - SA
|
||||
* Chris Ransom - SA
|
||||
* Mike Ricks - Red Team
|
||||
* Randy Santossio - Surface
|
||||
* Ashish Sen Jaswal - Device Health
|
||||
* Zoltan Harmath - Security Tools
|
||||
* Luciano Krigun - Security Products
|
||||
* Jo Hemmerlein - Red Team
|
||||
* Chris Johnson - Surface Hub
|
||||
* Loren Ponten - Surface Hub
|
||||
* Paul Schmitt - WWL
|
||||
* And many other Users!
|
||||
|
||||
- Microsoft Garage: Quinn Hawkins, Michael Low, Joe Coplen, Nino Yuniardi, Gwyneth Marshall, David Andrews, Karen Luecking
|
||||
- Peter Hauge - Visual Studio
|
||||
- Bruce Dawson - Windows Fundamentals
|
||||
- Alan Myrvold - Office Security
|
||||
- Adrian Garside - WEX
|
||||
- Scott Bradner - Surface
|
||||
- Aleks Gershaft - Windows Azure
|
||||
- Chinh Huynh - Windows Azure
|
||||
- Long Nguyen - Data Center
|
||||
- Triet Le - Cloud Engineering
|
||||
- Luke Schoen - Excel
|
||||
- Bao Nguyen - Bing
|
||||
- Ross Nichols - Windows
|
||||
- Ryan Baltazar - Windows
|
||||
- Ed Essey - The Garage
|
||||
- Mario Madden - The Garage
|
||||
- Karthick Mahalingam - ACE
|
||||
- Pooja Kamra - ACE
|
||||
- Justin White - SA
|
||||
- Chris Ransom - SA
|
||||
- Mike Ricks - Red Team
|
||||
- Randy Santossio - Surface
|
||||
- Ashish Sen Jaswal - Device Health
|
||||
- Zoltan Harmath - Security Tools
|
||||
- Luciano Krigun - Security Products
|
||||
- Jo Hemmerlein - Red Team
|
||||
- Chris Johnson - Surface Hub
|
||||
- Loren Ponten - Surface Hub
|
||||
- Paul Schmitt - WWL
|
||||
- And many other Users!
|
||||
|
||||
## ZoomIt original contributors
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# PowerToys Contributor's Guide
|
||||
# PowerToys contributor's guide
|
||||
|
||||
Below is our guidance for reporting issues, proposing new features, and submitting contributions via Pull Requests (PRs). Our philosophy is to understand the problem and scenarios first, which is why we follow this pattern before work starts.
|
||||
|
||||
@@ -6,46 +6,46 @@ Below is our guidance for reporting issues, proposing new features, and submitti
|
||||
2. There has been a conversation.
|
||||
3. There is agreement on the problem, the fit for PowerToys, and the solution to the problem (implementation).
|
||||
|
||||
## Filing an Issue
|
||||
## Filing an issue
|
||||
|
||||
**Importance of Filing an Issue First**
|
||||
|
||||
Please follow this rule to help eliminate wasted effort and frustration, and to ensure an efficient and effective use of everyone’s time:
|
||||
Please follow this rule to help eliminate wasted effort and frustration, and to ensure an efficient and effective use of everyone's time:
|
||||
|
||||
> 👉 If you have a question, think you've discovered an issue, or would like to propose a new feature, please find/file an issue **BEFORE** starting work to fix/implement it.
|
||||
|
||||
When requesting new features or enhancements, providing additional evidence, data, tweets, blog posts, or research is extremely helpful. This information gives context to the scenario that may otherwise be lost.
|
||||
|
||||
* Unsure whether it’s an issue or feature request? File an issue.
|
||||
* Have a question that isn't answered in the docs, videos, etc.? File an issue.
|
||||
* Want to know if we’re planning a particular feature? File an issue.
|
||||
* Got a great idea for a new utility or feature? File an issue/request/idea.
|
||||
* Don’t understand how to do something? File an issue/Community Guidance Request.
|
||||
* Found an existing issue that describes yours? Great! Upvote and add additional commentary, info, or repro steps.
|
||||
- Unsure whether it's an issue or feature request? File an issue.
|
||||
- Have a question that isn't answered in the docs, videos, etc.? File an issue.
|
||||
- Want to know if we're planning a particular feature? File an issue.
|
||||
- Got a great idea for a new utility or feature? File an issue/request/idea.
|
||||
- Don't understand how to do something? File an issue/Community Guidance Request.
|
||||
- Found an existing issue that describes yours? Great! Upvote and add additional commentary, info, or repro steps.
|
||||
|
||||
A quick search before filing an issue could be helpful. It’s likely someone else has found the same problem, and they may even be working on or have already contributed a fix!
|
||||
A quick search before filing an issue could be helpful. It's likely someone else has found the same problem, and they may even be working on or have already contributed a fix!
|
||||
|
||||
### Indicating Interest in Issues
|
||||
### Indicating interest in issues
|
||||
|
||||
To let the team know which issues are important, upvote by clicking the [+😊] button and the 👍 icon on the original issue post. Avoid comments like "+1" or "me too" as they clutter the discussion and make it harder to prioritize requests.
|
||||
|
||||
---
|
||||
|
||||
## Contributing Fixes/Features
|
||||
## Contributing fixes or features
|
||||
|
||||
Please comment on our ["Would you like to contribute to PowerToys?"](https://github.com/microsoft/PowerToys/issues/28769) thread to let us know you're interested in working on something before you start. This helps avoid multiple people unexpectedly working on the same thing and ensures everyone is clear on what should be done. It's less work for everyone to establish this up front.
|
||||
Please comment on our [Would you like to contribute to PowerToys?](https://github.com/microsoft/PowerToys/issues/28769) thread to let us know you're interested in working on something before you start. This helps avoid multiple people unexpectedly working on the same thing and ensures everyone is clear on what should be done. It's less work for everyone to establish this up front.
|
||||
|
||||
### Localization Issues
|
||||
### Localization issues
|
||||
|
||||
For localization issues, please file an issue to notify our internal localization team, as community PRs for localization aren't accepted. Localization is handled exclusively by the internal Microsoft team.
|
||||
|
||||
### To Spec or Not to Spec
|
||||
### To spec or not to spec
|
||||
|
||||
A key point is for everyone to understand the approach that will be taken. We want to be sure that any work done will be accepted. Larger-scope items will require a spec to outline the approach and allow for discussion. Specs help collaborators consider different solutions, describe feature behavior, and plan for errors. Achieving agreement in a spec before writing code often results in simpler code and less wasted effort.
|
||||
|
||||
Once a team member has agreed with your approach, proceed to the "Development" section below. Team members are happy to help review specs and guide them to completion.
|
||||
|
||||
### Help Wanted
|
||||
### Help wanted
|
||||
|
||||
Once the team has approved an issue/spec approach, development can proceed. If no developers are immediately available, the spec may be parked and labeled "Help Wanted," ready for a developer to get started. For development opportunities, visit [Issues labeled Help Wanted](https://github.com/microsoft/PowerToys/labels/Help%20Wanted).
|
||||
|
||||
@@ -55,18 +55,18 @@ Once the team has approved an issue/spec approach, development can proceed. If n
|
||||
|
||||
Follow the [development guidelines](https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/readme.md).
|
||||
|
||||
### Naming Features and Functionality
|
||||
### Naming features and functionality
|
||||
|
||||
Names should be descriptive and straightforward, clearly reflecting functionality and usefulness.
|
||||
|
||||
### Becoming a Collaborator on the PowerToys Team
|
||||
### Becoming a collaborator on the PowerToys team
|
||||
|
||||
Be an active community member! Make helpful contributions by filing bugs, offering suggestions, developing fixes and features, conducting code reviews, and updating documentation.
|
||||
Be an active community member! Make helpful contributions by filing bugs, offering suggestions, developing fixes and features, conducting code reviews, and updating documentation.
|
||||
|
||||
When the time comes, Microsoft will reach out to you about becoming a formal team member. Just make sure they have a way to contact you. 😊
|
||||
|
||||
---
|
||||
|
||||
## Thank You
|
||||
## Thank you
|
||||
|
||||
Thank you in advance for your contribution! We appreciate your help in making PowerToys a better tool for everyone.
|
||||
|
||||
1698
DATA_AND_PRIVACY.md
1698
DATA_AND_PRIVACY.md
File diff suppressed because it is too large
Load Diff
@@ -18,15 +18,15 @@
|
||||
<PackageVersion Include="SixLabors.ImageSharp" Version="2.1.12" />
|
||||
<PackageVersion Include="CommunityToolkit.Common" Version="8.4.0" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.2.251219" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.2.251219" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.251219" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.2.251219" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.2.251219" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.2.251219" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.2.251219" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.251219" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
|
||||
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" Version="0.1.260116-build.2514" />
|
||||
<PackageVersion Include="ControlzEx" Version="6.0.0" />
|
||||
<PackageVersion Include="HelixToolkit" Version="2.24.0" />
|
||||
@@ -75,7 +75,7 @@
|
||||
This is present due to a bug in CsWinRT where WPF projects cause the analyzer to fail.
|
||||
-->
|
||||
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
|
||||
<PackageVersion Include="Microsoft.Windows.ImplementationLibrary" Version="1.0.231216.1"/>
|
||||
<PackageVersion Include="Microsoft.Windows.ImplementationLibrary" Version="1.0.250325.1"/>
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.6901" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.260209005" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="1.8.260203002" />
|
||||
|
||||
87
NOTICE.md
87
NOTICE.md
@@ -17,7 +17,7 @@ This software incorporates material from third parties.
|
||||
|
||||
### Martin Chrzan's Color Picker
|
||||
|
||||
**Source**: https://github.com/martinchrzan/ColorPicker
|
||||
**Source**: <https://github.com/martinchrzan/ColorPicker>
|
||||
|
||||
MIT License
|
||||
|
||||
@@ -49,7 +49,7 @@ We use the WyHash NuGet package for calculating stable hashes for strings.
|
||||
|
||||
**Source**: [https://github.com/wangyi-fudan/wyhash](https://github.com/wangyi-fudan/wyhash)
|
||||
|
||||
```
|
||||
```text
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
@@ -82,7 +82,7 @@ We use the ToolGood.Words.Pinyin NuGet package for converting Chinese characters
|
||||
|
||||
**Source**: [https://github.com/toolgood/ToolGood.Words.Pinyin](https://github.com/toolgood/ToolGood.Words.Pinyin)
|
||||
|
||||
```
|
||||
```text
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 ToolGood
|
||||
@@ -106,8 +106,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
|
||||
## Utility: Command Palette Built-in Extensions
|
||||
## Utility: Command palette built-in extensions
|
||||
|
||||
### Calculator
|
||||
|
||||
@@ -117,7 +116,7 @@ We use the exprtk library (exprtk.hpp) to evaluate mathematical expressions.
|
||||
|
||||
**Source**: [https://github.com/ArashPartow/exprtk](https://github.com/ArashPartow/exprtk)
|
||||
|
||||
```
|
||||
```text
|
||||
MIT License
|
||||
|
||||
Copyright (c) 1999-2024 Arash Partow
|
||||
@@ -144,7 +143,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
```
|
||||
|
||||
## Utility: PowerToys Run Built-in Extensions
|
||||
## Utility: PowerToys Run built-in extensions
|
||||
|
||||
### Calculator
|
||||
|
||||
@@ -154,7 +153,7 @@ We use the Mages NuGet package for calculating the result of expression.
|
||||
|
||||
**Source**: [https://github.com/FlorianRappl/Mages](https://github.com/FlorianRappl/Mages)
|
||||
|
||||
```
|
||||
```text
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 - 2025 Florian Rappl
|
||||
@@ -178,13 +177,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## Utility: File Explorer Add-ins
|
||||
## Utility: File Explorer add-ins
|
||||
|
||||
### Monaco Editor
|
||||
|
||||
**Source**: https://github.com/Microsoft/monaco-editor
|
||||
**Source**: <https://github.com/Microsoft/monaco-editor>
|
||||
|
||||
**Additional third party notifications:** https://github.com/microsoft/monaco-editor/blob/main/ThirdPartyNotices.txt
|
||||
**Additional third party notifications:** <https://github.com/microsoft/monaco-editor/blob/main/ThirdPartyNotices.txt>
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
@@ -208,9 +207,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
### The Quite OK Image Format reference decoder
|
||||
### The Quite OK image format reference decoder
|
||||
|
||||
**Source**: https://github.com/phoboslab/qoi
|
||||
**Source**: <https://github.com/phoboslab/qoi>
|
||||
|
||||
**Note**: [@pedrolamas](https://github.com/pedrolamas) translated and adapted the reference decoder code to C# that is in PowerToys from the original C++ implementation.
|
||||
|
||||
@@ -240,9 +239,9 @@ SOFTWARE.
|
||||
|
||||
We use the UTF.Unknown NuGet package for detecting encoding in text/code files.
|
||||
|
||||
**Source**: https://github.com/CharsetDetector/UTF-unknown
|
||||
**Source**: <https://github.com/CharsetDetector/UTF-unknown>
|
||||
|
||||
```
|
||||
```text
|
||||
MOZILLA PUBLIC LICENSE
|
||||
Version 1.1
|
||||
|
||||
@@ -716,9 +715,9 @@ EXHIBIT A -Mozilla Public License.
|
||||
|
||||
## Utility: ImageResizer
|
||||
|
||||
### Brice Lams's Image Resizer License
|
||||
### Brice Lams's Image Resizer license
|
||||
|
||||
**Source**: https://github.com/bricelam/ImageResizer/
|
||||
**Source**: <https://github.com/bricelam/ImageResizer/>
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
@@ -744,10 +743,10 @@ THE SOFTWARE.
|
||||
|
||||
## Utility: PowerToys Run
|
||||
|
||||
### Wox License
|
||||
### Wox license
|
||||
|
||||
**Fork project source**: https://github.com/jjw24/Wox/
|
||||
**Base project source**: https://github.com/Wox-launcher/Wox
|
||||
**Fork project source**: <https://github.com/jjw24/Wox/>
|
||||
**Base project source**: <https://github.com/Wox-launcher/Wox>
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
@@ -770,9 +769,9 @@ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
### Beta Tadele's Window Walker License
|
||||
### Beta Tadele's Window Walker license
|
||||
|
||||
**Source**: https://github.com/betsegaw/windowwalker
|
||||
**Source**: <https://github.com/betsegaw/windowwalker>
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
@@ -786,9 +785,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
## Utility: PowerRename
|
||||
|
||||
### Chris Davis's SmartRename License
|
||||
### Chris Davis's SmartRename license
|
||||
|
||||
**Source**: https://github.com/chrdavis/SmartRename
|
||||
**Source**: <https://github.com/chrdavis/SmartRename>
|
||||
|
||||
MIT License
|
||||
|
||||
@@ -816,7 +815,7 @@ SOFTWARE.
|
||||
|
||||
### spdlog
|
||||
|
||||
**Source**: https://github.com/gabime/spdlog
|
||||
**Source**: <https://github.com/gabime/spdlog>
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
@@ -841,12 +840,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-- NOTE: Third party dependency used by this software --
|
||||
This software depends on the fmt lib (MIT License),
|
||||
and users must comply to its license: https://github.com/fmtlib/fmt/blob/master/LICENSE.rst
|
||||
This software depends on the fmt lib (MIT License), and users must comply to its license:
|
||||
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>
|
||||
|
||||
### expected-lite
|
||||
|
||||
**Source**: https://github.com/martinmoene/expected-lite
|
||||
**Source**: <https://github.com/martinmoene/expected-lite>
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
@@ -874,7 +873,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
### zip
|
||||
|
||||
**Source**: https://github.com/kuba--/zip
|
||||
**Source**: <https://github.com/kuba--/zip>
|
||||
|
||||
All Rights Reserved.
|
||||
|
||||
@@ -902,7 +901,7 @@ THE SOFTWARE.
|
||||
|
||||
We adopted some functions from it.
|
||||
|
||||
**Source**: https://github.com/DLTcollab/sse2neon
|
||||
**Source**: <https://github.com/DLTcollab/sse2neon>
|
||||
|
||||
sse2neon is freely redistributable under the MIT License.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@@ -925,9 +924,9 @@ SOFTWARE.
|
||||
|
||||
### Monaco Editor
|
||||
|
||||
**Source**: https://github.com/Microsoft/monaco-editor
|
||||
**Source**: <https://github.com/Microsoft/monaco-editor>
|
||||
|
||||
**Additional third party notifications:** https://github.com/microsoft/monaco-editor/blob/main/ThirdPartyNotices.txt
|
||||
**Additional third party notifications:** <https://github.com/microsoft/monaco-editor/blob/main/ThirdPartyNotices.txt>
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
@@ -951,11 +950,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
### The Quite OK Image Format reference decoder
|
||||
### The Quite OK image format reference decoder
|
||||
|
||||
**Source**: https://github.com/phoboslab/qoi
|
||||
**Source**: <https://github.com/phoboslab/qoi>
|
||||
|
||||
**Note**: [@pedrolamas](https://github.com/pedrolamas) translated and adapted the reference decoder code to C# that is in PowerToys from the original C++ implementation.
|
||||
**Note**: [@pedrolamas](https://github.com/pedrolamas) translated and adapted the reference decoder code to C# that is in PowerToys, from the original C++ implementation.
|
||||
|
||||
MIT License
|
||||
|
||||
@@ -979,13 +978,13 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
### UTF Unknown
|
||||
### UTF unknown
|
||||
|
||||
We use the UTF.Unknown NuGet package for detecting encoding in text/code files.
|
||||
|
||||
**Source**: https://github.com/CharsetDetector/UTF-unknown
|
||||
**Source**: <https://github.com/CharsetDetector/UTF-unknown>
|
||||
|
||||
```
|
||||
```text
|
||||
MOZILLA PUBLIC LICENSE
|
||||
Version 1.1
|
||||
|
||||
@@ -1463,9 +1462,9 @@ EXHIBIT A -Mozilla Public License.
|
||||
|
||||
We use HexBox.WinUI to show a preview of binary values.
|
||||
|
||||
**Source**: https://github.com/hotkidfamily/HexBox.WinUI
|
||||
**Source**: <https://github.com/hotkidfamily/HexBox.WinUI>
|
||||
|
||||
```
|
||||
```text
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Filip Jeremic
|
||||
@@ -1492,11 +1491,11 @@ SOFTWARE.
|
||||
|
||||
### Monaco Editor
|
||||
|
||||
**Source**: https://github.com/Microsoft/monaco-editor
|
||||
**Source**: <https://github.com/Microsoft/monaco-editor>
|
||||
|
||||
**Additional third party notifications:** https://github.com/microsoft/monaco-editor/blob/main/ThirdPartyNotices.txt
|
||||
**Additional third party notifications:** <https://github.com/microsoft/monaco-editor/blob/main/ThirdPartyNotices.txt>
|
||||
|
||||
```
|
||||
```text
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 - present Microsoft Corporation
|
||||
@@ -1526,7 +1525,7 @@ SOFTWARE.
|
||||
|
||||
PowerDisplay's DDC/CI implementation references techniques from Twinkle Tray.
|
||||
|
||||
**Source**: https://github.com/xanderfrangos/twinkle-tray
|
||||
**Source**: <https://github.com/xanderfrangos/twinkle-tray>
|
||||
|
||||
MIT License
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
<Project Path="src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj" Id="1a066c63-64b3-45f8-92fe-664e1cce8077" />
|
||||
<Project Path="src/common/UnitTests-CommonUtils/UnitTests-CommonUtils.vcxproj" Id="8b5cfb38-ccba-40a8-ad7a-89c57b070884" />
|
||||
<Project Path="src/common/updating/updating.vcxproj" Id="17da04df-e393-4397-9cf0-84dabe11032e" />
|
||||
<Project Path="src/common/updating/UnitTests/UpdatingUnitTests.vcxproj" Id="a1b2c3d4-e5f6-7890-abcd-ef1234567890" />
|
||||
<Project Path="src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
|
||||
</Folder>
|
||||
<Folder Name="/common/interop/">
|
||||
@@ -709,17 +710,19 @@
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerDisplay/">
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplay.Models/PowerDisplay.Models.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplay.Lib/PowerDisplay.Lib.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<!-- TEMPORARILY_DISABLED: PowerDisplay
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplay/PowerDisplay.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplayModuleInterface/PowerDisplayModuleInterface.vcxproj" Id="d1234567-8901-2345-6789-abcdef012345" />
|
||||
-->
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerDisplay/Tests/">
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplay.Lib.UnitTests/PowerDisplay.Lib.UnitTests.csproj">
|
||||
|
||||
70
README.md
70
README.md
@@ -19,14 +19,13 @@
|
||||
<span> · </span>
|
||||
<a href="#-whats-new">Release notes</a>
|
||||
</h3>
|
||||
<br/><br/>
|
||||
|
||||
## 🔨 Utilities
|
||||
|
||||
PowerToys includes over 25 utilities to help you customize and optimize your Windows experience:
|
||||
PowerToys includes over 30 utilities to help you customize and optimize your Windows experience:
|
||||
|
||||
| | | |
|
||||
|---|---|---|
|
||||
| --- | --- | --- |
|
||||
| [<img src="doc/images/icons/AdvancedPaste.png" alt="Advanced Paste icon" height="16"> Advanced Paste](https://aka.ms/PowerToysOverview_AdvancedPaste) | [<img src="doc/images/icons/Always%20On%20Top.png" alt="Always on Top icon" height="16"> Always on Top](https://aka.ms/PowerToysOverview_AoT) | [<img src="doc/images/icons/Awake.png" alt="Awake icon" height="16"> Awake](https://aka.ms/PowerToysOverview_Awake) |
|
||||
| [<img src="doc/images/icons/Color%20Picker.png" alt="Color Picker icon" height="16"> Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) | [<img src="doc/images/icons/Command%20Not%20Found.png" alt="Command Not Found icon" height="16"> Command Not Found](https://aka.ms/PowerToysOverview_CmdNotFound) | [<img src="doc/images/icons/Command Palette.png" alt="Command Palette icon" height="16"> Command Palette](https://aka.ms/PowerToysOverview_CmdPal) |
|
||||
| [<img src="doc/images/icons/Crop%20And%20Lock.png" alt="Crop and Lock icon" height="16"> Crop And Lock](https://aka.ms/PowerToysOverview_CropAndLock) | [<img src="doc/images/icons/Environment%20Manager.png" alt="Environment Variables icon" height="16"> Environment Variables](https://aka.ms/PowerToysOverview_EnvironmentVariables) | [<img src="doc/images/icons/FancyZones.png" alt="FancyZones icon" height="16"> FancyZones](https://aka.ms/PowerToysOverview_FancyZones) |
|
||||
@@ -38,28 +37,27 @@ PowerToys includes over 25 utilities to help you customize and optimize your Win
|
||||
| [<img src="doc/images/icons/Shortcut%20Guide.png" alt="Shortcut Guide icon" height="16"> Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) | [<img src="doc/images/icons/PowerOCR.png" alt="Text Extractor icon" height="16"> Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [<img src="doc/images/icons/Workspaces.png" alt="Workspaces icon" height="16"> Workspaces](https://aka.ms/PowerToysOverview_Workspaces) |
|
||||
| [<img src="doc/images/icons/ZoomIt.png" alt="ZoomIt icon" height="16"> ZoomIt](https://aka.ms/PowerToysOverview_ZoomIt) | | |
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
## 📋 Installation
|
||||
|
||||
For detailed installation instructions and system requirements, visit the [installation docs](https://learn.microsoft.com/windows/powertoys/install).
|
||||
For detailed installation instructions and system requirements, visit the [installation docs](https://learn.microsoft.com/windows/powertoys/install).
|
||||
|
||||
But to get started quickly, choose one of the installation methods below:
|
||||
<br/><br/>
|
||||
<details open>
|
||||
<summary><strong>Download .exe from GitHub</strong></summary>
|
||||
<summary><strong>Download the .exe file from GitHub</strong></summary>
|
||||
<br/>
|
||||
Go to the <a href="https://aka.ms/installPowerToys">PowerToys GitHub releases</a>, click Assets to reveal the downloads, and choose the installer that matches your architecture and install scope. For most devices, that's the x64 per-user installer.
|
||||
|
||||
Go to the [PowerToys GitHub releases](https://aka.ms/installPowerToys), select **Assets** to reveal the installation files, and choose the one that matches your architecture and install scope. For most devices, that would be _x64 per-user_.
|
||||
|
||||
<!-- items that need to be updated release to release -->
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.99%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.98%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysUserSetup-0.98.1-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysUserSetup-0.98.1-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysSetup-0.98.1-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysUserSetup-0.98.1-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysSetup-0.98.1-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysSetup-0.98.1-arm64.exe
|
||||
|
||||
| Description | Filename |
|
||||
|----------------|----------|
|
||||
|
||||
| Description | Filename |
|
||||
| --- | --- |
|
||||
| Per user - x64 | [PowerToysUserSetup-0.98.1-x64.exe][ptUserX64] |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.98.1-arm64.exe][ptUserArm64] |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.98.1-x64.exe][ptMachineX64] |
|
||||
@@ -83,14 +81,16 @@ You can easily install PowerToys from the Microsoft Store:
|
||||
<details>
|
||||
<summary><strong>WinGet</strong></summary>
|
||||
<br/>
|
||||
Download PowerToys from <a href="https://github.com/microsoft/winget-cli#installing-the-client">WinGet</a>. Updating PowerToys via winget will respect the current PowerToys installation scope. To install PowerToys, run the following command from the command line / PowerShell:
|
||||
Download PowerToys from [WinGet](https://github.com/microsoft/winget-cli#installing-the-client). Updating PowerToys via winget will respect the current PowerToys installation scope. To install PowerToys, run the following command from the command line / PowerShell:
|
||||
|
||||
- User scope installer (default)
|
||||
|
||||
*User scope installer [default]*
|
||||
```powershell
|
||||
winget install Microsoft.PowerToys -s winget
|
||||
```
|
||||
|
||||
*Machine-wide scope installer*
|
||||
- Machine-wide scope installer
|
||||
|
||||
```powershell
|
||||
winget install --scope machine Microsoft.PowerToys -s winget
|
||||
```
|
||||
@@ -99,7 +99,7 @@ winget install --scope machine Microsoft.PowerToys -s winget
|
||||
<details>
|
||||
<summary><strong>Other methods</strong></summary>
|
||||
<br/>
|
||||
There are <a href="https://learn.microsoft.com/windows/powertoys/install#community-driven-install-tools">community driven install methods</a> such as Chocolatey and Scoop. If these are your preferred install solutions, you can find the install instructions there.
|
||||
There are [community driven install methods](https://learn.microsoft.com/windows/powertoys/install#community-driven-install-tools) such as Chocolatey and Scoop. If these are your preferred install solutions, you can find the install instructions there.
|
||||
</details>
|
||||
|
||||
## ✨ What's new?
|
||||
@@ -108,28 +108,26 @@ There are <a href="https://learn.microsoft.com/windows/powertoys/install#communi
|
||||
|
||||
To see what's new, check out the [release notes](https://github.com/microsoft/PowerToys/releases/tag/v0.98.1).
|
||||
|
||||
## 🛣️ Roadmap
|
||||
## 🛣️ Roadmap
|
||||
|
||||
We are planning some nice new features and improvements for the next releases – PowerDisplay, Command Palette improvements and a brand-new Shortcut Guide experience! Stay tuned for [v0.99][github-next-release-work]!
|
||||
|
||||
## ❤️ PowerToys Community
|
||||
## ❤️ PowerToys Community
|
||||
|
||||
The PowerToys team is extremely grateful to have the [support of an amazing active community][community-link]. The work you do is incredibly important. PowerToys wouldn't be nearly what it is today without your help filing bugs, updating documentation, guiding the design, or writing features. We want to say thank you and take time to recognize your work. Your contributions and feedback improve PowerToys month after month!
|
||||
|
||||
## Contributing
|
||||
This project welcomes contributions of all types. Besides coding features / bug fixes, other ways to assist include spec writing, design, documentation, and finding bugs. We are excited to work with the power user community to build a set of tools for helping you get the most out of Windows. We ask that **before you start work on a feature that you would like to contribute**, please read our [Contributor's Guide](CONTRIBUTING.md). We would be happy to work with you to figure out the best approach, provide guidance and mentorship throughout feature development, and help avoid any wasted or duplicate effort. Most contributions require you to agree to a [Contributor License Agreement (CLA)][oss-CLA] declaring that you grant us the rights to use your contribution and that you have permission to do so. For guidance on developing for PowerToys, please read the [developer docs](./doc/devdocs) for a detailed breakdown. This includes how to setup your computer to compile.
|
||||
## Contributing
|
||||
|
||||
## Code of Conduct
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct][oss-conduct-code].
|
||||
This project welcomes contributions of all types. Besides coding features / bug fixes, other ways to assist include spec writing, design, documentation, and finding bugs. We are excited to work with the power user community to build a set of tools for helping you get the most out of Windows. We ask that **before you start work on a feature that you would like to contribute**, please read our [Contributor's Guide](CONTRIBUTING.md). We would be happy to work with you to figure out the best approach, provide guidance and mentorship throughout feature development, and help avoid any wasted or duplicate effort. Most contributions require you to agree to a [Contributor License Agreement (CLA)][oss-CLA] declaring that you grant us the rights to use your contribution and that you have permission to do so. For guidance on developing for PowerToys, please read the [developer docs](./doc/devdocs) for a detailed breakdown. This includes how to setup your computer to compile.
|
||||
|
||||
## Privacy Statement
|
||||
The application logs basic diagnostic data (telemetry). For more privacy information and what we collect, see our [PowerToys Data and Privacy documentation](https://aka.ms/powertoys-data-and-privacy-documentation).
|
||||
## Code of conduct
|
||||
|
||||
[oss-CLA]: https://cla.opensource.microsoft.com
|
||||
[oss-conduct-code]: CODE_OF_CONDUCT.md
|
||||
[community-link]: COMMUNITY.md
|
||||
[github-release-link]: https://aka.ms/installPowerToys
|
||||
[microsoft-store-link]: https://aka.ms/getPowertoys
|
||||
[winget-link]: https://github.com/microsoft/winget-cli#installing-the-client
|
||||
[roadmap]: https://github.com/microsoft/PowerToys/wiki/Roadmap
|
||||
[privacy-link]: http://go.microsoft.com/fwlink/?LinkId=521839
|
||||
[loc-bug]: https://github.com/microsoft/PowerToys/issues/new?assignees=&labels=&template=translation_issue.md&title=
|
||||
[usingPowerToys-docs-link]: https://aka.ms/powertoys-docs
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct][oss-conduct-code].
|
||||
|
||||
## Privacy statement
|
||||
|
||||
The application logs basic diagnostic data (telemetry). For more privacy information and what we collect, see our [PowerToys Data and Privacy documentation](https://aka.ms/powertoys-data-and-privacy-documentation).
|
||||
|
||||
[oss-CLA]: https://cla.opensource.microsoft.com
|
||||
[oss-conduct-code]: CODE_OF_CONDUCT.md
|
||||
[community-link]: COMMUNITY.md
|
||||
|
||||
24
SECURITY.md
24
SECURITY.md
@@ -1,36 +1,36 @@
|
||||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.9 BLOCK -->
|
||||
|
||||
## Security
|
||||
# Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
## Reporting security issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp).
|
||||
If you prefer to submit without logging in, send an email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
* Full paths of source file(s) related to the manifestation of the issue
|
||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||
* Any special configuration required to reproduce the issue
|
||||
* Step-by-step instructions to reproduce the issue
|
||||
* Proof-of-concept or exploit code (if possible)
|
||||
* Impact of the issue, including how an attacker might exploit the issue
|
||||
- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
- Full paths of source file(s) related to the manifestation of the issue
|
||||
- The location of the affected source code (tag/branch/commit or direct URL)
|
||||
- Any special configuration required to reproduce the issue
|
||||
- Step-by-step instructions to reproduce the issue
|
||||
- Proof-of-concept or exploit code (if possible)
|
||||
- Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs.
|
||||
|
||||
## Preferred Languages
|
||||
## Preferred languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
|
||||
17
SUPPORT.md
17
SUPPORT.md
@@ -1,24 +1,21 @@
|
||||
# Support
|
||||
|
||||
## How to use Microsoft PowerToys
|
||||
|
||||
## How to use Microsoft PowerToys
|
||||
|
||||
For more info on [PowerToys overviews and how to use the utilities][usingPowerToys-docs-link], or any other tools and resources for [Windows development environments](https://learn.microsoft.com/windows/dev-environment/overview), head over to [learn.microsoft.com][usingPowerToys-docs-link]!
|
||||
For more information about PowerToys overviews, how to use the utilities, and other tools and resources for [Windows development environments](https://learn.microsoft.com/windows/dev-environment/overview), visit [learn.microsoft.com][usingPowerToys-docs-link].
|
||||
|
||||
## How to file issues and get help
|
||||
|
||||
This project uses [GitHub Issues][gh-issue] to [track bugs][gh-bug] and [feature requests][gh-feature]. Please search the existing issues before filing new issues to avoid duplicates. For new issues, file your bug or
|
||||
feature request as a new Issue.
|
||||
This project uses [GitHub Issues][gh-issue] to [track bugs][gh-bug] and [feature requests][gh-feature]. Please search the existing issues before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a new issue.
|
||||
|
||||
For help and questions about using this project, please look at our Wiki for using PowerToys and our [Contributor's Guide][contributor] if you want to work on PowerToys.
|
||||
For help and questions about using this project, please visit our documentation and [Contributor's Guide][contributor] if you want to contribute to PowerToys.
|
||||
|
||||
## Microsoft Support Policy
|
||||
## Microsoft support policy
|
||||
|
||||
Support for PowerToys is limited to the resources listed above.
|
||||
|
||||
[gh-issue]: https://github.com/microsoft/PowerToys/issues/new/choose
|
||||
[gh-bug]: https://github.com/microsoft/PowerToys/issues/new?assignees=&labels=Issue-Bug&template=bug_report.md&title=
|
||||
[gh-feature]: https://github.com/microsoft/PowerToys/issues/new?assignees=&labels=&template=feature_request.md&title=
|
||||
[wiki]: https://github.com/microsoft/PowerToys/wiki
|
||||
[gh-bug]: https://github.com/microsoft/PowerToys/issues/new?assignees=&labels=Issue-Bug&template=bug_report.md
|
||||
[gh-feature]: https://github.com/microsoft/PowerToys/issues/new?assignees=&labels=&template=feature_request.md
|
||||
[contributor]: https://github.com/microsoft/PowerToys/blob/main/CONTRIBUTING.md
|
||||
[usingPowerToys-docs-link]: https://aka.ms/powertoys-docs
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
# Settings resource
|
||||
Manage the settings for PowerToys modules
|
||||
|
||||
## Commands
|
||||
|
||||
### ✨ Modules
|
||||
List all the modules supported by the settings resource.
|
||||
```shell
|
||||
PS C:\> PowerToys.DSC.exe modules --resource 'settings'
|
||||
AdvancedPaste
|
||||
AlwaysOnTop
|
||||
App
|
||||
Awake
|
||||
ColorPicker
|
||||
CropAndLock
|
||||
EnvironmentVariables
|
||||
FancyZones
|
||||
FileLocksmith
|
||||
FindMyMouse
|
||||
Hosts
|
||||
ImageResizer
|
||||
KeyboardManager
|
||||
MeasureTool
|
||||
MouseHighlighter
|
||||
MouseJump
|
||||
MousePointerCrosshairs
|
||||
Peek
|
||||
PowerAccent
|
||||
PowerOCR
|
||||
PowerRename
|
||||
RegistryPreview
|
||||
ShortcutGuide
|
||||
Workspaces
|
||||
ZoomIt
|
||||
```
|
||||
|
||||
### 📄 Get
|
||||
Get the settings for a specific module.
|
||||
```shell
|
||||
PS C:\> PowerToys.DSC.exe get --resource 'settings' --module EnvironmentVariables
|
||||
{"settings":{"properties":{"LaunchAdministrator":{"value":true}},"name":"EnvironmentVariables","version":"1.0"}}
|
||||
```
|
||||
|
||||
### 🖨️ Export
|
||||
Export the settings for a specific module.
|
||||
|
||||
ℹ️ Settings resource Get and Export operation output states are identical.
|
||||
```shell
|
||||
PS C:\> PowerToys.DSC.exe get --resource 'settings' --module EnvironmentVariables
|
||||
{"settings":{"properties":{"LaunchAdministrator":{"value":true}},"name":"EnvironmentVariables","version":"1.0"}}
|
||||
```
|
||||
|
||||
### 📝 Set
|
||||
Set the settings for a specific module. This command will update the settings to the specified values.
|
||||
```shell
|
||||
PS C:\> PowerToys.DSC.exe set --resource 'settings' --module Awake --input '{"settings":{"properties":{"keepDisplayOn":false,"mode":0,"intervalHours":0,"intervalMinutes":1,"expirationDateTime":"2025-08-13T10:10:00.000001-07:00","customTrayTimes":{}},"name":"Awake","version":"0.0.1"}}'
|
||||
{"settings":{"properties":{"keepDisplayOn":false,"mode":0,"intervalHours":0,"intervalMinutes":1,"expirationDateTime":"2025-08-13T10:10:00.000001-07:00","customTrayTimes":{}},"name":"Awake","version":"0.0.1"}}
|
||||
["settings"]
|
||||
```
|
||||
|
||||
### 🧪 Test
|
||||
Test the settings for a specific module. This command will check if the current settings match the desired state.
|
||||
```shell
|
||||
PS C:\> PowerToys.DSC.exe test --resource 'settings' --module Awake --input '{"settings":{"properties":{"keepDisplayOn":false,"mode":0,"intervalHours":0,"intervalMinutes":1,"expirationDateTime":"2025-08-13T10:10:00.000002-07:00","customTrayTimes":{}},"name":"Awake","version":"0.0.1"}}'
|
||||
{"settings":{"properties":{"keepDisplayOn":false,"mode":0,"intervalHours":0,"intervalMinutes":1,"expirationDateTime":"2025-08-13T10:10:00.000001-07:00","customTrayTimes":{}},"name":"Awake","version":"0.0.1"},"_inDesiredState":false}
|
||||
["settings"]
|
||||
```
|
||||
|
||||
### 🛠️ Schema
|
||||
Generates the JSON schema for the settings resource of a specific module.
|
||||
```shell
|
||||
PS C:\> PowerToys.DSC.exe schema --resource 'settings' --module Awake
|
||||
{"$schema":"http://json-schema.org/draft-04/schema#","title":"SettingsResourceObjectOfAwakeSettings","type":"object","additionalProperties":false,"required":["settings"],"properties":{"_inDesiredState":{"type":["boolean","null"],"description":"Indicates whether an instance is in the desired state"},"settings":{"description":"The settings content for the module."}}}
|
||||
PS E:\src\powertoys> PowerToys.DSC.exe schema --resource 'settings' --module Awake | Format-Json
|
||||
```
|
||||
|
||||
### 📦 Manifest
|
||||
Generates a manifest dsc resource JSON file for the specified module.
|
||||
- If the module is not specified, it will generate a manifest for all modules.
|
||||
- If the output directory is not specified, it will print the manifest to the console.
|
||||
```shell
|
||||
PS C:\> PowerToys.DSC.exe manifest --resource settings --module 'Awake' --outputDir "C:\manifests"
|
||||
```
|
||||
263
doc/dsc/modules/AdvancedPaste.md
Normal file
263
doc/dsc/modules/AdvancedPaste.md
Normal file
@@ -0,0 +1,263 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys AdvancedPaste module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: AdvancedPaste Module
|
||||
---
|
||||
|
||||
# AdvancedPaste Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Advanced Paste utility, which provides advanced clipboard operations and custom paste formats.
|
||||
|
||||
## Description
|
||||
|
||||
The `AdvancedPaste` module configures PowerToys Advanced Paste, a utility
|
||||
that extends clipboard functionality with AI-powered transformations, custom
|
||||
formats, and advanced paste options. It allows you to paste clipboard content
|
||||
with transformations like plain text conversion, markdown formatting, JSON
|
||||
formatting, and AI-based text processing.
|
||||
|
||||
## Properties
|
||||
|
||||
The AdvancedPaste module supports the following configurable properties:
|
||||
|
||||
### IsAdvancedAIEnabled
|
||||
|
||||
Controls whether AI-powered paste transformations are enabled.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
**Description:** Enables AI-based clipboard transformations such as
|
||||
summarization, translation, and content reformatting.
|
||||
|
||||
### PasteAsPlainTextHotkey
|
||||
|
||||
Sets the keyboard shortcut for pasting as plain text.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier.
|
||||
- `ctrl` (boolean) - Ctrl key modifier.
|
||||
- `alt` (boolean) - Alt key modifier.
|
||||
- `shift` (boolean) - Shift key modifier.
|
||||
- `code` (integer) - Virtual key code.
|
||||
- `key` (string) - Key name.
|
||||
|
||||
**Default:** `Ctrl+Win+V`
|
||||
|
||||
### PasteAsMarkdownHotkey
|
||||
|
||||
Sets the keyboard shortcut for pasting as markdown.
|
||||
|
||||
**Type:** object (same structure as PasteAsPlainTextHotkey)
|
||||
**Default:** `Ctrl+Win+Shift+V`
|
||||
|
||||
### PasteAsJsonHotkey
|
||||
|
||||
Sets the keyboard shortcut for pasting as JSON.
|
||||
|
||||
**Type:** object (same structure as PasteAsPlainTextHotkey)
|
||||
|
||||
### ShowCustomPreview
|
||||
|
||||
Controls whether a preview window is shown before pasting custom formats.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### CloseAfterLosingFocus
|
||||
|
||||
Controls whether the Advanced Paste window closes when it loses focus.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Enable AI features with direct execution
|
||||
|
||||
This example enables AI-powered paste transformations.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
IsAdvancedAIEnabled = $true
|
||||
}
|
||||
name = "AdvancedPaste"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module AdvancedPaste `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure paste hotkeys with DSC
|
||||
|
||||
This example customizes keyboard shortcuts for different paste formats.
|
||||
|
||||
```bash
|
||||
dsc config set --file advancedpaste-hotkeys.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# advancedpaste-hotkeys.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Advanced Paste hotkeys
|
||||
type: Microsoft.PowerToys/AdvancedPasteSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PasteAsPlainTextHotkey:
|
||||
win: true
|
||||
ctrl: true
|
||||
alt: false
|
||||
shift: false
|
||||
code: 86
|
||||
key: V
|
||||
PasteAsMarkdownHotkey:
|
||||
win: true
|
||||
ctrl: true
|
||||
alt: false
|
||||
shift: true
|
||||
code: 86
|
||||
key: V
|
||||
name: AdvancedPaste
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Advanced Paste with AI
|
||||
enabled.
|
||||
|
||||
```bash
|
||||
winget configure winget-advancedpaste.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-advancedpaste.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Advanced Paste
|
||||
type: Microsoft.PowerToys/AdvancedPasteSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
IsAdvancedAIEnabled: true
|
||||
ShowCustomPreview: true
|
||||
CloseAfterLosingFocus: true
|
||||
name: AdvancedPaste
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Enable with custom preview settings
|
||||
|
||||
This example configures preview behavior for custom paste formats.
|
||||
|
||||
```bash
|
||||
dsc config set --file advancedpaste-preview.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# advancedpaste-preview.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure preview settings
|
||||
type: Microsoft.PowerToys/AdvancedPasteSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ShowCustomPreview: true
|
||||
CloseAfterLosingFocus: false
|
||||
name: AdvancedPaste
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Test AI enablement
|
||||
|
||||
This example tests whether AI features are enabled.
|
||||
|
||||
```powershell
|
||||
$desired = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
IsAdvancedAIEnabled = $true
|
||||
}
|
||||
name = "AdvancedPaste"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
$result = PowerToys.DSC.exe test --resource 'settings' `
|
||||
--module AdvancedPaste --input $desired | ConvertFrom-Json
|
||||
|
||||
if ($result._inDesiredState) {
|
||||
Write-Host "AI features are enabled"
|
||||
} else {
|
||||
Write-Host "AI features need to be enabled"
|
||||
}
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Development workflow
|
||||
|
||||
Enable AI transformations for code snippets and documentation:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Developer paste settings
|
||||
type: Microsoft.PowerToys/AdvancedPasteSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
IsAdvancedAIEnabled: true
|
||||
ShowCustomPreview: true
|
||||
name: AdvancedPaste
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Content creation
|
||||
|
||||
Configure for markdown and formatted text operations:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Content creator settings
|
||||
type: Microsoft.PowerToys/AdvancedPasteSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ShowCustomPreview: true
|
||||
CloseAfterLosingFocus: false
|
||||
name: AdvancedPaste
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [ColorPicker Module][03] - System-wide color picker utility
|
||||
- [PowerToys Advanced Paste Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./ColorPicker.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/advanced-paste
|
||||
299
doc/dsc/modules/AlwaysOnTop.md
Normal file
299
doc/dsc/modules/AlwaysOnTop.md
Normal file
@@ -0,0 +1,299 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys AlwaysOnTop module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: AlwaysOnTop Module
|
||||
---
|
||||
|
||||
# AlwaysOnTop Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Always On Top utility, which pins windows to stay on top of other windows.
|
||||
|
||||
## Description
|
||||
|
||||
The `AlwaysOnTop` module configures PowerToys Always On Top, a utility that
|
||||
allows you to pin any window to remain visible above all other windows. This
|
||||
is useful for keeping reference materials, chat windows, or monitoring tools
|
||||
visible while working with other applications.
|
||||
|
||||
## Properties
|
||||
|
||||
The AlwaysOnTop module supports the following configurable properties:
|
||||
|
||||
### Hotkey
|
||||
|
||||
Sets the keyboard shortcut to toggle Always On Top for the active window.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier.
|
||||
- `ctrl` (boolean) - Ctrl key modifier.
|
||||
- `alt` (boolean) - Alt key modifier.
|
||||
- `shift` (boolean) - Shift key modifier.
|
||||
- `code` (integer) - Virtual key code.
|
||||
- `key` (string) - Key name.
|
||||
|
||||
**Default:** `Win+Ctrl+T`
|
||||
|
||||
### FrameEnabled
|
||||
|
||||
Controls whether a colored border is displayed around pinned windows.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### FrameThickness
|
||||
|
||||
Sets the thickness of the border around pinned windows (in pixels).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `1` to `100`
|
||||
**Default:** `5`
|
||||
|
||||
### FrameColor
|
||||
|
||||
Sets the color of the border around pinned windows.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBB"`
|
||||
**Default:** `"#FF0000"` (red)
|
||||
|
||||
### FrameOpacity
|
||||
|
||||
Sets the opacity of the border (0-100).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `100`
|
||||
**Default:** `100`
|
||||
|
||||
### FrameAccentColor
|
||||
|
||||
Controls whether to use the Windows accent color for the frame.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### SoundEnabled
|
||||
|
||||
Controls whether a sound plays when toggling Always On Top.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### DoNotActivateOnGameMode
|
||||
|
||||
Controls whether Always On Top is automatically disabled during game mode.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### RoundCornersEnabled
|
||||
|
||||
Controls whether the frame has rounded corners.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### ExcludedApps
|
||||
|
||||
List of applications excluded from Always On Top functionality.
|
||||
|
||||
**Type:** string (newline-separated list of executable names)
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Enable with default settings using direct execution
|
||||
|
||||
This example enables Always On Top with default border appearance.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
FrameEnabled = $true
|
||||
FrameThickness = 5
|
||||
FrameColor = "#FF0000"
|
||||
FrameOpacity = 100
|
||||
}
|
||||
name = "AlwaysOnTop"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module AlwaysOnTop `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Customize frame appearance with DSC
|
||||
|
||||
This example configures a custom border color and thickness.
|
||||
|
||||
```bash
|
||||
dsc config set --file alwaysontop-appearance.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# alwaysontop-appearance.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Customize Always On Top frame
|
||||
type: Microsoft.PowerToys/AlwaysOnTopSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
FrameEnabled: true
|
||||
FrameThickness: 8
|
||||
FrameColor: "#0078D7"
|
||||
FrameOpacity: 80
|
||||
RoundCornersEnabled: true
|
||||
name: AlwaysOnTop
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Configure with accent color using WinGet
|
||||
|
||||
This example installs PowerToys and configures Always On Top to use the
|
||||
Windows accent color.
|
||||
|
||||
```bash
|
||||
winget configure winget-alwaysontop.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-alwaysontop.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Always On Top
|
||||
type: Microsoft.PowerToys/AlwaysOnTopSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
FrameEnabled: true
|
||||
FrameAccentColor: true
|
||||
FrameThickness: 6
|
||||
SoundEnabled: true
|
||||
name: AlwaysOnTop
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Disable for gaming
|
||||
|
||||
This example ensures Always On Top is disabled during game mode.
|
||||
|
||||
```yaml
|
||||
# alwaysontop-gaming.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure for gaming
|
||||
type: Microsoft.PowerToys/AlwaysOnTopSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
DoNotActivateOnGameMode: true
|
||||
name: AlwaysOnTop
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Minimal border configuration
|
||||
|
||||
This example configures a subtle, thin border.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
FrameEnabled = $true
|
||||
FrameThickness = 2
|
||||
FrameOpacity = 50
|
||||
RoundCornersEnabled = true
|
||||
}
|
||||
name = "AlwaysOnTop"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module AlwaysOnTop --input $config
|
||||
```
|
||||
|
||||
### Example 6 - Exclude specific applications
|
||||
|
||||
This example excludes certain applications from Always On Top.
|
||||
|
||||
```yaml
|
||||
# alwaysontop-exclusions.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Exclude apps from Always On Top
|
||||
type: Microsoft.PowerToys/AlwaysOnTopSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ExcludedApps: |
|
||||
Game.exe
|
||||
FullScreenApp.exe
|
||||
name: AlwaysOnTop
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Reference material
|
||||
|
||||
Keep documentation or reference windows visible:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Reference window settings
|
||||
type: Microsoft.PowerToys/AlwaysOnTopSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
FrameEnabled: true
|
||||
FrameColor: "#00FF00"
|
||||
FrameOpacity: 60
|
||||
name: AlwaysOnTop
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Monitoring dashboards
|
||||
|
||||
Pin monitoring tools and dashboards:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Monitoring settings
|
||||
type: Microsoft.PowerToys/AlwaysOnTopSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
FrameEnabled: true
|
||||
FrameAccentColor: true
|
||||
SoundEnabled: false
|
||||
name: AlwaysOnTop
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [FancyZones Module][03] - Window layout manager
|
||||
- [PowerToys Always On Top Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./FancyZones.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/always-on-top
|
||||
279
doc/dsc/modules/App.md
Normal file
279
doc/dsc/modules/App.md
Normal file
@@ -0,0 +1,279 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys App module (general settings)
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: App module
|
||||
---
|
||||
|
||||
# App Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages general PowerToys application settings, including utility enable/disable states, startup behavior, and theme preferences.
|
||||
|
||||
## Description
|
||||
|
||||
The `App` module controls global PowerToys settings that affect the entire
|
||||
application. This includes which utilities are enabled, whether PowerToys
|
||||
runs at startup, the application theme, and other general preferences.
|
||||
|
||||
Unlike other modules that configure specific utilities, the App module
|
||||
manages PowerToys-wide settings and the enabled state of all utilities.
|
||||
|
||||
## Properties
|
||||
|
||||
The App module supports the following configurable properties:
|
||||
|
||||
### Enabled
|
||||
|
||||
Controls which PowerToys utilities are enabled or disabled.
|
||||
|
||||
**Type:** Object
|
||||
**Properties:**
|
||||
|
||||
- `AdvancedPaste` (boolean) - Enable/disable Advanced Paste utility.
|
||||
- `AlwaysOnTop` (boolean) - Enable/disable Always On Top utility.
|
||||
- `Awake` (boolean) - Enable/disable Awake utility.
|
||||
- `ColorPicker` (boolean) - Enable/disable Color Picker utility.
|
||||
- `CropAndLock` (boolean) - Enable/disable Crop And Lock utility.
|
||||
- `EnvironmentVariables` (boolean) - Enable/disable Environment Variables
|
||||
utility.
|
||||
- `FancyZones` (boolean) - Enable/disable FancyZones utility.
|
||||
- `FileLocksmith` (boolean) - Enable/disable File Locksmith utility.
|
||||
- `FindMyMouse` (boolean) - Enable/disable Find My Mouse utility.
|
||||
- `Hosts` (boolean) - Enable/disable Hosts File Editor utility.
|
||||
- `ImageResizer` (boolean) - Enable/disable Image Resizer utility.
|
||||
- `KeyboardManager` (boolean) - Enable/disable Keyboard Manager utility.
|
||||
- `MeasureTool` (boolean) - Enable/disable Measure Tool utility.
|
||||
- `MouseHighlighter` (boolean) - Enable/disable Mouse Highlighter utility.
|
||||
- `MouseJump` (boolean) - Enable/disable Mouse Jump utility.
|
||||
- `MousePointerCrosshairs` (boolean) - Enable/disable Mouse Pointer
|
||||
Crosshairs utility.
|
||||
- `Peek` (boolean) - Enable/disable Peek utility.
|
||||
- `PowerAccent` (boolean) - Enable/disable Power Accent utility.
|
||||
- `PowerOCR` (boolean) - Enable/disable Power OCR utility.
|
||||
- `PowerRename` (boolean) - Enable/disable Power Rename utility.
|
||||
- `RegistryPreview` (boolean) - Enable/disable Registry Preview utility.
|
||||
- `ShortcutGuide` (boolean) - Enable/disable Shortcut Guide utility.
|
||||
- `Workspaces` (boolean) - Enable/disable Workspaces utility.
|
||||
- `ZoomIt` (boolean) - Enable/disable ZoomIt utility.
|
||||
|
||||
### startup
|
||||
|
||||
Controls whether PowerToys starts automatically when you sign in.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### run_elevated
|
||||
|
||||
Controls whether PowerToys runs with administrator privileges.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### theme
|
||||
|
||||
Sets the application theme.
|
||||
|
||||
**Type:** string
|
||||
**Allowed values:** `"light"`, `"dark"`, `"system"`
|
||||
**Default:** `"system"`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Enable specific utilities with direct execution
|
||||
|
||||
This example enables only FancyZones, PowerRename, and ColorPicker while
|
||||
disabling all others.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
Enabled = @{
|
||||
AdvancedPaste = $false
|
||||
AlwaysOnTop = $false
|
||||
Awake = $false
|
||||
ColorPicker = $true
|
||||
CropAndLock = $false
|
||||
EnvironmentVariables = $false
|
||||
FancyZones = $true
|
||||
FileLocksmith = $false
|
||||
FindMyMouse = $false
|
||||
Hosts = $false
|
||||
ImageResizer = $false
|
||||
KeyboardManager = $false
|
||||
MeasureTool = $false
|
||||
MouseHighlighter = $false
|
||||
MouseJump = $false
|
||||
MousePointerCrosshairs = $false
|
||||
Peek = $false
|
||||
PowerAccent = $false
|
||||
PowerOCR = $false
|
||||
PowerRename = $true
|
||||
RegistryPreview = $false
|
||||
ShortcutGuide = $false
|
||||
Workspaces = $false
|
||||
ZoomIt = $false
|
||||
}
|
||||
}
|
||||
name = "App"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module App --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure startup and theme with DSC
|
||||
|
||||
This example configures PowerToys to run at startup with elevated privileges
|
||||
and use dark theme.
|
||||
|
||||
```bash
|
||||
dsc config set --file app-config.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# app-config.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure PowerToys general settings
|
||||
type: Microsoft.PowerToys/AppSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
startup: true
|
||||
run_elevated: true
|
||||
theme: dark
|
||||
name: App
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Enable all utilities with WinGet
|
||||
|
||||
This example installs PowerToys and enables all available utilities.
|
||||
|
||||
```bash
|
||||
winget configure winget-enable-all.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-enable-all.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Enable all utilities
|
||||
type: Microsoft.PowerToys/AppSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
Enabled:
|
||||
AdvancedPaste: true
|
||||
AlwaysOnTop: true
|
||||
Awake: true
|
||||
ColorPicker: true
|
||||
CropAndLock: true
|
||||
EnvironmentVariables: true
|
||||
FancyZones: true
|
||||
FileLocksmith: true
|
||||
FindMyMouse: true
|
||||
Hosts: true
|
||||
ImageResizer: true
|
||||
KeyboardManager: true
|
||||
MeasureTool: true
|
||||
MouseHighlighter: true
|
||||
MouseJump: true
|
||||
MousePointerCrosshairs: true
|
||||
Peek: true
|
||||
PowerAccent: true
|
||||
PowerOCR: true
|
||||
PowerRename: true
|
||||
RegistryPreview: true
|
||||
ShortcutGuide: true
|
||||
Workspaces: true
|
||||
ZoomIt: true
|
||||
name: App
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Test if specific utilities are enabled
|
||||
|
||||
This example tests whether FancyZones and PowerRename are enabled.
|
||||
|
||||
```powershell
|
||||
$desired = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
Enabled = @{
|
||||
FancyZones = $true
|
||||
PowerRename = $true
|
||||
}
|
||||
}
|
||||
name = "App"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
$result = PowerToys.DSC.exe test --resource 'settings' --module App `
|
||||
--input $desired | ConvertFrom-Json
|
||||
|
||||
if ($result._inDesiredState) {
|
||||
Write-Host "FancyZones and PowerRename are enabled"
|
||||
} else {
|
||||
Write-Host "Configuration needs to be updated"
|
||||
}
|
||||
```
|
||||
|
||||
### Example 5 - Individual resource for each utility
|
||||
|
||||
This example shows enabling utilities individually, which provides better granularity for complex configurations.
|
||||
|
||||
```powershell
|
||||
# Get current state
|
||||
PowerToys.DSC.exe get --resource 'settings' --module App
|
||||
|
||||
# Enable individual utilities
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
Enabled = @{
|
||||
FancyZones = $true
|
||||
}
|
||||
}
|
||||
name = "App"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module App --input $config
|
||||
```
|
||||
|
||||
### Example 6 - Get schema for App module
|
||||
|
||||
This example retrieves the complete JSON schema for the App module.
|
||||
|
||||
```powershell
|
||||
PowerToys.DSC.exe schema --resource 'settings' --module App | `
|
||||
ConvertFrom-Json | ConvertTo-Json -Depth 10
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [Awake][03]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./Awake.md
|
||||
342
doc/dsc/modules/Awake.md
Normal file
342
doc/dsc/modules/Awake.md
Normal file
@@ -0,0 +1,342 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys Awake module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: Awake Module
|
||||
---
|
||||
|
||||
# Awake Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Awake utility, which keeps your computer awake without changing power settings.
|
||||
|
||||
## Description
|
||||
|
||||
The `Awake` module configures PowerToys Awake, a utility that prevents your
|
||||
computer from going to sleep or turning off the display. This is useful
|
||||
during installations, presentations, or any scenario where you need to
|
||||
temporarily override power settings without permanently changing them.
|
||||
|
||||
Awake supports multiple modes including indefinite keep-awake, timed
|
||||
intervals, and scheduled expiration. The display can be kept on or allowed
|
||||
to turn off independently of the system sleep state.
|
||||
|
||||
## Properties
|
||||
|
||||
The Awake module supports the following configurable properties:
|
||||
|
||||
### keepDisplayOn
|
||||
|
||||
Controls whether the display remains on while Awake is active.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
**Description:** When `true`, prevents the display from turning off. When
|
||||
`false`, only prevents system sleep while allowing the display to turn off
|
||||
according to power settings.
|
||||
|
||||
### mode
|
||||
|
||||
Specifies the Awake operating mode.
|
||||
|
||||
**Type:** integer
|
||||
**Allowed values:**
|
||||
|
||||
- `0` - Off (Awake is disabled).
|
||||
- `1` - Keep awake indefinitely.
|
||||
- `2` - Keep awake for a timed interval.
|
||||
- `3` - Keep awake until a specific date/time.
|
||||
|
||||
**Default:** `0`
|
||||
|
||||
### intervalHours
|
||||
|
||||
Number of hours to keep the system awake (used when mode is `2`).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `999`
|
||||
**Default:** `0`
|
||||
|
||||
### intervalMinutes
|
||||
|
||||
Number of minutes to keep the system awake (used when mode is `2`).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `59`
|
||||
**Default:** `1`
|
||||
|
||||
### expirationDateTime
|
||||
|
||||
The date and time when Awake should automatically disable (used when mode is `3`).
|
||||
|
||||
**Type:** string (ISO 8601 datetime format)
|
||||
**Format:** `"YYYY-MM-DDTHH:mm:ss.fffffffzzz"`
|
||||
**Example:** `"2025-12-31T23:59:59.0000000-08:00"`
|
||||
|
||||
### customTrayTimes
|
||||
|
||||
Custom time intervals displayed in the system tray context menu for quick activation.
|
||||
|
||||
**Type:** object
|
||||
**Description:** A dictionary of custom time presets for quick access. Keys
|
||||
are display names, values are time specifications.
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Keep awake indefinitely with display on
|
||||
|
||||
This example configures Awake to keep the system and display awake
|
||||
indefinitely using direct execution.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
keepDisplayOn = $true
|
||||
mode = 1
|
||||
}
|
||||
name = "Awake"
|
||||
version = "0.0.1"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module Awake --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Keep awake for 2 hours with DSC
|
||||
|
||||
This example configures a timed keep-awake period.
|
||||
|
||||
```bash
|
||||
dsc config set --file awake-timed.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# awake-timed.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Awake for 2 hours
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
keepDisplayOn: true
|
||||
mode: 2
|
||||
intervalHours: 2
|
||||
intervalMinutes: 0
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
```
|
||||
|
||||
### Example 3 - Keep awake until specific time with WinGet
|
||||
|
||||
This example configures Awake to stay active until a specific date and time.
|
||||
|
||||
```bash
|
||||
winget configure winget-awake-scheduled.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-awake-scheduled.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Keep awake until end of workday
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
keepDisplayOn: true
|
||||
mode: 3
|
||||
expirationDateTime: "2025-10-18T17:00:00.0000000-07:00"
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
```
|
||||
|
||||
### Example 4 - Disable Awake
|
||||
|
||||
This example disables Awake using direct execution.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
mode = 0
|
||||
}
|
||||
name = "Awake"
|
||||
version = "0.0.1"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module Awake --input $config
|
||||
```
|
||||
|
||||
### Example 5 - Keep system awake but allow display to sleep
|
||||
|
||||
This example keeps the system awake while allowing the display to turn off.
|
||||
|
||||
```bash
|
||||
dsc config set --file awake-system-only.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# awake-system-only.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Keep system awake only
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
keepDisplayOn: false
|
||||
mode: 1
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
```
|
||||
|
||||
### Example 6 - Configure for presentation (4 hours)
|
||||
|
||||
This example configures Awake for a presentation scenario using WinGet.
|
||||
|
||||
```bash
|
||||
winget configure presentation-mode.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# presentation-mode.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Enable Awake for presentation
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
keepDisplayOn: true
|
||||
mode: 2
|
||||
intervalHours: 4
|
||||
intervalMinutes: 0
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
```
|
||||
|
||||
### Example 7 - Test current configuration
|
||||
|
||||
This example tests whether Awake is configured for indefinite keep-awake.
|
||||
|
||||
```powershell
|
||||
$desired = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
keepDisplayOn = $true
|
||||
mode = 1
|
||||
}
|
||||
name = "Awake"
|
||||
version = "0.0.1"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
$result = PowerToys.DSC.exe test --resource 'settings' --module Awake --input $desired | ConvertFrom-Json
|
||||
|
||||
if ($result._inDesiredState) {
|
||||
Write-Host "Awake is configured for indefinite keep-awake"
|
||||
} else {
|
||||
Write-Host "Awake configuration differs from desired state"
|
||||
}
|
||||
```
|
||||
|
||||
### Example 8 - Get current Awake configuration
|
||||
|
||||
This example retrieves the current Awake settings.
|
||||
|
||||
```powershell
|
||||
PowerToys.DSC.exe get --resource 'settings' --module Awake | ConvertFrom-Json | ConvertTo-Json -Depth 10
|
||||
```
|
||||
|
||||
### Example 9 - Get Awake schema
|
||||
|
||||
This example retrieves the JSON schema for Awake module properties.
|
||||
|
||||
```powershell
|
||||
PowerToys.DSC.exe schema --resource 'settings' --module Awake | ConvertFrom-Json | ConvertTo-Json -Depth 10
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Development and builds
|
||||
|
||||
Keep the system awake during long-running builds or installations:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Keep awake during build
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
mode: 2
|
||||
intervalHours: 8
|
||||
intervalMinutes: 0
|
||||
keepDisplayOn: false
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
```
|
||||
|
||||
### Presentations and demos
|
||||
|
||||
Ensure the system stays awake during presentations:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Presentation mode
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
mode: 1
|
||||
keepDisplayOn: true
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
```
|
||||
|
||||
### Scheduled maintenance
|
||||
|
||||
Keep the system awake until a specific time for scheduled tasks:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Maintenance window
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
mode: 3
|
||||
expirationDateTime: "2025-10-19T02:00:00.0000000-07:00"
|
||||
keepDisplayOn: false
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [PowerRename][03]
|
||||
- [PowerToys Awake Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./PowerRename.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/awake
|
||||
307
doc/dsc/modules/ColorPicker.md
Normal file
307
doc/dsc/modules/ColorPicker.md
Normal file
@@ -0,0 +1,307 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys ColorPicker module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: ColorPicker Module
|
||||
---
|
||||
|
||||
# ColorPicker Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Color Picker utility, a system-wide color selection and identification tool.
|
||||
|
||||
## Description
|
||||
|
||||
The `ColorPicker` module configures PowerToys Color Picker, a utility that allows you to pick colors from anywhere on your screen and copy them to the clipboard in various formats. It's useful for designers, developers, and anyone working with colors.
|
||||
|
||||
## Properties
|
||||
|
||||
The ColorPicker module supports the following configurable properties:
|
||||
|
||||
### ActivationShortcut
|
||||
|
||||
Sets the keyboard shortcut to activate the color picker.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier.
|
||||
- `ctrl` (boolean) - Ctrl key modifier.
|
||||
- `alt` (boolean) - Alt key modifier.
|
||||
- `shift` (boolean) - Shift key modifier.
|
||||
- `code` (integer) - Virtual key code.
|
||||
- `key` (string) - Key name.
|
||||
|
||||
**Default:** `Win+Shift+C`
|
||||
|
||||
### changecursor
|
||||
|
||||
Controls whether the cursor changes when the color picker is activated.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### copiedcolorrepresentation
|
||||
|
||||
Sets the default color format copied to the clipboard.
|
||||
|
||||
**Type:** string
|
||||
**Allowed values:** `"HEX"`, `"RGB"`, `"HSL"`, `"HSV"`, `"CMYK"`, `"HSB"`,
|
||||
`"HSI"`, `"HWB"`, `"NCol"`
|
||||
**Default:** `"HEX"`
|
||||
|
||||
### activationaction
|
||||
|
||||
Controls the action when the color picker activation shortcut is pressed.
|
||||
|
||||
**Type:** integer
|
||||
**Allowed values:**
|
||||
|
||||
- `0` - Open color picker and show editor
|
||||
- `1` - Open color picker only
|
||||
- `2` - Open editor only
|
||||
|
||||
**Default:** `0`
|
||||
|
||||
### showColorName
|
||||
|
||||
Controls whether color names are displayed in the color picker.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### VisibleColorFormats
|
||||
|
||||
Defines which color formats are visible in the picker interface.
|
||||
|
||||
**Type:** object with boolean properties for each format:
|
||||
|
||||
- `HEX` (boolean)
|
||||
- `RGB` (boolean)
|
||||
- `HSL` (boolean)
|
||||
- `HSV` (boolean)
|
||||
- `CMYK` (boolean)
|
||||
- `HSB` (boolean)
|
||||
- `HSI` (boolean)
|
||||
- `HWB` (boolean)
|
||||
- `NCol` (boolean)
|
||||
- `Decimal` (boolean)
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure default color format with direct execution
|
||||
|
||||
This example sets the default copied color format to RGB.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
copiedcolorrepresentation = "RGB"
|
||||
}
|
||||
name = "ColorPicker"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module ColorPicker --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure activation behavior with DSC
|
||||
|
||||
This example configures the color picker to open directly without the
|
||||
editor.
|
||||
|
||||
```bash
|
||||
dsc config set --file colorpicker-activation.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# colorpicker-activation.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Color Picker activation
|
||||
type: Microsoft.PowerToys/ColorPickerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
activationaction: 1
|
||||
changecursor: true
|
||||
copiedcolorrepresentation: HEX
|
||||
name: ColorPicker
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure for web development with WinGet
|
||||
|
||||
This example installs PowerToys and configures Color Picker for web
|
||||
developers.
|
||||
|
||||
```bash
|
||||
winget configure winget-colorpicker-webdev.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-colorpicker-webdev.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Color Picker for web development
|
||||
type: Microsoft.PowerToys/ColorPickerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
copiedcolorrepresentation: HEX
|
||||
showColorName: true
|
||||
changecursor: true
|
||||
VisibleColorFormats:
|
||||
HEX: true
|
||||
RGB: true
|
||||
HSL: true
|
||||
HSV: false
|
||||
CMYK: false
|
||||
name: ColorPicker
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Configure visible formats
|
||||
|
||||
This example enables only HEX, RGB, and HSL formats.
|
||||
|
||||
```bash
|
||||
dsc config set --file colorpicker-formats.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# colorpicker-formats.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure visible color formats
|
||||
type: Microsoft.PowerToys/ColorPickerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
VisibleColorFormats:
|
||||
HEX: true
|
||||
RGB: true
|
||||
HSL: true
|
||||
HSV: false
|
||||
CMYK: false
|
||||
HSB: false
|
||||
HSI: false
|
||||
HWB: false
|
||||
NCol: false
|
||||
Decimal: false
|
||||
name: ColorPicker
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Configure for graphic design
|
||||
|
||||
This example configures Color Picker for graphic designers with CMYK support.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
copiedcolorrepresentation = "CMYK"
|
||||
showColorName = $true
|
||||
VisibleColorFormats = @{
|
||||
HEX = $true
|
||||
RGB = $true
|
||||
CMYK = $true
|
||||
HSL = $true
|
||||
HSV = $true
|
||||
}
|
||||
}
|
||||
name = "ColorPicker"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module ColorPicker --input $config
|
||||
```
|
||||
|
||||
### Example 6 - Test configuration
|
||||
|
||||
This example tests whether HEX is the default format.
|
||||
|
||||
```powershell
|
||||
$desired = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
copiedcolorrepresentation = "HEX"
|
||||
}
|
||||
name = "ColorPicker"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
$result = PowerToys.DSC.exe test --resource 'settings' --module ColorPicker `
|
||||
--input $desired | ConvertFrom-Json
|
||||
|
||||
if ($result._inDesiredState) {
|
||||
Write-Host "HEX is the default format"
|
||||
}
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Web development
|
||||
|
||||
Configure for HTML/CSS color codes:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Web developer settings
|
||||
type: Microsoft.PowerToys/ColorPickerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
copiedcolorrepresentation: HEX
|
||||
VisibleColorFormats:
|
||||
HEX: true
|
||||
RGB: true
|
||||
HSL: true
|
||||
name: ColorPicker
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Print design
|
||||
|
||||
Configure for CMYK color space:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Print designer settings
|
||||
type: Microsoft.PowerToys/ColorPickerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
copiedcolorrepresentation: CMYK
|
||||
showColorName: true
|
||||
name: ColorPicker
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [ImageResizer][03]
|
||||
- [PowerToys Color Picker Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./ImageResizer.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/color-picker
|
||||
195
doc/dsc/modules/CropAndLock.md
Normal file
195
doc/dsc/modules/CropAndLock.md
Normal file
@@ -0,0 +1,195 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys CropAndLock module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: CropAndLock Module
|
||||
---
|
||||
|
||||
# CropAndLock Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Crop And Lock utility, which crops and locks portions of windows.
|
||||
|
||||
## Description
|
||||
|
||||
The `CropAndLock` module configures PowerToys Crop And Lock, a utility that allows you to crop a portion of any window and keep it visible as a thumbnail. This is useful for monitoring specific parts of applications, keeping reference information visible, or focusing on particular UI elements.
|
||||
|
||||
## Properties
|
||||
|
||||
The CropAndLock module supports the following configurable properties:
|
||||
|
||||
### Hotkey
|
||||
|
||||
Sets the keyboard shortcut to activate Crop And Lock for the active window.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier.
|
||||
- `ctrl` (boolean) - Ctrl key modifier.
|
||||
- `alt` (boolean) - Alt key modifier.
|
||||
- `shift` (boolean) - Shift key modifier.
|
||||
- `code` (integer) - Virtual key code.
|
||||
- `key` (string) - Key name.
|
||||
|
||||
**Default:** `Win+Ctrl+Shift+T`
|
||||
|
||||
### ReparentHotkey
|
||||
|
||||
Sets the keyboard shortcut to change the parent window of a cropped thumbnail.
|
||||
|
||||
**Type:** object (same structure as Hotkey)
|
||||
|
||||
### ThumbnailOpacity
|
||||
|
||||
Sets the opacity of cropped thumbnails (0-100).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `100`
|
||||
**Default:** `100`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure basic settings with direct execution
|
||||
|
||||
This example sets the Crop And Lock hotkey and thumbnail opacity.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ThumbnailOpacity = 90
|
||||
}
|
||||
name = "CropAndLock"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module CropAndLock --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure hotkeys with DSC
|
||||
|
||||
This example configures custom hotkeys for cropping and reparenting.
|
||||
|
||||
```bash
|
||||
dsc config set --file cropandlock-hotkeys.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# cropandlock-hotkeys.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Crop And Lock hotkeys
|
||||
type: Microsoft.PowerToys/CropAndLockSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
Hotkey:
|
||||
win: true
|
||||
ctrl: true
|
||||
shift: true
|
||||
alt: false
|
||||
code: 84
|
||||
key: T
|
||||
ThumbnailOpacity: 85
|
||||
name: CropAndLock
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Crop And Lock.
|
||||
|
||||
```bash
|
||||
winget configure winget-cropandlock.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-cropandlock.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Crop And Lock
|
||||
type: Microsoft.PowerToys/CropAndLockSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ThumbnailOpacity: 75
|
||||
name: CropAndLock
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Semi-transparent thumbnails
|
||||
|
||||
This example configures thumbnails to be semi-transparent for overlay use.
|
||||
|
||||
```yaml
|
||||
# cropandlock-transparent.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Semi-transparent thumbnails
|
||||
type: Microsoft.PowerToys/CropAndLockSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ThumbnailOpacity: 60
|
||||
name: CropAndLock
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Monitoring dashboards
|
||||
|
||||
Keep portions of monitoring tools visible:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Monitoring configuration
|
||||
type: Microsoft.PowerToys/CropAndLockSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ThumbnailOpacity: 80
|
||||
name: CropAndLock
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Reference material
|
||||
|
||||
Crop and display reference information:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Reference display
|
||||
type: Microsoft.PowerToys/CropAndLockSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ThumbnailOpacity: 95
|
||||
name: CropAndLock
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [MouseJump][03]
|
||||
- [PowerToys Crop And Lock Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./MouseJump.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/crop-and-lock
|
||||
193
doc/dsc/modules/EnvironmentVariables.md
Normal file
193
doc/dsc/modules/EnvironmentVariables.md
Normal file
@@ -0,0 +1,193 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys EnvironmentVariables module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: EnvironmentVariables Module
|
||||
---
|
||||
|
||||
# EnvironmentVariables Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Environment Variables utility, a quick editor for system and user environment variables.
|
||||
|
||||
## Description
|
||||
|
||||
The `EnvironmentVariables` module configures PowerToys Environment Variables, a utility that provides an enhanced interface for viewing and editing Windows environment variables. It offers a more user-friendly alternative to the standard Windows environment variable editor.
|
||||
|
||||
## Properties
|
||||
|
||||
The EnvironmentVariables module supports the following configurable properties:
|
||||
|
||||
### LaunchAdministrator
|
||||
|
||||
Controls whether the Environment Variables editor launches with administrator privileges by default.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
**Description:** When enabled, the editor will always attempt to launch with elevated permissions, allowing editing of system-wide environment variables.
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Enable admin launch with direct execution
|
||||
|
||||
This example configures the Environment Variables editor to always launch with admin rights.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
LaunchAdministrator = $true
|
||||
}
|
||||
name = "EnvironmentVariables"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module EnvironmentVariables --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure with DSC
|
||||
|
||||
This example enables administrator launch through DSC configuration.
|
||||
|
||||
```bash
|
||||
dsc config set --file environmentvariables-config.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# environmentvariables-config.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Environment Variables editor
|
||||
type: Microsoft.PowerToys/EnvironmentVariablesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchAdministrator: true
|
||||
name: EnvironmentVariables
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Environment Variables for
|
||||
admin launch.
|
||||
|
||||
```bash
|
||||
winget configure winget-envvars.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-envvars.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Environment Variables
|
||||
type: Microsoft.PowerToys/EnvironmentVariablesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchAdministrator: true
|
||||
name: EnvironmentVariables
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Standard user mode
|
||||
|
||||
This example configures for standard user access (no elevation).
|
||||
|
||||
```bash
|
||||
dsc config set --file envvars-user.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# envvars-user.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: User-level Environment Variables
|
||||
type: Microsoft.PowerToys/EnvironmentVariablesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchAdministrator: false
|
||||
name: EnvironmentVariables
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Test admin launch configuration
|
||||
|
||||
This example tests whether admin launch is enabled.
|
||||
|
||||
```powershell
|
||||
$desired = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
LaunchAdministrator = $true
|
||||
}
|
||||
name = "EnvironmentVariables"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
$result = PowerToys.DSC.exe test --resource 'settings' --module EnvironmentVariables --input $desired | ConvertFrom-Json
|
||||
|
||||
if ($result._inDesiredState) {
|
||||
Write-Host "Admin launch is enabled"
|
||||
}
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### System administration
|
||||
|
||||
Configure for system-wide environment variable management:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Admin configuration
|
||||
type: Microsoft.PowerToys/EnvironmentVariablesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchAdministrator: true
|
||||
name: EnvironmentVariables
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Development workstations
|
||||
|
||||
Configure for user-level variable management:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Developer configuration
|
||||
type: Microsoft.PowerToys/EnvironmentVariablesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchAdministrator: false
|
||||
name: EnvironmentVariables
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [Hosts][03]
|
||||
- [PowerToys Environment Variables Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./Hosts.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/environment-variables
|
||||
545
doc/dsc/modules/FancyZones.md
Normal file
545
doc/dsc/modules/FancyZones.md
Normal file
@@ -0,0 +1,545 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys FancyZones module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: FancyZones Module
|
||||
---
|
||||
|
||||
# FancyZones Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the FancyZones utility, a window layout manager that arranges and snaps windows into efficient layouts.
|
||||
|
||||
## Description
|
||||
|
||||
The `FancyZones` module configures PowerToys FancyZones, a window manager
|
||||
utility that helps organize windows into custom layouts called zones.
|
||||
FancyZones allows you to create multiple zone layouts for different displays
|
||||
and quickly snap windows into position using keyboard shortcuts or mouse
|
||||
actions.
|
||||
|
||||
This module controls activation methods, window behavior, zone appearance, editor settings, and other FancyZones preferences.
|
||||
|
||||
## Properties
|
||||
|
||||
The FancyZones module supports the following configurable properties:
|
||||
|
||||
### fancyzones_shiftDrag
|
||||
|
||||
Controls whether holding Shift while dragging a window activates zone snapping.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### fancyzones_mouseSwitch
|
||||
|
||||
Controls whether moving a window across monitors triggers zone selection.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### fancyzones_overrideSnapHotkeys
|
||||
|
||||
Controls whether FancyZones overrides the Windows Snap hotkeys (Win+Arrow keys).
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### fancyzones_moveWindowsAcrossMonitors
|
||||
|
||||
Controls whether moving windows between monitors is enabled.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### fancyzones_moveWindowsBasedOnPosition
|
||||
|
||||
Controls whether windows move to zones based on cursor position rather than window position.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### fancyzones_overlappingZonesAlgorithm
|
||||
|
||||
Determines the algorithm used when multiple zones overlap.
|
||||
|
||||
**Type:** integer
|
||||
**Allowed values:**
|
||||
|
||||
- `0` - Smallest zone
|
||||
- `1` - Largest zone
|
||||
- `2` - Positional (based on cursor/window position)
|
||||
|
||||
**Default:** `0`
|
||||
|
||||
### fancyzones_displayOrWorkAreaChange_moveWindows
|
||||
|
||||
Controls whether windows are moved to fit when display or work area changes.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### fancyzones_zoneSetChange_flashZones
|
||||
|
||||
Controls whether zones flash briefly when the zone set changes.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### fancyzones_zoneSetChange_moveWindows
|
||||
|
||||
Controls whether windows are automatically moved when the zone set changes.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### fancyzones_appLastZone_moveWindows
|
||||
|
||||
Controls whether windows are moved to their last known zone when reopened.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### fancyzones_openWindowOnActiveMonitor
|
||||
|
||||
Controls whether newly opened windows appear on the currently active monitor.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### fancyzones_spanZonesAcrossMonitors
|
||||
|
||||
Controls whether zones can span across multiple monitors.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### fancyzones_makeDraggedWindowTransparent
|
||||
|
||||
Controls whether dragged windows become transparent to show zones underneath.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### fancyzones_zoneColor
|
||||
|
||||
Sets the color of zone areas.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBB"`
|
||||
**Example:** `"#0078D7"`
|
||||
**Default:** `"#0078D7"`
|
||||
|
||||
### fancyzones_zoneBorderColor
|
||||
|
||||
Sets the color of zone borders.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBB"`
|
||||
**Example:** `"#FFFFFF"`
|
||||
**Default:** `"#FFFFFF"`
|
||||
|
||||
### fancyzones_zoneHighlightColor
|
||||
|
||||
Sets the highlight color when a zone is activated.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBB"`
|
||||
**Example:** `"#0078D7"`
|
||||
**Default:** `"#0078D7"`
|
||||
|
||||
### fancyzones_highlightOpacity
|
||||
|
||||
Sets the opacity of zone highlights (0-100).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `100`
|
||||
**Default:** `50`
|
||||
|
||||
### fancyzones_editorHotkey
|
||||
|
||||
Sets the keyboard shortcut to open the FancyZones editor.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier
|
||||
- `ctrl` (boolean) - Ctrl key modifier
|
||||
- `alt` (boolean) - Alt key modifier
|
||||
- `shift` (boolean) - Shift key modifier
|
||||
- `code` (integer) - Virtual key code
|
||||
- `key` (string) - Key name
|
||||
|
||||
**Default:** `Win+Shift+~`
|
||||
|
||||
### fancyzones_windowSwitching
|
||||
|
||||
Controls whether window switching with arrow keys is enabled.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### fancyzones_nextTabHotkey
|
||||
|
||||
Sets the keyboard shortcut to switch to the next tab/window in a zone.
|
||||
|
||||
**Type:** object (same structure as fancyzones_editorHotkey)
|
||||
|
||||
### fancyzones_prevTabHotkey
|
||||
|
||||
Sets the keyboard shortcut to switch to the previous tab/window in a zone.
|
||||
|
||||
**Type:** object (same structure as fancyzones_editorHotkey)
|
||||
|
||||
### fancyzones_excludedApps
|
||||
|
||||
List of applications excluded from FancyZones snapping.
|
||||
|
||||
**Type:** string (newline-separated list of executable names)
|
||||
**Example:** `"Notepad.exe\nCalc.exe"`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Enable basic zone snapping with direct execution
|
||||
|
||||
This example enables Shift-drag zone snapping and mouse-based monitor switching.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
fancyzones_shiftDrag = $true
|
||||
fancyzones_mouseSwitch = $true
|
||||
}
|
||||
name = "FancyZones"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module FancyZones --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure window movement behavior with DSC
|
||||
|
||||
This example configures how windows behave when displays or zones change.
|
||||
|
||||
```bash
|
||||
dsc config set --file fancyzones-window-behavior.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# fancyzones-window-behavior.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure FancyZones window behavior
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_displayOrWorkAreaChange_moveWindows: true
|
||||
fancyzones_zoneSetChange_moveWindows: true
|
||||
fancyzones_appLastZone_moveWindows: true
|
||||
fancyzones_moveWindowsAcrossMonitors: true
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Customize zone appearance with WinGet
|
||||
|
||||
This example installs PowerToys and configures custom zone colors and
|
||||
opacity.
|
||||
|
||||
```bash
|
||||
winget configure winget-fancyzones-appearance.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-fancyzones-appearance.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Customize FancyZones appearance
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_zoneColor: "#2D2D30"
|
||||
fancyzones_zoneBorderColor: "#007ACC"
|
||||
fancyzones_zoneHighlightColor: "#007ACC"
|
||||
fancyzones_highlightOpacity: 75
|
||||
fancyzones_makeDraggedWindowTransparent: true
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Override Windows Snap hotkeys
|
||||
|
||||
This example configures FancyZones to replace Windows default snap
|
||||
functionality.
|
||||
|
||||
```bash
|
||||
dsc config set --file fancyzones-snap-override.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# fancyzones-snap-override.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Override Windows Snap
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_overrideSnapHotkeys: true
|
||||
fancyzones_moveWindowsBasedOnPosition: true
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Configure editor hotkey
|
||||
|
||||
This example changes the FancyZones editor hotkey to Ctrl+Shift+Alt+F.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
fancyzones_editorHotkey = @{
|
||||
win = $false
|
||||
ctrl = $true
|
||||
alt = $true
|
||||
shift = $true
|
||||
code = 70 # F key
|
||||
key = "F"
|
||||
}
|
||||
}
|
||||
name = "FancyZones"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module FancyZones --input $config
|
||||
```
|
||||
|
||||
### Example 6 - Exclude applications from zone snapping
|
||||
|
||||
This example configures FancyZones to ignore specific applications.
|
||||
|
||||
```yaml
|
||||
# fancyzones-exclusions.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Exclude apps from FancyZones
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_excludedApps: |
|
||||
Notepad.exe
|
||||
Calculator.exe
|
||||
mspaint.exe
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 7 - Multi-monitor configuration
|
||||
|
||||
This example configures FancyZones for optimal multi-monitor workflow.
|
||||
|
||||
```bash
|
||||
dsc config set --file fancyzones-multimonitor.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# fancyzones-multimonitor.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Multi-monitor FancyZones setup
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_shiftDrag: true
|
||||
fancyzones_mouseSwitch: true
|
||||
fancyzones_moveWindowsAcrossMonitors: true
|
||||
fancyzones_spanZonesAcrossMonitors: false
|
||||
fancyzones_openWindowOnActiveMonitor: true
|
||||
fancyzones_displayOrWorkAreaChange_moveWindows: true
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 8 - Complete FancyZones configuration with WinGet
|
||||
|
||||
This example shows a comprehensive FancyZones setup with installation.
|
||||
|
||||
```bash
|
||||
winget configure winget-fancyzones-complete.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-fancyzones-complete.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Enable FancyZones
|
||||
type: Microsoft.PowerToys/AppSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
Enabled:
|
||||
FancyZones: true
|
||||
name: App
|
||||
version: 1.0
|
||||
|
||||
- name: Configure FancyZones
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
# Activation
|
||||
fancyzones_shiftDrag: true
|
||||
fancyzones_mouseSwitch: true
|
||||
fancyzones_overrideSnapHotkeys: false
|
||||
|
||||
# Window behavior
|
||||
fancyzones_moveWindowsAcrossMonitors: true
|
||||
fancyzones_moveWindowsBasedOnPosition: false
|
||||
fancyzones_displayOrWorkAreaChange_moveWindows: true
|
||||
fancyzones_zoneSetChange_moveWindows: false
|
||||
fancyzones_appLastZone_moveWindows: true
|
||||
|
||||
# Appearance
|
||||
fancyzones_makeDraggedWindowTransparent: true
|
||||
fancyzones_zoneColor: "#0078D7"
|
||||
fancyzones_zoneBorderColor: "#FFFFFF"
|
||||
fancyzones_zoneHighlightColor: "#0078D7"
|
||||
fancyzones_highlightOpacity: 50
|
||||
|
||||
# Multi-monitor
|
||||
fancyzones_openWindowOnActiveMonitor: true
|
||||
fancyzones_spanZonesAcrossMonitors: false
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 9 - Test FancyZones configuration
|
||||
|
||||
This example tests whether FancyZones is configured for multi-monitor use.
|
||||
|
||||
```powershell
|
||||
$desired = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
fancyzones_moveWindowsAcrossMonitors = $true
|
||||
fancyzones_openWindowOnActiveMonitor = $true
|
||||
}
|
||||
name = "FancyZones"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
$result = PowerToys.DSC.exe test --resource 'settings' --module FancyZones `
|
||||
--input $desired | ConvertFrom-Json
|
||||
|
||||
if ($result._inDesiredState) {
|
||||
Write-Host "FancyZones is configured for multi-monitor"
|
||||
} else {
|
||||
Write-Host "FancyZones configuration needs updating"
|
||||
}
|
||||
```
|
||||
|
||||
### Example 10 - Get FancyZones schema
|
||||
|
||||
This example retrieves the complete JSON schema for FancyZones properties.
|
||||
|
||||
```powershell
|
||||
PowerToys.DSC.exe schema --resource 'settings' --module FancyZones | `
|
||||
ConvertFrom-Json | ConvertTo-Json -Depth 10
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Development workflow
|
||||
|
||||
Configure FancyZones for efficient development with IDE, browser, and terminal windows:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Developer layout
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_shiftDrag: true
|
||||
fancyzones_overrideSnapHotkeys: true
|
||||
fancyzones_appLastZone_moveWindows: true
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Presentation mode
|
||||
|
||||
Optimize window management for presentations and screen sharing:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Presentation layout
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_openWindowOnActiveMonitor: true
|
||||
fancyzones_highlightOpacity: 30
|
||||
fancyzones_makeDraggedWindowTransparent: false
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Home office setup
|
||||
|
||||
Configure for docking/undocking laptop scenarios:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Home office configuration
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_displayOrWorkAreaChange_moveWindows: true
|
||||
fancyzones_moveWindowsAcrossMonitors: true
|
||||
fancyzones_appLastZone_moveWindows: true
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [Peek][03]
|
||||
- [PowerToys FancyZones Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./Peek.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/fancyzones
|
||||
179
doc/dsc/modules/FileLocksmith.md
Normal file
179
doc/dsc/modules/FileLocksmith.md
Normal file
@@ -0,0 +1,179 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys FileLocksmith module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: FileLocksmith Module
|
||||
---
|
||||
|
||||
# FileLocksmith Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the File Locksmith utility, which identifies
|
||||
processes that are locking files or folders.
|
||||
|
||||
## Description
|
||||
|
||||
The `FileLocksmith` module configures PowerToys File Locksmith, a Windows
|
||||
shell extension that helps identify which processes are using (locking)
|
||||
specific files or folders. It integrates with the Windows Explorer context
|
||||
menu for easy access.
|
||||
|
||||
## Properties
|
||||
|
||||
The FileLocksmith module supports the following configurable properties:
|
||||
|
||||
### ExtendedContextMenuOnly
|
||||
|
||||
Controls whether File Locksmith appears only in the extended context menu.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
**Description:** When `true`, File Locksmith only appears in the context menu
|
||||
when you hold Shift while right-clicking. When `false`, it appears in the
|
||||
standard context menu.
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Show in standard context menu with direct execution
|
||||
|
||||
This example configures File Locksmith to appear in the standard context menu.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ExtendedContextMenuOnly = $false
|
||||
}
|
||||
name = "FileLocksmith"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module FileLocksmith `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Extended menu only with DSC
|
||||
|
||||
This example configures File Locksmith to appear only in the extended
|
||||
context menu.
|
||||
|
||||
```bash
|
||||
dsc config set --file filelocksmith-extended.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# filelocksmith-extended.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure File Locksmith for extended menu
|
||||
type: Microsoft.PowerToys/FileLocksmithSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ExtendedContextMenuOnly: true
|
||||
name: FileLocksmith
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures File Locksmith for standard
|
||||
menu access.
|
||||
|
||||
```bash
|
||||
winget configure winget-filelocksmith.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-filelocksmith.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure File Locksmith
|
||||
type: Microsoft.PowerToys/FileLocksmithSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ExtendedContextMenuOnly: false
|
||||
name: FileLocksmith
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Minimize context menu clutter
|
||||
|
||||
This example configures for extended menu to reduce clutter.
|
||||
|
||||
```bash
|
||||
dsc config set --file filelocksmith-minimal.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# filelocksmith-minimal.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Minimal context menu
|
||||
type: Microsoft.PowerToys/FileLocksmithSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ExtendedContextMenuOnly: true
|
||||
name: FileLocksmith
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### System administration
|
||||
|
||||
Quick access for troubleshooting file locks:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Admin quick access
|
||||
type: Microsoft.PowerToys/FileLocksmithSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ExtendedContextMenuOnly: false
|
||||
name: FileLocksmith
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Clean context menu
|
||||
|
||||
Reduce menu clutter for casual users:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Clean menu
|
||||
type: Microsoft.PowerToys/FileLocksmithSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ExtendedContextMenuOnly: true
|
||||
name: FileLocksmith
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [RegistryPreview][03]
|
||||
- [PowerToys File Locksmith Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./RegistryPreview.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/file-locksmith
|
||||
288
doc/dsc/modules/FindMyMouse.md
Normal file
288
doc/dsc/modules/FindMyMouse.md
Normal file
@@ -0,0 +1,288 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys FindMyMouse module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: FindMyMouse Module
|
||||
---
|
||||
|
||||
# FindMyMouse Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Find My Mouse utility, which helps locate your
|
||||
mouse cursor on the screen.
|
||||
|
||||
## Description
|
||||
|
||||
The `FindMyMouse` module configures PowerToys Find My Mouse, a utility that
|
||||
highlights your mouse cursor location when you press the Ctrl key. This is
|
||||
particularly useful on large or multiple displays where the cursor can be
|
||||
difficult to locate.
|
||||
|
||||
## Properties
|
||||
|
||||
The FindMyMouse module supports the following configurable properties:
|
||||
|
||||
### DoNotActivateOnGameMode
|
||||
|
||||
Controls whether Find My Mouse is disabled during game mode.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
**Description:** When enabled, Find My Mouse will not activate when Windows
|
||||
game mode is active.
|
||||
|
||||
### BackgroundColor
|
||||
|
||||
Sets the background color of the spotlight effect.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBB"`
|
||||
**Default:** `"#000000"` (black)
|
||||
|
||||
### SpotlightColor
|
||||
|
||||
Sets the color of the spotlight circle around the cursor.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBB"`
|
||||
**Default:** `"#FFFFFF"` (white)
|
||||
|
||||
### OverlayOpacity
|
||||
|
||||
Sets the opacity of the background overlay (0-100).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `100`
|
||||
**Default:** `50`
|
||||
|
||||
### SpotlightRadius
|
||||
|
||||
Sets the radius of the spotlight in pixels.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `50` to `500`
|
||||
**Default:** `100`
|
||||
|
||||
### AnimationDurationMs
|
||||
|
||||
Sets the duration of the spotlight animation in milliseconds.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `5000`
|
||||
**Default:** `500`
|
||||
|
||||
### SpotlightInitialZoom
|
||||
|
||||
Sets the initial zoom level of the spotlight effect.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `100` to `1000`
|
||||
**Default:** `200`
|
||||
|
||||
### ExcludedApps
|
||||
|
||||
List of applications where Find My Mouse is disabled.
|
||||
|
||||
**Type:** string (newline-separated list of executable names)
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure spotlight appearance with direct execution
|
||||
|
||||
This example customizes the spotlight colors and radius.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
BackgroundColor = "#000000"
|
||||
SpotlightColor = "#00FF00"
|
||||
SpotlightRadius = 150
|
||||
OverlayOpacity = 60
|
||||
}
|
||||
name = "FindMyMouse"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module FindMyMouse --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure animation with DSC
|
||||
|
||||
This example customizes the spotlight animation behavior.
|
||||
|
||||
```bash
|
||||
dsc config set --file findmymouse-animation.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# findmymouse-animation.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Find My Mouse animation
|
||||
type: Microsoft.PowerToys/FindMyMouseSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
AnimationDurationMs: 750
|
||||
SpotlightInitialZoom: 300
|
||||
SpotlightRadius: 120
|
||||
name: FindMyMouse
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Find My Mouse with custom
|
||||
colors.
|
||||
|
||||
```bash
|
||||
winget configure winget-findmymouse.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-findmymouse.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Find My Mouse
|
||||
type: Microsoft.PowerToys/FindMyMouseSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
BackgroundColor: "#000000"
|
||||
SpotlightColor: "#0078D7"
|
||||
OverlayOpacity: 70
|
||||
SpotlightRadius: 140
|
||||
DoNotActivateOnGameMode: true
|
||||
name: FindMyMouse
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Subtle configuration
|
||||
|
||||
This example creates a subtle, less intrusive spotlight effect.
|
||||
|
||||
```bash
|
||||
dsc config set --file findmymouse-subtle.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# findmymouse-subtle.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Subtle spotlight
|
||||
type: Microsoft.PowerToys/FindMyMouseSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
OverlayOpacity: 30
|
||||
SpotlightRadius: 100
|
||||
AnimationDurationMs: 300
|
||||
name: FindMyMouse
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - High visibility configuration
|
||||
|
||||
This example creates a high-visibility spotlight for accessibility.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
BackgroundColor = "#000000"
|
||||
SpotlightColor = "#FFFF00"
|
||||
OverlayOpacity = 80
|
||||
SpotlightRadius = 200
|
||||
SpotlightInitialZoom = 400
|
||||
}
|
||||
name = "FindMyMouse"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module FindMyMouse --input $config
|
||||
```
|
||||
|
||||
### Example 6 - Disable during gaming
|
||||
|
||||
This example ensures Find My Mouse doesn't interfere with games.
|
||||
|
||||
```bash
|
||||
dsc config set --file findmymouse-gaming.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# findmymouse-gaming.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Gaming configuration
|
||||
type: Microsoft.PowerToys/FindMyMouseSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
DoNotActivateOnGameMode: true
|
||||
name: FindMyMouse
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Large displays
|
||||
|
||||
Configure for high visibility on large screens:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Large display configuration
|
||||
type: Microsoft.PowerToys/FindMyMouseSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
SpotlightRadius: 180
|
||||
OverlayOpacity: 70
|
||||
SpotlightColor: "#FFFFFF"
|
||||
name: FindMyMouse
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Accessibility
|
||||
|
||||
Configure for maximum visibility:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Accessibility configuration
|
||||
type: Microsoft.PowerToys/FindMyMouseSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
SpotlightColor: "#FFFF00"
|
||||
OverlayOpacity: 80
|
||||
SpotlightRadius: 200
|
||||
AnimationDurationMs: 1000
|
||||
name: FindMyMouse
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [MouseHighlighter][03]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./MouseHighlighter.md
|
||||
200
doc/dsc/modules/Hosts.md
Normal file
200
doc/dsc/modules/Hosts.md
Normal file
@@ -0,0 +1,200 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys Hosts module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: Hosts Module
|
||||
---
|
||||
|
||||
# Hosts Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Hosts File Editor utility, a quick editor for
|
||||
the Windows hosts file.
|
||||
|
||||
## Description
|
||||
|
||||
The `Hosts` module configures PowerToys Hosts File Editor, a utility that
|
||||
provides a user-friendly interface for viewing and editing the Windows hosts
|
||||
file. It simplifies the process of adding, modifying, and managing DNS
|
||||
entries in the hosts file.
|
||||
|
||||
## Properties
|
||||
|
||||
The Hosts module supports the following configurable properties:
|
||||
|
||||
### LaunchAdministrator
|
||||
|
||||
Controls whether the Hosts File Editor launches with administrator privileges
|
||||
by default.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
**Description:** When enabled, the editor will always attempt to launch with
|
||||
elevated permissions, which is required to edit the hosts file.
|
||||
|
||||
### LoopbackDuplicates
|
||||
|
||||
Controls how duplicate loopback addresses are handled.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### AdditionalLinesPosition
|
||||
|
||||
Controls where additional lines are positioned when editing entries.
|
||||
|
||||
**Type:** integer
|
||||
**Allowed values:**
|
||||
|
||||
- `0` - Top
|
||||
- `1` - Bottom
|
||||
|
||||
**Default:** `0`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Enable admin launch with direct execution
|
||||
|
||||
This example configures the Hosts editor to always launch with admin rights.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
LaunchAdministrator = $true
|
||||
}
|
||||
name = "Hosts"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module Hosts --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure with DSC
|
||||
|
||||
This example enables administrator launch and configures line positioning.
|
||||
|
||||
```bash
|
||||
dsc config set --file hosts-config.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# hosts-config.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Hosts File Editor
|
||||
type: Microsoft.PowerToys/HostsSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchAdministrator: true
|
||||
AdditionalLinesPosition: 1
|
||||
name: Hosts
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures the Hosts editor for admin
|
||||
launch.
|
||||
|
||||
```bash
|
||||
winget configure winget-hosts.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-hosts.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Hosts File Editor
|
||||
type: Microsoft.PowerToys/HostsSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchAdministrator: true
|
||||
LoopbackDuplicates: false
|
||||
name: Hosts
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Development configuration
|
||||
|
||||
This example configures for development use with new entries at the bottom.
|
||||
|
||||
```bash
|
||||
dsc config set --file hosts-development.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# hosts-development.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Development hosts configuration
|
||||
type: Microsoft.PowerToys/HostsSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchAdministrator: true
|
||||
AdditionalLinesPosition: 1
|
||||
name: Hosts
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### System administration
|
||||
|
||||
Configure for frequent hosts file editing:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Admin configuration
|
||||
type: Microsoft.PowerToys/HostsSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchAdministrator: true
|
||||
name: Hosts
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Web development
|
||||
|
||||
Configure for development environment management:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Developer configuration
|
||||
type: Microsoft.PowerToys/HostsSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchAdministrator: true
|
||||
AdditionalLinesPosition: 1
|
||||
name: Hosts
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [KeyboardManager][03]
|
||||
- [PowerToys Hosts File Editor Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./KeyboardManager.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/hosts-file-editor
|
||||
349
doc/dsc/modules/ImageResizer.md
Normal file
349
doc/dsc/modules/ImageResizer.md
Normal file
@@ -0,0 +1,349 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys ImageResizer module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: ImageResizer Module
|
||||
---
|
||||
|
||||
# ImageResizer Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Image Resizer utility, which provides quick
|
||||
image resizing from the Windows Explorer context menu.
|
||||
|
||||
## Description
|
||||
|
||||
The `ImageResizer` module configures PowerToys Image Resizer, a Windows shell
|
||||
extension that allows you to resize one or multiple images directly from the
|
||||
File Explorer context menu. It supports custom size presets and various
|
||||
resize options.
|
||||
|
||||
## Properties
|
||||
|
||||
The ImageResizer module supports the following configurable properties:
|
||||
|
||||
### ImageResizerSizes
|
||||
|
||||
Defines the preset sizes available in the Image Resizer interface.
|
||||
|
||||
**Type:** array of objects
|
||||
**Object properties:**
|
||||
|
||||
- `Name` (string) - Display name for the preset
|
||||
- `Width` (integer) - Width value
|
||||
- `Height` (integer) - Height value
|
||||
- `Unit` (string) - Unit of measurement: `"Pixel"`, `"Percent"`, `"Centimeter"`, `"Inch"`
|
||||
- `Fit` (string) - Resize mode: `"Fit"`, `"Fill"`, `"Stretch"`
|
||||
|
||||
### ImageresizerSelectedSizeIndex
|
||||
|
||||
Sets the default selected size preset (0-based index).
|
||||
|
||||
**Type:** integer
|
||||
**Default:** `0`
|
||||
|
||||
### ImageresizerShrinkOnly
|
||||
|
||||
Controls whether images are only resized if they're larger than the target size.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### ImageresizerReplace
|
||||
|
||||
Controls whether resized images replace the original files.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### ImageresizerIgnoreOrientation
|
||||
|
||||
Controls whether EXIF orientation data is ignored.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### ImageresizerJpegQualityLevel
|
||||
|
||||
Sets the JPEG quality level for resized images (1-100).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `1` to `100`
|
||||
**Default:** `90`
|
||||
|
||||
### ImageresizerPngInterlaceOption
|
||||
|
||||
Sets the PNG interlace option.
|
||||
|
||||
**Type:** integer
|
||||
**Allowed values:**
|
||||
|
||||
- `0` - No interlacing
|
||||
- `1` - Interlaced
|
||||
|
||||
**Default:** `0`
|
||||
|
||||
### ImageresizerTiffCompressOption
|
||||
|
||||
Sets the TIFF compression option.
|
||||
|
||||
**Type:** integer
|
||||
**Allowed values:**
|
||||
|
||||
- `0` - No compression
|
||||
- `1` - LZW compression
|
||||
- `2` - ZIP compression
|
||||
|
||||
**Default:** `0`
|
||||
|
||||
### ImageresizerFileName
|
||||
|
||||
Sets the naming pattern for resized images.
|
||||
|
||||
**Type:** string
|
||||
**Default:** `"%1 (%2)"`
|
||||
**Placeholders:**
|
||||
|
||||
- `%1` - Original filename
|
||||
- `%2` - Size name
|
||||
- `%3` - Selected width
|
||||
- `%4` - Selected height
|
||||
- `%5` - Actual width
|
||||
- `%6` - Actual height
|
||||
|
||||
### ImageresizerKeepDateModified
|
||||
|
||||
Controls whether the original file's modified date is preserved.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### ImageresizerFallbackEncoder
|
||||
|
||||
Sets the fallback encoder for unsupported formats.
|
||||
|
||||
**Type:** string
|
||||
**Allowed values:** `"png"`, `"jpg"`, `"bmp"`, `"tiff"`, `"gif"`
|
||||
**Default:** `"png"`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure custom size presets with direct execution
|
||||
|
||||
This example defines custom image resize presets.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ImageResizerSizes = @(
|
||||
@{
|
||||
Name = "Small"
|
||||
Width = 640
|
||||
Height = 480
|
||||
Unit = "Pixel"
|
||||
Fit = "Fit"
|
||||
},
|
||||
@{
|
||||
Name = "Medium"
|
||||
Width = 1280
|
||||
Height = 720
|
||||
Unit = "Pixel"
|
||||
Fit = "Fit"
|
||||
},
|
||||
@{
|
||||
Name = "Large"
|
||||
Width = 1920
|
||||
Height = 1080
|
||||
Unit = "Pixel"
|
||||
Fit = "Fit"
|
||||
}
|
||||
)
|
||||
}
|
||||
name = "ImageResizer"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module ImageResizer `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure quality settings with DSC
|
||||
|
||||
This example configures image quality and format options.
|
||||
|
||||
```bash
|
||||
dsc config set --file imageresizer-quality.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# imageresizer-quality.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Image Resizer quality
|
||||
type: Microsoft.PowerToys/ImageResizerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ImageresizerJpegQualityLevel: 95
|
||||
ImageresizerShrinkOnly: true
|
||||
ImageresizerKeepDateModified: true
|
||||
name: ImageResizer
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Image Resizer with
|
||||
web-optimized presets.
|
||||
|
||||
```bash
|
||||
winget configure winget-imageresizer.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-imageresizer.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Image Resizer
|
||||
type: Microsoft.PowerToys/ImageResizerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ImageResizerSizes:
|
||||
- Name: Thumbnail
|
||||
Width: 320
|
||||
Height: 240
|
||||
Unit: Pixel
|
||||
Fit: Fit
|
||||
- Name: Web Small
|
||||
Width: 800
|
||||
Height: 600
|
||||
Unit: Pixel
|
||||
Fit: Fit
|
||||
- Name: Web Large
|
||||
Width: 1920
|
||||
Height: 1080
|
||||
Unit: Pixel
|
||||
Fit: Fit
|
||||
ImageresizerJpegQualityLevel: 85
|
||||
ImageresizerFileName: "%1_resized_%2"
|
||||
name: ImageResizer
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Photography workflow
|
||||
|
||||
This example configures for photography with high quality and metadata
|
||||
preservation.
|
||||
|
||||
```bash
|
||||
dsc config set --file imageresizer-photo.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# imageresizer-photography.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Photography configuration
|
||||
type: Microsoft.PowerToys/ImageResizerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ImageresizerJpegQualityLevel: 100
|
||||
ImageresizerKeepDateModified: true
|
||||
ImageresizerIgnoreOrientation: false
|
||||
ImageresizerShrinkOnly: true
|
||||
name: ImageResizer
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Social media presets
|
||||
|
||||
This example defines presets for social media platforms.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ImageResizerSizes = @(
|
||||
@{ Name = "Instagram Square"; Width = 1080; Height = 1080; Unit = "Pixel"; Fit = "Fill" },
|
||||
@{ Name = "Instagram Portrait"; Width = 1080; Height = 1350; Unit = "Pixel"; Fit = "Fill" },
|
||||
@{ Name = "Facebook Cover"; Width = 820; Height = 312; Unit = "Pixel"; Fit = "Fill" },
|
||||
@{ Name = "Twitter Header"; Width = 1500; Height = 500; Unit = "Pixel"; Fit = "Fill" }
|
||||
)
|
||||
ImageresizerJpegQualityLevel = 90
|
||||
}
|
||||
name = "ImageResizer"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module ImageResizer `
|
||||
--input $config
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Web development
|
||||
|
||||
Configure for web-optimized images:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Web optimization
|
||||
type: Microsoft.PowerToys/ImageResizerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ImageresizerJpegQualityLevel: 85
|
||||
ImageresizerShrinkOnly: true
|
||||
name: ImageResizer
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Content creation
|
||||
|
||||
Configure for social media and content platforms:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Content creation
|
||||
type: Microsoft.PowerToys/ImageResizerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ImageResizerSizes:
|
||||
- Name: HD
|
||||
Width: 1920
|
||||
Height: 1080
|
||||
Unit: Pixel
|
||||
Fit: Fit
|
||||
ImageresizerJpegQualityLevel: 90
|
||||
name: ImageResizer
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [MeasureTool][03]
|
||||
- [PowerToys Image Resizer Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./MeasureTool.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/image-resizer
|
||||
145
doc/dsc/modules/KeyboardManager.md
Normal file
145
doc/dsc/modules/KeyboardManager.md
Normal file
@@ -0,0 +1,145 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys KeyboardManager module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: KeyboardManager Module
|
||||
---
|
||||
|
||||
# KeyboardManager Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Keyboard Manager utility, which allows key
|
||||
remapping and custom keyboard shortcuts.
|
||||
|
||||
## Description
|
||||
|
||||
The `KeyboardManager` module configures PowerToys Keyboard Manager, a utility
|
||||
that enables you to remap keys and create custom keyboard shortcuts. It
|
||||
allows reassigning keys, creating application-specific remappings, and
|
||||
defining shortcuts that run programs or commands.
|
||||
|
||||
## Properties
|
||||
|
||||
The KeyboardManager module supports the following configurable properties:
|
||||
|
||||
### Enabled
|
||||
|
||||
Controls whether Keyboard Manager is enabled.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Enable Keyboard Manager with direct execution
|
||||
|
||||
This example enables the Keyboard Manager utility.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
Enabled = $true
|
||||
}
|
||||
name = "KeyboardManager"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module KeyboardManager --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure with DSC
|
||||
|
||||
This example enables Keyboard Manager through DSC configuration.
|
||||
|
||||
```bash
|
||||
dsc config set --file keyboardmanager-config.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# keyboardmanager-config.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Enable Keyboard Manager
|
||||
type: Microsoft.PowerToys/KeyboardManagerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
Enabled: true
|
||||
name: KeyboardManager
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and enables Keyboard Manager.
|
||||
|
||||
```bash
|
||||
winget configure winget-keyboardmanager.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-keyboardmanager.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Enable Keyboard Manager
|
||||
type: Microsoft.PowerToys/KeyboardManagerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
Enabled: true
|
||||
name: KeyboardManager
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Important notes
|
||||
|
||||
> **Note:** The Keyboard Manager module DSC configuration controls the enabled state only. Key remappings and shortcut definitions are managed through the Keyboard Manager UI and stored separately. This design ensures that complex remapping configurations are not accidentally overwritten by DSC operations.
|
||||
|
||||
To configure key remappings:
|
||||
1. Enable Keyboard Manager using DSC
|
||||
2. Open PowerToys Settings
|
||||
3. Navigate to Keyboard Manager
|
||||
4. Use "Remap a key" or "Remap a shortcut" to configure specific mappings
|
||||
|
||||
## Use cases
|
||||
|
||||
### Enable for deployment
|
||||
|
||||
Enable Keyboard Manager on new workstations:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Enable Keyboard Manager
|
||||
type: Microsoft.PowerToys/KeyboardManagerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
Enabled: true
|
||||
name: KeyboardManager
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [PowerOCR][03]
|
||||
- [PowerToys Keyboard Manager Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./PowerOCR.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/keyboard-manager
|
||||
254
doc/dsc/modules/MeasureTool.md
Normal file
254
doc/dsc/modules/MeasureTool.md
Normal file
@@ -0,0 +1,254 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys MeasureTool module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: MeasureTool Module
|
||||
---
|
||||
|
||||
# MeasureTool Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Measure Tool (Screen Ruler) utility, which
|
||||
measures pixels on your screen.
|
||||
|
||||
## Description
|
||||
|
||||
The `MeasureTool` module configures PowerToys Measure Tool (also known as
|
||||
Screen Ruler), a utility that allows you to measure the distance between two
|
||||
points on your screen in pixels. It's useful for designers, developers, and
|
||||
anyone who needs to measure UI elements or screen distances.
|
||||
|
||||
## Properties
|
||||
|
||||
The MeasureTool module supports the following configurable properties:
|
||||
|
||||
### ActivationShortcut
|
||||
|
||||
Sets the keyboard shortcut to activate the measure tool.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier
|
||||
- `ctrl` (boolean) - Ctrl key modifier
|
||||
- `alt` (boolean) - Alt key modifier
|
||||
- `shift` (boolean) - Shift key modifier
|
||||
- `code` (integer) - Virtual key code
|
||||
- `key` (string) - Key name
|
||||
|
||||
**Default:** `Win+Shift+M`
|
||||
|
||||
### ContinuousCapture
|
||||
|
||||
Controls whether continuous capture mode is enabled.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### DrawFeetOnCross
|
||||
|
||||
Controls whether measurement lines extend to screen edges.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### PerColorChannelEdgeDetection
|
||||
|
||||
Controls whether edge detection is per-color-channel or luminosity-based.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### PixelTolerance
|
||||
|
||||
Sets the pixel tolerance for edge detection (0-255).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `255`
|
||||
**Default:** `30`
|
||||
|
||||
### MeasureCrossColor
|
||||
|
||||
Sets the color of the measurement crosshair.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBBAA"` (with alpha)
|
||||
**Default:** `"#FF4500FF"`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure activation shortcut with direct execution
|
||||
|
||||
This example customizes the measure tool activation shortcut.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ActivationShortcut = @{
|
||||
win = $true
|
||||
ctrl = $false
|
||||
alt = $false
|
||||
shift = $true
|
||||
code = 77
|
||||
key = "M"
|
||||
}
|
||||
}
|
||||
name = "MeasureTool"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module MeasureTool `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure measurement appearance with DSC
|
||||
|
||||
This example customizes the crosshair color and measurement behavior.
|
||||
|
||||
```bash
|
||||
dsc config set --file measuretool-appearance.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# measuretool-appearance.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Measure Tool appearance
|
||||
type: Microsoft.PowerToys/MeasureToolSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
MeasureCrossColor: "#00FF00FF"
|
||||
DrawFeetOnCross: true
|
||||
ContinuousCapture: false
|
||||
name: MeasureTool
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Measure Tool with edge
|
||||
detection.
|
||||
|
||||
```bash
|
||||
winget configure winget-measuretool.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-measuretool.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Measure Tool
|
||||
type: Microsoft.PowerToys/MeasureToolSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PixelTolerance: 20
|
||||
PerColorChannelEdgeDetection: true
|
||||
DrawFeetOnCross: true
|
||||
name: MeasureTool
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - High contrast configuration
|
||||
|
||||
This example configures for high visibility measurements.
|
||||
|
||||
```bash
|
||||
dsc config set --file measuretool-highcontrast.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# measuretool-highcontrast.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: High contrast Measure Tool
|
||||
type: Microsoft.PowerToys/MeasureToolSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
MeasureCrossColor: "#FFFF00FF"
|
||||
DrawFeetOnCross: true
|
||||
name: MeasureTool
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Continuous capture mode
|
||||
|
||||
This example enables continuous capture for repeated measurements.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ContinuousCapture = $true
|
||||
PixelTolerance = 25
|
||||
}
|
||||
name = "MeasureTool"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module MeasureTool --input $config
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### UI/UX design
|
||||
|
||||
Configure for design work with precise measurements:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Design configuration
|
||||
type: Microsoft.PowerToys/MeasureToolSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PixelTolerance: 15
|
||||
DrawFeetOnCross: true
|
||||
name: MeasureTool
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Web development
|
||||
|
||||
Configure for layout debugging:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Developer configuration
|
||||
type: Microsoft.PowerToys/MeasureToolSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ContinuousCapture: true
|
||||
MeasureCrossColor: "#0078D7FF"
|
||||
name: MeasureTool
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [PowerAccent][03]
|
||||
- [PowerToys Screen Ruler Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./PowerAccent.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/screen-ruler
|
||||
276
doc/dsc/modules/MouseHighlighter.md
Normal file
276
doc/dsc/modules/MouseHighlighter.md
Normal file
@@ -0,0 +1,276 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys MouseHighlighter module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: MouseHighlighter Module
|
||||
---
|
||||
|
||||
# MouseHighlighter Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Mouse Highlighter utility, which highlights
|
||||
your mouse cursor and clicks.
|
||||
|
||||
## Description
|
||||
|
||||
The `MouseHighlighter` module configures PowerToys Mouse Highlighter, a
|
||||
utility that adds visual highlights to your mouse cursor and click locations.
|
||||
This is useful for presentations, tutorials, screen recordings, or
|
||||
accessibility purposes.
|
||||
|
||||
## Properties
|
||||
|
||||
The MouseHighlighter module supports the following configurable properties:
|
||||
|
||||
### ActivationShortcut
|
||||
|
||||
Sets the keyboard shortcut to toggle mouse highlighting.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier
|
||||
- `ctrl` (boolean) - Ctrl key modifier
|
||||
- `alt` (boolean) - Alt key modifier
|
||||
- `shift` (boolean) - Shift key modifier
|
||||
- `code` (integer) - Virtual key code
|
||||
- `key` (string) - Key name
|
||||
|
||||
**Default:** `Win+Shift+H`
|
||||
|
||||
### LeftButtonClickColor
|
||||
|
||||
Sets the color for left mouse button clicks.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBB"`
|
||||
**Default:** `"#FFFF00"` (yellow)
|
||||
|
||||
### RightButtonClickColor
|
||||
|
||||
Sets the color for right mouse button clicks.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBB"`
|
||||
**Default:** `"#0000FF"` (blue)
|
||||
|
||||
### HighlightOpacity
|
||||
|
||||
Sets the opacity of click highlights (0-100).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `100`
|
||||
**Default:** `160`
|
||||
|
||||
### HighlightRadius
|
||||
|
||||
Sets the radius of click highlights in pixels.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `1` to `500`
|
||||
**Default:** `20`
|
||||
|
||||
### HighlightFadeDelayMs
|
||||
|
||||
Sets how long highlights remain visible in milliseconds.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `10000`
|
||||
**Default:** `500`
|
||||
|
||||
### HighlightFadeDurationMs
|
||||
|
||||
Sets the duration of the highlight fade animation in milliseconds.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `10000`
|
||||
**Default:** `250`
|
||||
|
||||
### AutoActivate
|
||||
|
||||
Controls whether Mouse Highlighter activates automatically during presentations.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure highlight colors with direct execution
|
||||
|
||||
This example customizes the click highlight colors.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
LeftButtonClickColor = "#00FF00"
|
||||
RightButtonClickColor = "#FF0000"
|
||||
HighlightOpacity = 200
|
||||
}
|
||||
name = "MouseHighlighter"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module MouseHighlighter `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure highlight animation with DSC
|
||||
|
||||
This example customizes the animation timing and appearance.
|
||||
|
||||
```bash
|
||||
dsc config set --file mousehighlighter-animation.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# mousehighlighter-animation.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Mouse Highlighter animation
|
||||
type: Microsoft.PowerToys/MouseHighlighterSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
HighlightRadius: 30
|
||||
HighlightFadeDelayMs: 750
|
||||
HighlightFadeDurationMs: 400
|
||||
name: MouseHighlighter
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure for presentations with WinGet
|
||||
|
||||
This example installs PowerToys and configures Mouse Highlighter for
|
||||
presentations.
|
||||
|
||||
```bash
|
||||
winget configure winget-mousehighlighter.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-mousehighlighter.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Mouse Highlighter for presentations
|
||||
type: Microsoft.PowerToys/MouseHighlighterSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LeftButtonClickColor: "#FFD700"
|
||||
RightButtonClickColor: "#FF4500"
|
||||
HighlightOpacity: 220
|
||||
HighlightRadius: 25
|
||||
AutoActivate: true
|
||||
name: MouseHighlighter
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Subtle highlighting
|
||||
|
||||
This example configures subtle, less distracting highlights.
|
||||
|
||||
```bash
|
||||
dsc config set --file mousehighlighter-subtle.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# mousehighlighter-subtle.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Subtle mouse highlighting
|
||||
type: Microsoft.PowerToys/MouseHighlighterSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
HighlightOpacity: 100
|
||||
HighlightRadius: 15
|
||||
HighlightFadeDelayMs: 300
|
||||
name: MouseHighlighter
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - High visibility for accessibility
|
||||
|
||||
This example configures high-contrast, long-lasting highlights.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
LeftButtonClickColor = "#FFFFFF"
|
||||
RightButtonClickColor = "#FF0000"
|
||||
HighlightOpacity = 255
|
||||
HighlightRadius = 40
|
||||
HighlightFadeDelayMs = 1500
|
||||
HighlightFadeDurationMs = 500
|
||||
}
|
||||
name = "MouseHighlighter"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module MouseHighlighter --input $config
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Presentations and demos
|
||||
|
||||
Configure for clear visibility during presentations:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Presentation highlighting
|
||||
type: Microsoft.PowerToys/MouseHighlighterSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LeftButtonClickColor: "#FFD700"
|
||||
HighlightOpacity: 200
|
||||
HighlightRadius: 25
|
||||
AutoActivate: true
|
||||
name: MouseHighlighter
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Screen recording
|
||||
|
||||
Configure for video tutorials and recordings:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Recording configuration
|
||||
type: Microsoft.PowerToys/MouseHighlighterSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
HighlightOpacity: 180
|
||||
HighlightFadeDelayMs: 600
|
||||
name: MouseHighlighter
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [MousePointerCrosshairs][03]
|
||||
- [PowerToys Mouse Utilities Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./MousePointerCrosshairs.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/mouse-utilities
|
||||
220
doc/dsc/modules/MouseJump.md
Normal file
220
doc/dsc/modules/MouseJump.md
Normal file
@@ -0,0 +1,220 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys MouseJump module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: MouseJump Module
|
||||
---
|
||||
|
||||
# MouseJump Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Mouse Jump utility, which enables quick
|
||||
navigation across large or multiple displays.
|
||||
|
||||
## Description
|
||||
|
||||
The `MouseJump` module configures PowerToys Mouse Jump, a utility that
|
||||
provides a miniature preview of all your displays, allowing you to quickly
|
||||
jump your mouse cursor to any location. This is particularly useful with
|
||||
large monitors or multi-monitor setups.
|
||||
|
||||
## Properties
|
||||
|
||||
The MouseJump module supports the following configurable properties:
|
||||
|
||||
### ActivationShortcut
|
||||
|
||||
Sets the keyboard shortcut to activate Mouse Jump.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier
|
||||
- `ctrl` (boolean) - Ctrl key modifier
|
||||
- `alt` (boolean) - Alt key modifier
|
||||
- `shift` (boolean) - Shift key modifier
|
||||
- `code` (integer) - Virtual key code
|
||||
- `key` (string) - Key name
|
||||
|
||||
**Default:** `Win+Shift+D`
|
||||
|
||||
### ThumbnailSize
|
||||
|
||||
Sets the size of the screen thumbnail preview.
|
||||
|
||||
**Type:** string
|
||||
**Allowed values:**
|
||||
|
||||
- `"small"` - Smaller thumbnail for faster performance
|
||||
- `"medium"` - Balanced size and performance
|
||||
- `"large"` - Larger thumbnail for better visibility
|
||||
|
||||
**Default:** `"medium"`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure activation shortcut with direct execution
|
||||
|
||||
This example customizes the Mouse Jump activation shortcut.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ActivationShortcut = @{
|
||||
win = $true
|
||||
ctrl = $false
|
||||
alt = $false
|
||||
shift = $true
|
||||
code = 68
|
||||
key = "D"
|
||||
}
|
||||
}
|
||||
name = "MouseJump"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module MouseJump `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure thumbnail size with DSC
|
||||
|
||||
This example sets a larger thumbnail for better visibility.
|
||||
|
||||
```bash
|
||||
dsc config set --file mousejump-size.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# mousejump-size.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Mouse Jump thumbnail
|
||||
type: Microsoft.PowerToys/MouseJumpSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ThumbnailSize: large
|
||||
name: MouseJump
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Mouse Jump for multi-monitor
|
||||
setups.
|
||||
|
||||
```bash
|
||||
winget configure winget-mousejump.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-mousejump.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Mouse Jump
|
||||
type: Microsoft.PowerToys/MouseJumpSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ThumbnailSize: medium
|
||||
name: MouseJump
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Performance-optimized configuration
|
||||
|
||||
This example uses a smaller thumbnail for better performance.
|
||||
|
||||
```bash
|
||||
dsc config set --file mousejump-performance.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# mousejump-performance.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Performance-optimized Mouse Jump
|
||||
type: Microsoft.PowerToys/MouseJumpSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ThumbnailSize: small
|
||||
name: MouseJump
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Large display configuration
|
||||
|
||||
This example configures for large or high-DPI displays.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ThumbnailSize = "large"
|
||||
}
|
||||
name = "MouseJump"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module MouseJump --input $config
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Multi-monitor workstations
|
||||
|
||||
Configure for efficient navigation across multiple displays:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Multi-monitor configuration
|
||||
type: Microsoft.PowerToys/MouseJumpSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ThumbnailSize: medium
|
||||
name: MouseJump
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Large displays
|
||||
|
||||
Configure for ultra-wide or 4K+ displays:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Large display configuration
|
||||
type: Microsoft.PowerToys/MouseJumpSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ThumbnailSize: large
|
||||
name: MouseJump
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [FindMyMouse][03]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./FindMyMouse.md
|
||||
290
doc/dsc/modules/MousePointerCrosshairs.md
Normal file
290
doc/dsc/modules/MousePointerCrosshairs.md
Normal file
@@ -0,0 +1,290 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys MousePointerCrosshairs module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: MousePointerCrosshairs Module
|
||||
---
|
||||
|
||||
# MousePointerCrosshairs Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Mouse Pointer Crosshairs utility, which
|
||||
displays crosshairs centered on your mouse pointer.
|
||||
|
||||
## Description
|
||||
|
||||
The `MousePointerCrosshairs` module configures PowerToys Mouse Pointer
|
||||
Crosshairs, a utility that displays customizable crosshairs overlaid on your
|
||||
screen, centered on the mouse cursor. This is useful for presentations,
|
||||
design work, or improving cursor visibility.
|
||||
|
||||
## Properties
|
||||
|
||||
The MousePointerCrosshairs module supports the following configurable properties:
|
||||
|
||||
### ActivationShortcut
|
||||
|
||||
Sets the keyboard shortcut to toggle crosshairs display.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier
|
||||
- `ctrl` (boolean) - Ctrl key modifier
|
||||
- `alt` (boolean) - Alt key modifier
|
||||
- `shift` (boolean) - Shift key modifier
|
||||
- `code` (integer) - Virtual key code
|
||||
- `key` (string) - Key name
|
||||
|
||||
**Default:** `Win+Alt+P`
|
||||
|
||||
### CrosshairsColor
|
||||
|
||||
Sets the color of the crosshairs.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBB"`
|
||||
**Default:** `"#FF0000"` (red)
|
||||
|
||||
### CrosshairsOpacity
|
||||
|
||||
Sets the opacity of the crosshairs (0-100).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `100`
|
||||
**Default:** `75`
|
||||
|
||||
### CrosshairsRadius
|
||||
|
||||
Sets the length of the crosshair lines in pixels.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `9999`
|
||||
**Default:** `100`
|
||||
|
||||
### CrosshairsThickness
|
||||
|
||||
Sets the thickness of the crosshair lines in pixels.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `1` to `50`
|
||||
**Default:** `5`
|
||||
|
||||
### CrosshairsBorderColor
|
||||
|
||||
Sets the border color of the crosshairs.
|
||||
|
||||
**Type:** string (hex color)
|
||||
**Format:** `"#RRGGBB"`
|
||||
**Default:** `"#FFFFFF"` (white)
|
||||
|
||||
### CrosshairsBorderSize
|
||||
|
||||
Sets the width of the crosshair border in pixels.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `50`
|
||||
**Default:** `1`
|
||||
|
||||
### CrosshairsAutoHide
|
||||
|
||||
Controls whether crosshairs automatically hide when the mouse is not moving.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### CrosshairsIsFixedLengthEnabled
|
||||
|
||||
Controls whether crosshairs have a fixed length or extend to screen edges.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### CrosshairsFixedLength
|
||||
|
||||
Sets the fixed length of crosshairs when fixed length mode is enabled.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `9999`
|
||||
**Default:** `100`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure crosshair appearance with direct execution
|
||||
|
||||
This example customizes the crosshair color and size.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
CrosshairsColor = "#00FF00"
|
||||
CrosshairsOpacity = 85
|
||||
CrosshairsThickness = 3
|
||||
CrosshairsRadius = 150
|
||||
}
|
||||
name = "MousePointerCrosshairs"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module MousePointerCrosshairs `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure with border with DSC
|
||||
|
||||
This example adds a border to the crosshairs for better visibility.
|
||||
|
||||
```bash
|
||||
dsc config set --file mousecrosshairs-border.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# mousecrosshairs-border.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure crosshairs with border
|
||||
type: Microsoft.PowerToys/MousePointerCrosshairsSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
CrosshairsColor: "#FF0000"
|
||||
CrosshairsBorderColor: "#FFFFFF"
|
||||
CrosshairsBorderSize: 2
|
||||
CrosshairsThickness: 4
|
||||
name: MousePointerCrosshairs
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures crosshairs for presentations.
|
||||
|
||||
```bash
|
||||
winget configure winget-mousecrosshairs.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-mousecrosshairs.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Mouse Crosshairs
|
||||
type: Microsoft.PowerToys/MousePointerCrosshairsSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
CrosshairsColor: "#FFFF00"
|
||||
CrosshairsOpacity: 90
|
||||
CrosshairsRadius: 120
|
||||
CrosshairsThickness: 5
|
||||
CrosshairsBorderSize: 2
|
||||
name: MousePointerCrosshairs
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Full-screen crosshairs
|
||||
|
||||
This example configures crosshairs that extend to screen edges.
|
||||
|
||||
```bash
|
||||
dsc config set --file mousecrosshairs-fullscreen.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# mousecrosshairs-fullscreen.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Full-screen crosshairs
|
||||
type: Microsoft.PowerToys/MousePointerCrosshairsSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
CrosshairsIsFixedLengthEnabled: false
|
||||
CrosshairsOpacity: 60
|
||||
name: MousePointerCrosshairs
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Subtle crosshairs with auto-hide
|
||||
|
||||
This example creates subtle crosshairs that hide when idle.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
CrosshairsColor = "#FFFFFF"
|
||||
CrosshairsOpacity = 50
|
||||
CrosshairsThickness = 2
|
||||
CrosshairsRadius = 80
|
||||
CrosshairsAutoHide = $true
|
||||
}
|
||||
name = "MousePointerCrosshairs"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module MousePointerCrosshairs --input $config
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Presentations and demos
|
||||
|
||||
Configure for clear cursor tracking during presentations:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Presentation crosshairs
|
||||
type: Microsoft.PowerToys/MousePointerCrosshairsSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
CrosshairsColor: "#FFFF00"
|
||||
CrosshairsOpacity: 85
|
||||
CrosshairsRadius: 150
|
||||
name: MousePointerCrosshairs
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Design and alignment
|
||||
|
||||
Configure for precise alignment work:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Design crosshairs
|
||||
type: Microsoft.PowerToys/MousePointerCrosshairsSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
CrosshairsIsFixedLengthEnabled: false
|
||||
CrosshairsThickness: 1
|
||||
CrosshairsOpacity: 70
|
||||
name: MousePointerCrosshairs
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [MouseHighlighter][03]
|
||||
- [PowerToys Mouse Utilities Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./MouseHighlighter.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/mouse-utilities
|
||||
200
doc/dsc/modules/Peek.md
Normal file
200
doc/dsc/modules/Peek.md
Normal file
@@ -0,0 +1,200 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys Peek module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: Peek Module
|
||||
---
|
||||
|
||||
# Peek Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Peek utility, a quick file preview tool.
|
||||
|
||||
## Description
|
||||
|
||||
The `Peek` module configures PowerToys Peek, a utility that provides quick
|
||||
file previews without opening files. Activate it with a keyboard shortcut to
|
||||
preview documents, images, videos, and more in a popup window.
|
||||
|
||||
## Properties
|
||||
|
||||
The Peek module supports the following configurable properties:
|
||||
|
||||
### ActivationShortcut
|
||||
|
||||
Sets the keyboard shortcut to activate Peek for the selected file.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier
|
||||
- `ctrl` (boolean) - Ctrl key modifier
|
||||
- `alt` (boolean) - Alt key modifier
|
||||
- `shift` (boolean) - Shift key modifier
|
||||
- `code` (integer) - Virtual key code
|
||||
- `key` (string) - Key name
|
||||
|
||||
**Default:** `Ctrl+Space`
|
||||
|
||||
### CloseAfterLosingFocus
|
||||
|
||||
Controls whether Peek window closes when it loses focus.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure activation shortcut with direct execution
|
||||
|
||||
This example customizes the Peek activation shortcut.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ActivationShortcut = @{
|
||||
win = $false
|
||||
ctrl = $true
|
||||
alt = $false
|
||||
shift = $false
|
||||
code = 32
|
||||
key = "Space"
|
||||
}
|
||||
}
|
||||
name = "Peek"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module Peek --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure focus behavior with DSC
|
||||
|
||||
This example configures Peek to remain open after losing focus.
|
||||
|
||||
```bash
|
||||
dsc config set --file peek-focus.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# peek-focus.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Peek focus behavior
|
||||
type: Microsoft.PowerToys/PeekSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
CloseAfterLosingFocus: false
|
||||
name: Peek
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Peek.
|
||||
|
||||
```bash
|
||||
winget configure winget-peek.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-peek.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Peek
|
||||
type: Microsoft.PowerToys/PeekSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
CloseAfterLosingFocus: true
|
||||
name: Peek
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Alternative activation shortcut
|
||||
|
||||
This example uses Ctrl+Shift+Space as the activation shortcut.
|
||||
|
||||
```bash
|
||||
dsc config set --file peek-altkey.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# peek-altkey.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Alternative Peek shortcut
|
||||
type: Microsoft.PowerToys/PeekSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ActivationShortcut:
|
||||
win: false
|
||||
ctrl: true
|
||||
alt: false
|
||||
shift: true
|
||||
code: 32
|
||||
key: Space
|
||||
name: Peek
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### File browsing
|
||||
|
||||
Configure for quick file preview during browsing:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: File browsing configuration
|
||||
type: Microsoft.PowerToys/PeekSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
CloseAfterLosingFocus: true
|
||||
name: Peek
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Content review
|
||||
|
||||
Configure for extended content review:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Review configuration
|
||||
type: Microsoft.PowerToys/PeekSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
CloseAfterLosingFocus: false
|
||||
name: Peek
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [ShortcutGuide][03]
|
||||
- [PowerToys Peek Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./ShortcutGuide.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/peek
|
||||
257
doc/dsc/modules/PowerAccent.md
Normal file
257
doc/dsc/modules/PowerAccent.md
Normal file
@@ -0,0 +1,257 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys PowerAccent module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: PowerAccent Module
|
||||
---
|
||||
|
||||
# PowerAccent Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Power Accent utility, a quick accent character selector.
|
||||
|
||||
## Description
|
||||
|
||||
The `PowerAccent` module configures PowerToys Power Accent (Quick Accent), a
|
||||
utility that provides quick access to accented characters. Hold down a key
|
||||
and use arrow keys or numbers to select from available accent variations.
|
||||
|
||||
## Properties
|
||||
|
||||
The PowerAccent module supports the following configurable properties:
|
||||
|
||||
### ActivationKey
|
||||
|
||||
Sets which key triggers the accent selection.
|
||||
|
||||
**Type:** string
|
||||
**Allowed values:**
|
||||
|
||||
- `"LeftRightArrow"` - Hold left or right arrow keys
|
||||
- `"Space"` - Hold spacebar
|
||||
- `"Both"` - Hold either left/right arrows or spacebar
|
||||
|
||||
**Default:** `"Both"`
|
||||
|
||||
### InputTime
|
||||
|
||||
Sets how long the activation key must be held (in milliseconds) before showing accents.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `100` to `1000`
|
||||
**Default:** `300`
|
||||
|
||||
### ExcludedApps
|
||||
|
||||
List of applications where Power Accent is disabled.
|
||||
|
||||
**Type:** string (newline-separated list of executable names)
|
||||
|
||||
### ToolbarPosition
|
||||
|
||||
Sets the position of the accent selection toolbar.
|
||||
|
||||
**Type:** string
|
||||
**Allowed values:**
|
||||
|
||||
- `"Top"` - Above the cursor
|
||||
- `"Bottom"` - Below the cursor
|
||||
- `"Left"` - To the left of cursor
|
||||
- `"Right"` - To the right of cursor
|
||||
- `"Center"` - Centered on screen
|
||||
|
||||
**Default:** `"Top"`
|
||||
|
||||
### ShowUnicodeDescription
|
||||
|
||||
Controls whether Unicode descriptions are shown for each accent character.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### SortByUsageFrequency
|
||||
|
||||
Controls whether accent characters are sorted by usage frequency.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### StartSelectionFromTheLeft
|
||||
|
||||
Controls whether selection starts from the left side.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure activation method with direct execution
|
||||
|
||||
This example sets spacebar as the activation key.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ActivationKey = "Space"
|
||||
InputTime = 250
|
||||
}
|
||||
name = "PowerAccent"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module PowerAccent `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure toolbar appearance with DSC
|
||||
|
||||
This example customizes the toolbar position and display options.
|
||||
|
||||
```bash
|
||||
dsc config set --file poweraccent-toolbar.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# poweraccent-toolbar.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Power Accent toolbar
|
||||
type: Microsoft.PowerToys/PowerAccentSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ToolbarPosition: Bottom
|
||||
ShowUnicodeDescription: true
|
||||
SortByUsageFrequency: true
|
||||
name: PowerAccent
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Power Accent for multilingual
|
||||
typing.
|
||||
|
||||
```bash
|
||||
winget configure winget-poweraccent.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-poweraccent.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Power Accent
|
||||
type: Microsoft.PowerToys/PowerAccentSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ActivationKey: Space
|
||||
InputTime: 300
|
||||
ToolbarPosition: Top
|
||||
SortByUsageFrequency: true
|
||||
name: PowerAccent
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Fast activation configuration
|
||||
|
||||
This example configures for quick accent selection.
|
||||
|
||||
```bash
|
||||
dsc config set --file poweraccent-fast.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# poweraccent-fast.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Fast accent activation
|
||||
type: Microsoft.PowerToys/PowerAccentSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
InputTime: 150
|
||||
SortByUsageFrequency: true
|
||||
name: PowerAccent
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Exclude applications
|
||||
|
||||
This example excludes specific applications from Power Accent.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ExcludedApps = "notepad.exe`nWordPad.exe"
|
||||
}
|
||||
name = "PowerAccent"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module PowerAccent --input $config
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Multilingual content creation
|
||||
|
||||
Configure for efficient multilingual typing:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Multilingual configuration
|
||||
type: Microsoft.PowerToys/PowerAccentSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ActivationKey: Space
|
||||
SortByUsageFrequency: true
|
||||
ShowUnicodeDescription: false
|
||||
name: PowerAccent
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Language learning
|
||||
|
||||
Configure for language learning with Unicode descriptions:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Learning configuration
|
||||
type: Microsoft.PowerToys/PowerAccentSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ShowUnicodeDescription: true
|
||||
InputTime: 400
|
||||
name: PowerAccent
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [Workspaces][03]
|
||||
- [PowerToys Quick Accent Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./Workspaces.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/quick-accent
|
||||
197
doc/dsc/modules/PowerOCR.md
Normal file
197
doc/dsc/modules/PowerOCR.md
Normal file
@@ -0,0 +1,197 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys PowerOCR module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: PowerOCR Module
|
||||
---
|
||||
|
||||
# PowerOCR Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Power OCR (Text Extractor) utility, which
|
||||
extracts text from images and screen regions.
|
||||
|
||||
## Description
|
||||
|
||||
The `PowerOCR` module configures PowerToys Power OCR (Text Extractor), a
|
||||
utility that uses optical character recognition (OCR) to extract text from
|
||||
any screen region and copy it to the clipboard. It's useful for capturing
|
||||
text from images, videos, PDFs, or any on-screen content.
|
||||
|
||||
## Properties
|
||||
|
||||
The PowerOCR module supports the following configurable properties:
|
||||
|
||||
### ActivationShortcut
|
||||
|
||||
Sets the keyboard shortcut to activate text extraction.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier
|
||||
- `ctrl` (boolean) - Ctrl key modifier
|
||||
- `alt` (boolean) - Alt key modifier
|
||||
- `shift` (boolean) - Shift key modifier
|
||||
- `code` (integer) - Virtual key code
|
||||
- `key` (string) - Key name
|
||||
|
||||
**Default:** `Win+Shift+T`
|
||||
|
||||
### PreferredLanguage
|
||||
|
||||
Sets the preferred language for OCR recognition.
|
||||
|
||||
**Type:** string
|
||||
**Default:** System language
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure activation shortcut with direct execution
|
||||
|
||||
This example customizes the OCR activation shortcut.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ActivationShortcut = @{
|
||||
win = $true
|
||||
ctrl = $false
|
||||
alt = $false
|
||||
shift = $true
|
||||
code = 84
|
||||
key = "T"
|
||||
}
|
||||
}
|
||||
name = "PowerOCR"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module PowerOCR `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure language with DSC
|
||||
|
||||
This example sets the preferred OCR language.
|
||||
|
||||
```bash
|
||||
dsc config set --file powerocr-language.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# powerocr-language.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Power OCR language
|
||||
type: Microsoft.PowerToys/PowerOCRSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PreferredLanguage: en-US
|
||||
name: PowerOCR
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Power OCR.
|
||||
|
||||
```bash
|
||||
winget configure winget-powerocr.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-powerocr.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Power OCR
|
||||
type: Microsoft.PowerToys/PowerOCRSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PreferredLanguage: en-US
|
||||
name: PowerOCR
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Multilingual configuration
|
||||
|
||||
This example configures for multilingual text extraction.
|
||||
|
||||
```bash
|
||||
dsc config set --file powerocr-multilingual.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# powerocr-multilingual.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Multilingual OCR
|
||||
type: Microsoft.PowerToys/PowerOCRSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PreferredLanguage: fr-FR
|
||||
name: PowerOCR
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Document digitization
|
||||
|
||||
Configure for extracting text from documents:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Document OCR
|
||||
type: Microsoft.PowerToys/PowerOCRSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PreferredLanguage: en-US
|
||||
name: PowerOCR
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### International content
|
||||
|
||||
Configure for multilingual content extraction:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Multilingual OCR
|
||||
type: Microsoft.PowerToys/PowerOCRSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PreferredLanguage: es-ES
|
||||
name: PowerOCR
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [ZoomIt][03]
|
||||
- [PowerToys Text Extractor Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./ZoomIt.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/text-extractor
|
||||
230
doc/dsc/modules/PowerRename.md
Normal file
230
doc/dsc/modules/PowerRename.md
Normal file
@@ -0,0 +1,230 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys PowerRename module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: PowerRename Module
|
||||
---
|
||||
|
||||
# PowerRename Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Power Rename utility, a bulk file and folder renaming tool.
|
||||
|
||||
## Description
|
||||
|
||||
The `PowerRename` module configures PowerToys Power Rename, a Windows shell
|
||||
extension that enables bulk renaming of files and folders with advanced
|
||||
features like regular expressions, preview, and undo functionality. It
|
||||
integrates with the Windows Explorer context menu.
|
||||
|
||||
## Properties
|
||||
|
||||
The PowerRename module supports the following configurable properties:
|
||||
|
||||
### MRUEnabled
|
||||
|
||||
Controls whether the most recently used (MRU) search and replace terms are saved.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### MaxMRUSize
|
||||
|
||||
Sets the maximum number of MRU entries to remember.
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `20`
|
||||
**Default:** `10`
|
||||
|
||||
### ShowIcon
|
||||
|
||||
Controls whether the Power Rename icon appears in the Explorer context menu.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `true`
|
||||
|
||||
### ExtendedContextMenuOnly
|
||||
|
||||
Controls whether Power Rename appears only in the extended context menu (Shift+right-click).
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### UseBoostLib
|
||||
|
||||
Controls whether the Boost library is used for regular expression processing.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure MRU settings with direct execution
|
||||
|
||||
This example configures the most recently used list behavior.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
MRUEnabled = $true
|
||||
MaxMRUSize = 15
|
||||
}
|
||||
name = "PowerRename"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module PowerRename --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure context menu with DSC
|
||||
|
||||
This example configures Power Rename to appear in the extended context menu
|
||||
only.
|
||||
|
||||
```bash
|
||||
dsc config set --file powerrename-context.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# powerrename-context.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Power Rename context menu
|
||||
type: Microsoft.PowerToys/PowerRenameSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ExtendedContextMenuOnly: true
|
||||
ShowIcon: true
|
||||
name: PowerRename
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Power Rename.
|
||||
|
||||
```bash
|
||||
winget configure winget-powerrename.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-powerrename.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Power Rename
|
||||
type: Microsoft.PowerToys/PowerRenameSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
MRUEnabled: true
|
||||
MaxMRUSize: 20
|
||||
ShowIcon: true
|
||||
UseBoostLib: true
|
||||
name: PowerRename
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Clean context menu configuration
|
||||
|
||||
This example minimizes context menu clutter.
|
||||
|
||||
```bash
|
||||
dsc config set --file powerrename-minimal.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# powerrename-minimal.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Minimal context menu
|
||||
type: Microsoft.PowerToys/PowerRenameSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ExtendedContextMenuOnly: true
|
||||
ShowIcon: false
|
||||
name: PowerRename
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Advanced regex configuration
|
||||
|
||||
This example enables the Boost library for advanced regex features.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
UseBoostLib = $true
|
||||
MRUEnabled = $true
|
||||
MaxMRUSize = 15
|
||||
}
|
||||
name = "PowerRename"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module PowerRename --input $config
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Content management
|
||||
|
||||
Configure for frequent file renaming tasks:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Content management
|
||||
type: Microsoft.PowerToys/PowerRenameSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
MRUEnabled: true
|
||||
MaxMRUSize: 20
|
||||
ShowIcon: true
|
||||
name: PowerRename
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Clean interface
|
||||
|
||||
Configure for minimal context menu presence:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Clean interface
|
||||
type: Microsoft.PowerToys/PowerRenameSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ExtendedContextMenuOnly: true
|
||||
name: PowerRename
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [AdvancedPaste][03]
|
||||
- [PowerToys PowerRename Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./AdvancedPaste.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/powerrename
|
||||
173
doc/dsc/modules/RegistryPreview.md
Normal file
173
doc/dsc/modules/RegistryPreview.md
Normal file
@@ -0,0 +1,173 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys RegistryPreview module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: RegistryPreview Module
|
||||
---
|
||||
|
||||
# RegistryPreview Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Registry Preview utility, which visualizes and edits Windows registry files (.reg).
|
||||
|
||||
## Description
|
||||
|
||||
The `RegistryPreview` module configures PowerToys Registry Preview, a utility
|
||||
that provides a visual preview and editing interface for Windows registry
|
||||
(.reg) files. It helps you understand and safely edit registry files before
|
||||
applying them to your system.
|
||||
|
||||
## Properties
|
||||
|
||||
The RegistryPreview module supports the following configurable properties:
|
||||
|
||||
### DefaultRegApp
|
||||
|
||||
Controls whether Registry Preview is set as the default application for .reg files.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Set as default .reg handler with direct execution
|
||||
|
||||
This example sets Registry Preview as the default application for .reg files.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
DefaultRegApp = $true
|
||||
}
|
||||
name = "RegistryPreview"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module RegistryPreview --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure with DSC
|
||||
|
||||
This example configures Registry Preview as the default handler.
|
||||
|
||||
```bash
|
||||
dsc config set --file registrypreview-default.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# registrypreview-default.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Set Registry Preview as default
|
||||
type: Microsoft.PowerToys/RegistryPreviewSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
DefaultRegApp: true
|
||||
name: RegistryPreview
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and sets Registry Preview as the default .reg
|
||||
handler.
|
||||
|
||||
```bash
|
||||
winget configure winget-registrypreview.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-registrypreview.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Registry Preview
|
||||
type: Microsoft.PowerToys/RegistryPreviewSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
DefaultRegApp: true
|
||||
name: RegistryPreview
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Disable as default handler
|
||||
|
||||
This example ensures Registry Preview is not the default .reg handler.
|
||||
|
||||
```bash
|
||||
dsc config set --file registrypreview-notdefault.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# registrypreview-notdefault.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Do not use as default
|
||||
type: Microsoft.PowerToys/RegistryPreviewSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
DefaultRegApp: false
|
||||
name: RegistryPreview
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### System administration
|
||||
|
||||
Configure as default for safe registry file handling:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Admin configuration
|
||||
type: Microsoft.PowerToys/RegistryPreviewSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
DefaultRegApp: true
|
||||
name: RegistryPreview
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Optional tool
|
||||
|
||||
Keep as optional tool without default file association:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Optional tool
|
||||
type: Microsoft.PowerToys/RegistryPreviewSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
DefaultRegApp: false
|
||||
name: RegistryPreview
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [FileLocksmith][03]
|
||||
- [PowerToys Registry Preview Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./FileLocksmith.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/registry-preview
|
||||
259
doc/dsc/modules/ShortcutGuide.md
Normal file
259
doc/dsc/modules/ShortcutGuide.md
Normal file
@@ -0,0 +1,259 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys ShortcutGuide module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: ShortcutGuide Module
|
||||
---
|
||||
|
||||
# ShortcutGuide Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Shortcut Guide utility, which displays available keyboard shortcuts.
|
||||
|
||||
## Description
|
||||
|
||||
The `ShortcutGuide` module configures PowerToys Shortcut Guide, a utility that
|
||||
displays an overlay showing available Windows keyboard shortcuts when you hold
|
||||
the Windows key. It helps users discover and learn keyboard shortcuts.
|
||||
|
||||
## Properties
|
||||
|
||||
The ShortcutGuide module supports the following configurable properties:
|
||||
|
||||
### OpenShortcutGuide
|
||||
|
||||
Sets the keyboard shortcut or method to open the shortcut guide.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier
|
||||
- `ctrl` (boolean) - Ctrl key modifier
|
||||
- `alt` (boolean) - Alt key modifier
|
||||
- `shift` (boolean) - Shift key modifier
|
||||
- `code` (integer) - Virtual key code
|
||||
- `key` (string) - Key name
|
||||
|
||||
**Default:** Hold Windows key for 900ms
|
||||
|
||||
### OverlayOpacity
|
||||
|
||||
Sets the opacity of the shortcut guide overlay (0-100).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `0` to `100`
|
||||
**Default:** `90`
|
||||
|
||||
### Theme
|
||||
|
||||
Sets the theme for the shortcut guide.
|
||||
|
||||
**Type:** string
|
||||
**Allowed values:** `"light"`, `"dark"`, `"system"`
|
||||
**Default:** `"dark"`
|
||||
|
||||
### PressTime
|
||||
|
||||
Sets how long the Windows key must be held before showing the guide (in milliseconds).
|
||||
|
||||
**Type:** integer
|
||||
**Range:** `100` to `10000`
|
||||
**Default:** `900`
|
||||
|
||||
### ExcludedApps
|
||||
|
||||
List of applications where Shortcut Guide is disabled.
|
||||
|
||||
**Type:** string (newline-separated list of executable names)
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure activation time with direct execution
|
||||
|
||||
This example sets a faster activation time for the shortcut guide.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
PressTime = 600
|
||||
}
|
||||
name = "ShortcutGuide"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module ShortcutGuide `
|
||||
--input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure appearance with DSC
|
||||
|
||||
This example customizes the overlay appearance.
|
||||
|
||||
```bash
|
||||
dsc config set --file shortcutguide-appearance.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# shortcutguide-appearance.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Shortcut Guide appearance
|
||||
type: Microsoft.PowerToys/ShortcutGuideSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
OverlayOpacity: 95
|
||||
Theme: light
|
||||
name: ShortcutGuide
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Shortcut Guide.
|
||||
|
||||
```bash
|
||||
winget configure winget-shortcutguide.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-shortcutguide.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Shortcut Guide
|
||||
type: Microsoft.PowerToys/ShortcutGuideSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PressTime: 700
|
||||
OverlayOpacity: 90
|
||||
Theme: dark
|
||||
name: ShortcutGuide
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Quick activation
|
||||
|
||||
This example configures for quick activation with a short press time.
|
||||
|
||||
```bash
|
||||
dsc config set --file shortcutguide-quick.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# shortcutguide-quick.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Quick activation
|
||||
type: Microsoft.PowerToys/ShortcutGuideSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PressTime: 400
|
||||
name: ShortcutGuide
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - High opacity for visibility
|
||||
|
||||
This example maximizes opacity for better visibility.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
OverlayOpacity = 100
|
||||
Theme = "dark"
|
||||
}
|
||||
name = "ShortcutGuide"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module ShortcutGuide --input $config
|
||||
```
|
||||
|
||||
### Example 6 - Exclude applications
|
||||
|
||||
This example excludes Shortcut Guide from specific applications.
|
||||
|
||||
```bash
|
||||
dsc config set --file shortcutguide-exclusions.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# shortcutguide-exclusions.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Exclude apps
|
||||
type: Microsoft.PowerToys/ShortcutGuideSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ExcludedApps: |
|
||||
Game.exe
|
||||
FullScreenApp.exe
|
||||
name: ShortcutGuide
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### New users
|
||||
|
||||
Configure for easy keyboard shortcut discovery:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: New user configuration
|
||||
type: Microsoft.PowerToys/ShortcutGuideSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PressTime: 800
|
||||
OverlayOpacity: 95
|
||||
name: ShortcutGuide
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Power users
|
||||
|
||||
Configure for quick access without accidental activation:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Power user configuration
|
||||
type: Microsoft.PowerToys/ShortcutGuideSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
PressTime: 1200
|
||||
OverlayOpacity: 85
|
||||
name: ShortcutGuide
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [Peek][03]
|
||||
- [PowerToys Keyboard Shortcut Guide Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./Peek.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/shortcut-guide
|
||||
238
doc/dsc/modules/Workspaces.md
Normal file
238
doc/dsc/modules/Workspaces.md
Normal file
@@ -0,0 +1,238 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys Workspaces module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: Workspaces Module
|
||||
---
|
||||
|
||||
# Workspaces Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the Workspaces utility, which launches application sets and arranges windows.
|
||||
|
||||
## Description
|
||||
|
||||
The `Workspaces` module configures PowerToys Workspaces, a utility that allows
|
||||
you to save and restore sets of applications with their window positions. It
|
||||
enables you to quickly switch between different work contexts by launching and
|
||||
arranging multiple applications at once.
|
||||
|
||||
## Properties
|
||||
|
||||
The Workspaces module supports the following configurable properties:
|
||||
|
||||
### LaunchHotkey
|
||||
|
||||
Sets the keyboard shortcut to launch the Workspaces editor.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier
|
||||
- `ctrl` (boolean) - Ctrl key modifier
|
||||
- `alt` (boolean) - Alt key modifier
|
||||
- `shift` (boolean) - Shift key modifier
|
||||
- `code` (integer) - Virtual key code
|
||||
- `key` (string) - Key name
|
||||
|
||||
**Default:** `Win+Shift+;` (VK code 186)
|
||||
|
||||
### MoveExistingWindows
|
||||
|
||||
Controls whether existing application windows are moved when launching a workspace.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
### SpanZonesAcrossMonitors
|
||||
|
||||
Controls whether workspace zones can span across multiple monitors.
|
||||
|
||||
**Type:** boolean
|
||||
**Default:** `false`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure launch hotkey with direct execution
|
||||
|
||||
This example sets a custom hotkey to launch the Workspaces editor.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
LaunchHotkey = @{
|
||||
win = $true
|
||||
ctrl = $true
|
||||
alt = $false
|
||||
shift = $false
|
||||
code = 87
|
||||
key = "W"
|
||||
}
|
||||
}
|
||||
name = "Workspaces"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module Workspaces --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure window behavior with DSC
|
||||
|
||||
This example enables moving existing windows when launching workspaces.
|
||||
|
||||
```bash
|
||||
dsc config set --file workspaces-behavior.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# workspaces-behavior.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Workspaces window behavior
|
||||
type: Microsoft.PowerToys/WorkspacesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
MoveExistingWindows: true
|
||||
SpanZonesAcrossMonitors: false
|
||||
name: Workspaces
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures Workspaces.
|
||||
|
||||
```bash
|
||||
winget configure winget-workspaces.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-workspaces.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure Workspaces
|
||||
type: Microsoft.PowerToys/WorkspacesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
LaunchHotkey:
|
||||
win: true
|
||||
ctrl: false
|
||||
alt: false
|
||||
shift: true
|
||||
code: 186
|
||||
key: ";"
|
||||
MoveExistingWindows: true
|
||||
name: Workspaces
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Multi-monitor setup
|
||||
|
||||
This example configures for multi-monitor workspace management.
|
||||
|
||||
```bash
|
||||
dsc config set --file workspaces-multimonitor.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# workspaces-multimonitor.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Multi-monitor configuration
|
||||
type: Microsoft.PowerToys/WorkspacesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
SpanZonesAcrossMonitors: true
|
||||
MoveExistingWindows: true
|
||||
name: Workspaces
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 5 - Simple hotkey
|
||||
|
||||
This example sets a simple single-key hotkey combination.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
LaunchHotkey = @{
|
||||
win = $true
|
||||
ctrl = $false
|
||||
alt = $true
|
||||
shift = $false
|
||||
code = 192
|
||||
key = "~"
|
||||
}
|
||||
}
|
||||
name = "Workspaces"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module Workspaces --input $config
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Development environments
|
||||
|
||||
Configure for quick switching between development workspaces:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Development workspace
|
||||
type: Microsoft.PowerToys/WorkspacesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
MoveExistingWindows: true
|
||||
SpanZonesAcrossMonitors: true
|
||||
name: Workspaces
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Single monitor usage
|
||||
|
||||
Configure for single-monitor workflow:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Single monitor setup
|
||||
type: Microsoft.PowerToys/WorkspacesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
SpanZonesAcrossMonitors: false
|
||||
MoveExistingWindows: false
|
||||
name: Workspaces
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [ColorPicker Module][03] - For additional PowerToys configuration
|
||||
- [PowerToys Workspaces Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./ColorPicker.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/workspaces
|
||||
215
doc/dsc/modules/ZoomIt.md
Normal file
215
doc/dsc/modules/ZoomIt.md
Normal file
@@ -0,0 +1,215 @@
|
||||
---
|
||||
description: DSC configuration reference for PowerToys ZoomIt module
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: ZoomIt Module
|
||||
---
|
||||
|
||||
# ZoomIt Module
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration for the ZoomIt utility, which provides screen zoom, annotation, and presentation tools.
|
||||
|
||||
## Description
|
||||
|
||||
The `ZoomIt` module configures PowerToys ZoomIt, a screen zoom and annotation utility for presentations and demonstrations. It provides live zoom, screen drawing, a break timer, and other presentation features activated through customizable keyboard shortcuts.
|
||||
|
||||
## Properties
|
||||
|
||||
The ZoomIt module supports the following configurable properties:
|
||||
|
||||
### ActivationShortcut
|
||||
|
||||
Sets the keyboard shortcut to activate the zoom mode.
|
||||
|
||||
**Type:** object
|
||||
**Properties:**
|
||||
|
||||
- `win` (boolean) - Windows key modifier
|
||||
- `ctrl` (boolean) - Ctrl key modifier
|
||||
- `alt` (boolean) - Alt key modifier
|
||||
- `shift` (boolean) - Shift key modifier
|
||||
- `code` (integer) - Virtual key code
|
||||
- `key` (string) - Key name
|
||||
|
||||
**Default:** `Ctrl+1` (VK code 49)
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Configure activation shortcut with direct execution
|
||||
|
||||
This example sets a custom keyboard shortcut to activate ZoomIt.
|
||||
|
||||
```powershell
|
||||
$config = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
ActivationShortcut = @{
|
||||
win = $false
|
||||
ctrl = $true
|
||||
alt = $false
|
||||
shift = $true
|
||||
code = 90
|
||||
key = "Z"
|
||||
}
|
||||
}
|
||||
name = "ZoomIt"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
PowerToys.DSC.exe set --resource 'settings' --module ZoomIt --input $config
|
||||
```
|
||||
|
||||
### Example 2 - Configure with Microsoft DSC
|
||||
|
||||
This example configures the ZoomIt activation shortcut using Microsoft DSC.
|
||||
|
||||
```bash
|
||||
dsc config set --file zoomit-config.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# zoomit-config.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure ZoomIt shortcut
|
||||
type: Microsoft.PowerToys/ZoomItSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ActivationShortcut:
|
||||
win: false
|
||||
ctrl: true
|
||||
alt: false
|
||||
shift: false
|
||||
code: 49
|
||||
key: "1"
|
||||
name: ZoomIt
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and configures ZoomIt using WinGet.
|
||||
|
||||
```bash
|
||||
winget configure winget-zoomit.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# winget-zoomit.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure ZoomIt
|
||||
type: Microsoft.PowerToys/ZoomItSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ActivationShortcut:
|
||||
win: false
|
||||
ctrl: true
|
||||
alt: false
|
||||
shift: true
|
||||
code: 90
|
||||
key: Z
|
||||
name: ZoomIt
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 4 - Presentation mode hotkey
|
||||
|
||||
This example configures an easy-to-remember presentation hotkey.
|
||||
|
||||
```bash
|
||||
dsc config set --file zoomit-presentation.dsc.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# zoomit-presentation.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Presentation hotkey
|
||||
type: Microsoft.PowerToys/ZoomItSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ActivationShortcut:
|
||||
win: true
|
||||
ctrl: false
|
||||
alt: false
|
||||
shift: false
|
||||
code: 187
|
||||
key: "="
|
||||
name: ZoomIt
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Presentations
|
||||
|
||||
Configure for easy screen zooming during presentations:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Presentation setup
|
||||
type: Microsoft.PowerToys/ZoomItSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ActivationShortcut:
|
||||
win: false
|
||||
ctrl: true
|
||||
alt: false
|
||||
shift: false
|
||||
code: 49
|
||||
key: "1"
|
||||
name: ZoomIt
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Screen recording
|
||||
|
||||
Configure for quick access during screen recording sessions:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- name: Recording setup
|
||||
type: Microsoft.PowerToys/ZoomItSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ActivationShortcut:
|
||||
win: true
|
||||
ctrl: false
|
||||
alt: false
|
||||
shift: true
|
||||
code: 90
|
||||
key: Z
|
||||
name: ZoomIt
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource][01]
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [CropAndLock Module][03] - For additional PowerToys configuration
|
||||
- [PowerToys ZoomIt Documentation][04]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ../settings-resource.md
|
||||
[02]: ../overview.md
|
||||
[03]: ./CropAndLock.md
|
||||
[04]: https://learn.microsoft.com/windows/powertoys/zoomit
|
||||
244
doc/dsc/overview.md
Normal file
244
doc/dsc/overview.md
Normal file
@@ -0,0 +1,244 @@
|
||||
---
|
||||
description: Overview of PowerToys Desired State Configuration (DSC) support
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: overview
|
||||
title: PowerToys DSC Overview
|
||||
---
|
||||
|
||||
# PowerToys DSC Overview
|
||||
|
||||
## Synopsis
|
||||
|
||||
PowerToys supports Desired State Configuration (DSC) v3 for declarative configuration management of PowerToys settings.
|
||||
|
||||
## Description
|
||||
|
||||
PowerToys includes Microsoft Desired State Configuration (DSC) support
|
||||
through the `PowerToys.DSC.exe` command-line tool, enabling you to:
|
||||
|
||||
- Declare and enforce desired configuration states for PowerToys
|
||||
utilities.
|
||||
- Automate PowerToys configuration across multiple systems.
|
||||
- Integrate PowerToys configuration with WinGet and other DSC-compatible
|
||||
tools.
|
||||
- Version control your PowerToys settings as code.
|
||||
|
||||
The PowerToys DSC implementation provides a **settings** resource that
|
||||
manages configuration for all PowerToys utilities (modules). Each utility
|
||||
can be configured independently, allowing granular control over your
|
||||
PowerToys environment.
|
||||
|
||||
## Usage methods
|
||||
|
||||
PowerToys DSC can be used in three ways:
|
||||
|
||||
### 1. Direct execution with PowerToys.DSC.exe
|
||||
|
||||
Execute DSC operations directly using the PowerToys.DSC.exe command-line
|
||||
tool:
|
||||
|
||||
```powershell
|
||||
# Get current settings for a module
|
||||
PowerToys.DSC.exe get --resource 'settings' --module Awake
|
||||
|
||||
# Set settings for a module
|
||||
$input = '{"settings":{...}}'
|
||||
PowerToys.DSC.exe set --resource 'settings' --module Awake --input $input
|
||||
|
||||
# Test if settings match desired state
|
||||
PowerToys.DSC.exe test --resource 'settings' --module Awake --input $input
|
||||
```
|
||||
|
||||
For detailed information, see [PowerToys.DSC.exe command reference][01].
|
||||
|
||||
### 2. Microsoft Desired State Configuration (DSC)
|
||||
|
||||
Use PowerToys DSC resources in standard DSC configuration documents:
|
||||
|
||||
```yaml
|
||||
# powertoys-config.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Awake
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
keepDisplayOn: true
|
||||
mode: 1
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
```
|
||||
|
||||
### 3. WinGet Configuration
|
||||
|
||||
Integrate PowerToys configuration with WinGet package installation:
|
||||
|
||||
```yaml
|
||||
# winget-powertoys.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure FancyZones
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_shiftDrag: true
|
||||
fancyzones_mouseSwitch: true
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
## Available resources
|
||||
|
||||
PowerToys DSC provides the following resource:
|
||||
|
||||
| Resource | Description |
|
||||
| ---------- | ---------------------------------------------------- |
|
||||
| `settings` | Manages configuration for PowerToys utility modules. |
|
||||
|
||||
For detailed information about the settings resource, see [Settings
|
||||
Resource Reference][03].
|
||||
|
||||
## Available modules
|
||||
|
||||
The settings resource supports configuration for the following PowerToys
|
||||
utilities:
|
||||
|
||||
| Module | Description | Documentation |
|
||||
| ---------------------- | -------------------------------------------- | ------------------------------------- |
|
||||
| App | General PowerToys application settings. | [App module][04] |
|
||||
| AdvancedPaste | Advanced clipboard operations. | [AdvancedPaste module][05] |
|
||||
| AlwaysOnTop | Pin windows to stay on top. | [AlwaysOnTop module][06] |
|
||||
| Awake | Keep computer awake. | [Awake module][07] |
|
||||
| ColorPicker | System-wide color picker utility. | [ColorPicker module][08] |
|
||||
| CropAndLock | Crop and lock portions of windows. | [CropAndLock module][09] |
|
||||
| EnvironmentVariables | Manage environment variables. | [EnvironmentVariables module][10] |
|
||||
| FancyZones | Window layout manager. | [FancyZones module][11] |
|
||||
| FileLocksmith | Identify what's locking files. | [FileLocksmith module][12] |
|
||||
| FindMyMouse | Locate your mouse cursor. | [FindMyMouse module][13] |
|
||||
| Hosts | Quick hosts file editor. | [Hosts module][14] |
|
||||
| ImageResizer | Resize images from context menu. | [ImageResizer module][15] |
|
||||
| KeyboardManager | Remap keys and create shortcuts. | [KeyboardManager module][16] |
|
||||
| MeasureTool | Measure pixels on screen. | [MeasureTool module][17] |
|
||||
| MouseHighlighter | Highlight mouse cursor. | [MouseHighlighter module][18] |
|
||||
| MouseJump | Jump across large or multiple displays. | [MouseJump module][19] |
|
||||
| MousePointerCrosshairs | Display crosshairs centered on mouse. | [MousePointerCrosshairs module][20] |
|
||||
| Peek | Quick file previewer. | [Peek module][21] |
|
||||
| PowerAccent | Quick accent character selector. | [PowerAccent module][22] |
|
||||
| PowerOCR | Extract text from images. | [PowerOCR module][23] |
|
||||
| PowerRename | Bulk rename files. | [PowerRename module][24] |
|
||||
| RegistryPreview | Visualize and edit registry files. | [RegistryPreview module][25] |
|
||||
| ShortcutGuide | Display keyboard shortcuts. | [ShortcutGuide module][26] |
|
||||
| Workspaces | Save and restore application sets. | [Workspaces module][27] |
|
||||
| ZoomIt | Screen zoom and annotation tool. | [ZoomIt module][28] |
|
||||
|
||||
## Common operations
|
||||
|
||||
### List all supported modules
|
||||
|
||||
```powershell
|
||||
PowerToys.DSC.exe modules --resource 'settings'
|
||||
```
|
||||
|
||||
### Get current configuration
|
||||
|
||||
```powershell
|
||||
# Get configuration for a specific module.
|
||||
PowerToys.DSC.exe get --resource 'settings' --module FancyZones
|
||||
|
||||
# Export configuration (identical to get).
|
||||
PowerToys.DSC.exe export --resource 'settings' --module FancyZones
|
||||
```
|
||||
|
||||
### Apply configuration
|
||||
|
||||
```powershell
|
||||
# Set configuration for a module.
|
||||
$input = '{"settings":{...}}'
|
||||
PowerToys.DSC.exe set --resource 'settings' --module FancyZones --input $input
|
||||
```
|
||||
|
||||
### Validate configuration
|
||||
|
||||
```powershell
|
||||
# Test if current state matches desired state.
|
||||
$input = '{"settings":{...}}'
|
||||
PowerToys.DSC.exe test --resource 'settings' --module FancyZones --input $input
|
||||
```
|
||||
|
||||
### Generate schema
|
||||
|
||||
```powershell
|
||||
# Get JSON schema for a module's settings.
|
||||
PowerToys.DSC.exe schema --resource 'settings' --module FancyZones
|
||||
```
|
||||
|
||||
### Generate DSC manifest
|
||||
|
||||
```powershell
|
||||
# Generate manifest for a specific module.
|
||||
$outputDir = "C:\manifests"
|
||||
PowerToys.DSC.exe manifest --resource 'settings' --module FancyZones `
|
||||
--outputDir $outputDir
|
||||
|
||||
# Generate manifests for all modules.
|
||||
PowerToys.DSC.exe manifest --resource 'settings' --outputDir $outputDir
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
For complete examples, see:
|
||||
|
||||
- [Settings Resource Examples][29]
|
||||
- Individual module documentation in the [modules][30] folder
|
||||
|
||||
## See also
|
||||
|
||||
- [Settings Resource Reference][03]
|
||||
- [PowerToys.DSC.exe Command Reference][01]
|
||||
- [Module Documentation][30]
|
||||
- [Microsoft DSC Documentation][31]
|
||||
- [WinGet Configuration Documentation][32]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ./modules/
|
||||
[03]: ./settings-resource.md
|
||||
[04]: ./modules/App.md
|
||||
[05]: ./modules/AdvancedPaste.md
|
||||
[06]: ./modules/AlwaysOnTop.md
|
||||
[07]: ./modules/Awake.md
|
||||
[08]: ./modules/ColorPicker.md
|
||||
[09]: ./modules/CropAndLock.md
|
||||
[10]: ./modules/EnvironmentVariables.md
|
||||
[11]: ./modules/FancyZones.md
|
||||
[12]: ./modules/FileLocksmith.md
|
||||
[13]: ./modules/FindMyMouse.md
|
||||
[14]: ./modules/Hosts.md
|
||||
[15]: ./modules/ImageResizer.md
|
||||
[16]: ./modules/KeyboardManager.md
|
||||
[17]: ./modules/MeasureTool.md
|
||||
[18]: ./modules/MouseHighlighter.md
|
||||
[19]: ./modules/MouseJump.md
|
||||
[20]: ./modules/MousePointerCrosshairs.md
|
||||
[21]: ./modules/Peek.md
|
||||
[22]: ./modules/PowerAccent.md
|
||||
[23]: ./modules/PowerOCR.md
|
||||
[24]: ./modules/PowerRename.md
|
||||
[25]: ./modules/RegistryPreview.md
|
||||
[26]: ./modules/ShortcutGuide.md
|
||||
[27]: ./modules/Workspaces.md
|
||||
[28]: ./modules/ZoomIt.md
|
||||
[29]: ./settings-resource.md#examples
|
||||
[30]: ./modules/
|
||||
[31]: https://learn.microsoft.com/powershell/dsc/overview
|
||||
[32]: https://learn.microsoft.com/windows/package-manager/configuration/
|
||||
458
doc/dsc/settings-resource.md
Normal file
458
doc/dsc/settings-resource.md
Normal file
@@ -0,0 +1,458 @@
|
||||
---
|
||||
description: Reference for the PowerToys DSC settings resource
|
||||
ms.date: 10/18/2025
|
||||
ms.topic: reference
|
||||
title: Settings Resource
|
||||
---
|
||||
|
||||
# Settings Resource
|
||||
|
||||
## Synopsis
|
||||
|
||||
Manages configuration settings for PowerToys utilities (modules).
|
||||
|
||||
## Description
|
||||
|
||||
The `settings` resource provides Microsoft Desired State Configuration (DSC)
|
||||
support for managing PowerToys configuration. It enables declarative
|
||||
configuration of PowerToys utilities, allowing you to define, test, and
|
||||
enforce desired states for each module.
|
||||
|
||||
Each PowerToys utility (module) has its own configurable properties that can
|
||||
be managed through this resource. The settings resource supports standard DSC
|
||||
operations: get, set, test, export, schema, and manifest generation.
|
||||
|
||||
## Supported modules
|
||||
|
||||
The settings resource supports the following PowerToys modules:
|
||||
|
||||
- **App** - General application settings (enable/disable utilities, run at
|
||||
startup, theme, etc.).
|
||||
- **AdvancedPaste** - Advanced clipboard and paste operations.
|
||||
- **AlwaysOnTop** - Window pinning configuration.
|
||||
- **Awake** - Keep-awake timer settings.
|
||||
- **ColorPicker** - Color picker activation and format settings.
|
||||
- **CropAndLock** - Window cropping settings.
|
||||
- **EnvironmentVariables** - Environment variable editor settings.
|
||||
- **FancyZones** - Window layout and zone configuration.
|
||||
- **FileLocksmith** - File lock detection settings.
|
||||
- **FindMyMouse** - Mouse locator settings.
|
||||
- **Hosts** - Hosts file editor settings.
|
||||
- **ImageResizer** - Image resize configuration.
|
||||
- **KeyboardManager** - Key remapping and shortcut settings.
|
||||
- **MeasureTool** - Screen measurement tool settings.
|
||||
- **MouseHighlighter** - Mouse highlighting configuration.
|
||||
- **MouseJump** - Mouse jump navigation settings.
|
||||
- **MousePointerCrosshairs** - Crosshair display settings.
|
||||
- **Peek** - File preview settings.
|
||||
- **PowerAccent** - Accent character selection settings.
|
||||
- **PowerOCR** - Text extraction settings.
|
||||
- **PowerRename** - Bulk rename configuration.
|
||||
- **RegistryPreview** - Registry file preview settings.
|
||||
- **ShortcutGuide** - Keyboard shortcut overlay settings.
|
||||
- **Workspaces** - Application workspace settings.
|
||||
- **ZoomIt** - Screen zoom and annotation settings.
|
||||
|
||||
For detailed property information for each module, see the individual [module
|
||||
documentation][01].
|
||||
|
||||
## Operations
|
||||
|
||||
### List supported modules
|
||||
|
||||
List all modules that can be configured with the settings resource.
|
||||
|
||||
**Direct execution:**
|
||||
|
||||
```powershell
|
||||
# List all configurable modules.
|
||||
PowerToys.DSC.exe modules --resource 'settings'
|
||||
```
|
||||
|
||||
### Get current state
|
||||
|
||||
Retrieve the current configuration state for a module.
|
||||
|
||||
**Direct execution:**
|
||||
|
||||
```powershell
|
||||
# Get current settings for a module.
|
||||
PowerToys.DSC.exe get --resource 'settings' --module <ModuleName>
|
||||
```
|
||||
|
||||
**DSC configuration:**
|
||||
|
||||
```yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Get Awake settings
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties: {}
|
||||
```
|
||||
|
||||
**WinGet configuration:**
|
||||
|
||||
```yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Get FancyZones settings
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties: {}
|
||||
```
|
||||
|
||||
### Export current state
|
||||
|
||||
Export the current configuration state. The output is identical to the `get`
|
||||
operation.
|
||||
|
||||
**Direct execution:**
|
||||
|
||||
```powershell
|
||||
# Export current settings for a module.
|
||||
PowerToys.DSC.exe export --resource 'settings' --module <ModuleName>
|
||||
```
|
||||
|
||||
### Set desired state
|
||||
|
||||
Apply a configuration to a module, updating only the properties that differ
|
||||
from the desired state.
|
||||
|
||||
**Direct execution:**
|
||||
|
||||
```powershell
|
||||
# Set desired configuration for a module.
|
||||
$input = '{
|
||||
"settings": {
|
||||
"properties": {
|
||||
"keepDisplayOn": true,
|
||||
"mode": 1
|
||||
},
|
||||
"name": "Awake",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
}'
|
||||
PowerToys.DSC.exe set --resource 'settings' --module Awake --input $input
|
||||
```
|
||||
|
||||
**DSC configuration:**
|
||||
|
||||
```yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Configure Awake
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
keepDisplayOn: true
|
||||
mode: 1
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
```
|
||||
|
||||
**WinGet configuration:**
|
||||
|
||||
```yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install and configure PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
|
||||
- name: Configure FancyZones
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_shiftDrag: true
|
||||
fancyzones_mouseSwitch: true
|
||||
fancyzones_displayOrWorkAreaChange_moveWindows: true
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Test desired state
|
||||
|
||||
Verify whether the current configuration matches the desired state.
|
||||
|
||||
**Direct execution:**
|
||||
|
||||
```powershell
|
||||
# Test if current state matches desired state.
|
||||
$input = '{
|
||||
"settings": {
|
||||
"properties": {
|
||||
"keepDisplayOn": true,
|
||||
"mode": 1
|
||||
},
|
||||
"name": "Awake",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
}'
|
||||
PowerToys.DSC.exe test --resource 'settings' --module Awake --input $input
|
||||
```
|
||||
|
||||
The output includes an `_inDesiredState` property indicating whether the
|
||||
configuration matches (`true`) or differs (`false`).
|
||||
|
||||
**DSC configuration:**
|
||||
|
||||
```yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Test Awake configuration
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
keepDisplayOn: true
|
||||
mode: 1
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
```
|
||||
|
||||
### Get schema
|
||||
|
||||
Generate the JSON schema for a module's settings, describing all configurable
|
||||
properties and their types.
|
||||
|
||||
**Direct execution:**
|
||||
|
||||
```powershell
|
||||
# Get JSON schema for a module.
|
||||
PowerToys.DSC.exe schema --resource 'settings' --module Awake
|
||||
|
||||
# Format for readability.
|
||||
PowerToys.DSC.exe schema --resource 'settings' --module Awake `
|
||||
| ConvertFrom-Json | ConvertTo-Json -Depth 10
|
||||
```
|
||||
|
||||
### Generate manifest
|
||||
|
||||
Create a DSC resource manifest file for one or all modules.
|
||||
|
||||
**Direct execution:**
|
||||
|
||||
```powershell
|
||||
# Generate manifest for a specific module.
|
||||
$outputDir = "C:\manifests"
|
||||
PowerToys.DSC.exe manifest --resource 'settings' --module Awake `
|
||||
--outputDir $outputDir
|
||||
|
||||
# Generate manifests for all modules.
|
||||
PowerToys.DSC.exe manifest --resource 'settings' --outputDir $outputDir
|
||||
|
||||
# Print manifest to console (omit --outputDir).
|
||||
PowerToys.DSC.exe manifest --resource 'settings' --module Awake
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Enable and configure FancyZones
|
||||
|
||||
This example enables FancyZones and configures window dragging behavior using
|
||||
direct execution.
|
||||
|
||||
```powershell
|
||||
# Get current FancyZones settings.
|
||||
$current = PowerToys.DSC.exe get --resource 'settings' --module FancyZones `
|
||||
| ConvertFrom-Json
|
||||
|
||||
# Modify settings.
|
||||
$desired = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
fancyzones_shiftDrag = $true
|
||||
fancyzones_mouseSwitch = $true
|
||||
fancyzones_displayOrWorkAreaChange_moveWindows = $true
|
||||
}
|
||||
name = "FancyZones"
|
||||
version = "1.0"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
# Apply configuration.
|
||||
PowerToys.DSC.exe set --resource 'settings' --module FancyZones `
|
||||
--input $desired
|
||||
```
|
||||
|
||||
### Example 2 - Configure multiple utilities with DSC
|
||||
|
||||
This example configures multiple PowerToys utilities in a single DSC
|
||||
configuration.
|
||||
|
||||
```yaml
|
||||
# powertoys-multi.dsc.yaml
|
||||
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
|
||||
resources:
|
||||
- name: Enable PowerToys utilities
|
||||
type: Microsoft.PowerToys/AppSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
Enabled:
|
||||
Awake: true
|
||||
FancyZones: true
|
||||
PowerRename: true
|
||||
ColorPicker: true
|
||||
name: App
|
||||
version: 1.0
|
||||
|
||||
- name: Configure Awake
|
||||
type: Microsoft.PowerToys/AwakeSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
keepDisplayOn: true
|
||||
mode: 1
|
||||
name: Awake
|
||||
version: 0.0.1
|
||||
|
||||
- name: Configure ColorPicker
|
||||
type: Microsoft.PowerToys/ColorPickerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
changecursor: true
|
||||
copiedcolorrepresentation: "HEX"
|
||||
name: ColorPicker
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
### Example 3 - Install and configure with WinGet
|
||||
|
||||
This example installs PowerToys and applies configuration using WinGet.
|
||||
|
||||
```yaml
|
||||
# winget-powertoys-setup.yaml
|
||||
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
|
||||
metadata:
|
||||
winget:
|
||||
processor: dscv3
|
||||
resources:
|
||||
- name: Install PowerToys
|
||||
type: Microsoft.WinGet.DSC/WinGetPackage
|
||||
properties:
|
||||
id: Microsoft.PowerToys
|
||||
source: winget
|
||||
ensure: Present
|
||||
|
||||
- name: Configure general settings
|
||||
type: Microsoft.PowerToys/AppSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
run_elevated: true
|
||||
startup: true
|
||||
theme: "dark"
|
||||
name: App
|
||||
version: 1.0
|
||||
|
||||
- name: Configure FancyZones
|
||||
type: Microsoft.PowerToys/FancyZonesSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
fancyzones_shiftDrag: true
|
||||
fancyzones_zoneSetChange_moveWindows: true
|
||||
name: FancyZones
|
||||
version: 1.0
|
||||
|
||||
- name: Configure ImageResizer
|
||||
type: Microsoft.PowerToys/ImageResizerSettings
|
||||
properties:
|
||||
settings:
|
||||
properties:
|
||||
ImageResizerSizes:
|
||||
- Name: Small
|
||||
Width: 854
|
||||
Height: 480
|
||||
Unit: Pixel
|
||||
Fit: Fit
|
||||
- Name: Medium
|
||||
Width: 1920
|
||||
Height: 1080
|
||||
Unit: Pixel
|
||||
Fit: Fit
|
||||
name: ImageResizer
|
||||
version: 1.0
|
||||
```
|
||||
|
||||
Apply the configuration:
|
||||
|
||||
```powershell
|
||||
winget configure winget-powertoys-setup.yaml
|
||||
```
|
||||
|
||||
### Example 4 - Test configuration drift
|
||||
|
||||
This example tests whether the current configuration matches the desired
|
||||
state.
|
||||
|
||||
```powershell
|
||||
# Define desired state.
|
||||
$desired = @{
|
||||
settings = @{
|
||||
properties = @{
|
||||
keepDisplayOn = $true
|
||||
mode = 1
|
||||
}
|
||||
name = "Awake"
|
||||
version = "0.0.1"
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10 -Compress
|
||||
|
||||
# Test for drift.
|
||||
$result = PowerToys.DSC.exe test --resource 'settings' --module Awake `
|
||||
--input $desired | ConvertFrom-Json
|
||||
|
||||
if ($result._inDesiredState) {
|
||||
Write-Host "Configuration is in desired state"
|
||||
} else {
|
||||
Write-Host "Configuration has drifted from desired state"
|
||||
|
||||
# Apply configuration.
|
||||
PowerToys.DSC.exe set --resource 'settings' --module Awake `
|
||||
--input $desired
|
||||
}
|
||||
```
|
||||
|
||||
### Example 5 - Export all module configurations
|
||||
|
||||
This example exports configuration for all modules.
|
||||
|
||||
```powershell
|
||||
# Get list of all modules.
|
||||
$modules = PowerToys.DSC.exe modules --resource 'settings'
|
||||
|
||||
# Export each module's configuration.
|
||||
$configurations = @{}
|
||||
foreach ($module in $modules) {
|
||||
$config = PowerToys.DSC.exe export --resource 'settings' `
|
||||
--module $module | ConvertFrom-Json
|
||||
$configurations[$module] = $config
|
||||
}
|
||||
|
||||
# Save to file.
|
||||
$configurations | ConvertTo-Json -Depth 10 `
|
||||
| Out-File "powertoys-backup.json"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [PowerToys DSC Overview][02]
|
||||
- [Module Documentation][01]
|
||||
- [WinGet Configuration][03]
|
||||
|
||||
<!-- Link reference definitions -->
|
||||
[01]: ./modules/
|
||||
[02]: ./overview.md
|
||||
[03]: https://learn.microsoft.com/windows/package-manager/configuration/
|
||||
@@ -1594,6 +1594,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
L"PowerToys.PowerRename.exe",
|
||||
L"PowerToys.ImageResizer.exe",
|
||||
L"PowerToys.LightSwitchService.exe",
|
||||
L"PowerToys.PowerDisplay.exe",
|
||||
L"PowerToys.GcodeThumbnailProvider.exe",
|
||||
L"PowerToys.BgcodeThumbnailProvider.exe",
|
||||
L"PowerToys.PdfThumbnailProvider.exe",
|
||||
|
||||
@@ -47,6 +47,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
call move /Y ..\..\..\NewPlus.wxs.bk ..\..\..\NewPlus.wxs
|
||||
call move /Y ..\..\..\Peek.wxs.bk ..\..\..\Peek.wxs
|
||||
call move /Y ..\..\..\PowerRename.wxs.bk ..\..\..\PowerRename.wxs
|
||||
call move /Y ..\..\..\PowerDisplay.wxs.bk ..\..\..\PowerDisplay.wxs
|
||||
call move /Y ..\..\..\Product.wxs.bk ..\..\..\Product.wxs
|
||||
call move /Y ..\..\..\RegistryPreview.wxs.bk ..\..\..\RegistryPreview.wxs
|
||||
call move /Y ..\..\..\Resources.wxs.bk ..\..\..\Resources.wxs
|
||||
@@ -123,6 +124,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
<Compile Include="KeyboardManager.wxs" />
|
||||
<Compile Include="Peek.wxs" />
|
||||
<Compile Include="PowerRename.wxs" />
|
||||
<Compile Include="PowerDisplay.wxs" />
|
||||
<Compile Include="DscResources.wxs" />
|
||||
<Compile Include="RegistryPreview.wxs" />
|
||||
<Compile Include="Run.wxs" />
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
<ComponentGroupRef Id="LightSwitchComponentGroup" />
|
||||
<ComponentGroupRef Id="PeekComponentGroup" />
|
||||
<ComponentGroupRef Id="PowerRenameComponentGroup" />
|
||||
<ComponentGroupRef Id="PowerDisplayComponentGroup" />
|
||||
<ComponentGroupRef Id="RegistryPreviewComponentGroup" />
|
||||
<ComponentGroupRef Id="RunComponentGroup" />
|
||||
<ComponentGroupRef Id="SettingsComponentGroup" />
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Fragment>
|
||||
<!-- Resource directories should be added only if the installer is built on the build farm -->
|
||||
<?ifdef env.IsPipeline?>
|
||||
<?foreach ParentDirectory in INSTALLFOLDER;WinUI3AppsInstallFolder;HistoryPluginFolder;CalculatorPluginFolder;FolderPluginFolder;ProgramPluginFolder;ShellPluginFolder;IndexerPluginFolder;UnitConverterPluginFolder;ValueGeneratorPluginFolder;UriPluginFolder;WindowWalkerPluginFolder;OneNotePluginFolder;RegistryPluginFolder;VSCodeWorkspacesPluginFolder;ServicePluginFolder;SystemPluginFolder;TimeDatePluginFolder;WindowsSettingsPluginFolder;WindowsTerminalPluginFolder;WebSearchPluginFolder;PowerToysPluginFolder?>
|
||||
<?foreach ParentDirectory in INSTALLFOLDER;HistoryPluginFolder;CalculatorPluginFolder;FolderPluginFolder;ProgramPluginFolder;ShellPluginFolder;IndexerPluginFolder;UnitConverterPluginFolder;ValueGeneratorPluginFolder;UriPluginFolder;WindowWalkerPluginFolder;OneNotePluginFolder;RegistryPluginFolder;VSCodeWorkspacesPluginFolder;ServicePluginFolder;SystemPluginFolder;TimeDatePluginFolder;WindowsSettingsPluginFolder;WindowsTerminalPluginFolder;WebSearchPluginFolder;PowerToysPluginFolder?>
|
||||
<DirectoryRef Id="$(var.ParentDirectory)">
|
||||
<!-- Resource file directories -->
|
||||
<?foreach Language in $(var.LocLanguageList)?>
|
||||
@@ -171,12 +171,6 @@
|
||||
</RegistryKey>
|
||||
<File Id="FancyZonesEditor_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\$(var.Language)\PowerToys.FancyZonesEditor.resources.dll" />
|
||||
</Component>
|
||||
<Component Id="ImageResizer_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)WinUI3AppsInstallFolder" Guid="$(var.CompGUIDPrefix)02">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="ImageResizer_$(var.IdSafeLanguage)_Component" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<File Id="ImageResizer_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\WinUI3Apps\$(var.Language)\PowerToys.ImageResizer.resources.dll" />
|
||||
</Component>
|
||||
<Component Id="ColorPicker_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)INSTALLFOLDER" Guid="$(var.CompGUIDPrefix)03">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="ColorPicker_$(var.IdSafeLanguage)_Component" Value="" KeyPath="yes" />
|
||||
@@ -459,7 +453,6 @@
|
||||
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)HistoryPluginFolder" Directory="Resource$(var.IdSafeLanguage)HistoryPluginFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)PowerToysPluginFolder" Directory="Resource$(var.IdSafeLanguage)PowerToysPluginFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)ValueGeneratorPluginFolder" Directory="Resource$(var.IdSafeLanguage)ValueGeneratorPluginFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)WinUI3AppsInstallFolder" Directory="Resource$(var.IdSafeLanguage)WinUI3AppsInstallFolder" On="uninstall"/>
|
||||
<?undef IdSafeLanguage?>
|
||||
<?endforeach?>
|
||||
</Component>
|
||||
|
||||
@@ -131,7 +131,25 @@ if ($platform -ceq "arm64") {
|
||||
}
|
||||
|
||||
#BaseApplications
|
||||
# WORKAROUND: Exclude ImageResizer files that leak into the root output directory.
|
||||
# ImageResizerCLI (Exe, SelfContained) has a ProjectReference to ImageResizerUI (WinExe, SelfContained).
|
||||
# MSBuild copies the referenced WinExe's apphost (.exe, .deps.json, .runtimeconfig.json) to the root
|
||||
# output directory as a side effect. These files are incomplete (missing the managed .dll) and should
|
||||
# not be included in the installer. The complete ImageResizer files are in WinUI3Apps/ and are handled
|
||||
# by WinUI3ApplicationsFiles. TODO: Refactor ImageResizer to use a shared Library project instead.
|
||||
Generate-FileList -fileDepsJson "" -fileListName BaseApplicationsFiles -wxsFilePath $PSScriptRoot\BaseApplications.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release"
|
||||
|
||||
# Remove leaked ImageResizer artifacts from BaseApplications
|
||||
$baseAppWxsPath = "$PSScriptRoot\BaseApplications.wxs"
|
||||
$baseAppWxs = Get-Content $baseAppWxsPath -Raw
|
||||
$baseAppWxs = $baseAppWxs -replace 'PowerToys\.ImageResizer\.exe;?', ''
|
||||
$baseAppWxs = $baseAppWxs -replace 'PowerToys\.ImageResizer\.deps\.json;?', ''
|
||||
$baseAppWxs = $baseAppWxs -replace 'PowerToys\.ImageResizer\.runtimeconfig\.json;?', ''
|
||||
# Clean up trailing/double semicolons left after removal
|
||||
$baseAppWxs = $baseAppWxs -replace ';;+', ';'
|
||||
$baseAppWxs = $baseAppWxs -replace '=;', '='
|
||||
$baseAppWxs = $baseAppWxs -replace ';"', '"'
|
||||
Set-Content -Path $baseAppWxsPath -Value $baseAppWxs
|
||||
Generate-FileComponents -fileListName "BaseApplicationsFiles" -wxsFilePath $PSScriptRoot\BaseApplications.wxs
|
||||
|
||||
#WinUI3Applications
|
||||
@@ -194,6 +212,10 @@ Generate-FileComponents -fileListName "PeekAssetsFiles" -wxsFilePath $PSScriptRo
|
||||
Generate-FileList -fileDepsJson "" -fileListName PowerRenameAssetsFiles -wxsFilePath $PSScriptRoot\PowerRename.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\PowerRename\"
|
||||
Generate-FileComponents -fileListName "PowerRenameAssetsFiles" -wxsFilePath $PSScriptRoot\PowerRename.wxs
|
||||
|
||||
#PowerDisplay
|
||||
Generate-FileList -fileDepsJson "" -fileListName PowerDisplayAssetsFiles -wxsFilePath $PSScriptRoot\PowerDisplay.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\PowerDisplay\"
|
||||
Generate-FileComponents -fileListName "PowerDisplayAssetsFiles" -wxsFilePath $PSScriptRoot\PowerDisplay.wxs
|
||||
|
||||
#RegistryPreview
|
||||
Generate-FileList -fileDepsJson "" -fileListName RegistryPreviewAssetsFiles -wxsFilePath $PSScriptRoot\RegistryPreview.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\RegistryPreview\"
|
||||
Generate-FileComponents -fileListName "RegistryPreviewAssetsFiles" -wxsFilePath $PSScriptRoot\RegistryPreview.wxs
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <common/updating/updating.h>
|
||||
#include <common/updating/updateState.h>
|
||||
#include <common/updating/installer.h>
|
||||
#include <common/updating/configBackup.h>
|
||||
#include <common/updating/updateLifecycle.h>
|
||||
|
||||
#include <common/utils/elevation.h>
|
||||
#include <common/utils/HttpClient.h>
|
||||
@@ -21,6 +23,8 @@
|
||||
#include <common/utils/resources.h>
|
||||
#include <common/utils/timeutil.h>
|
||||
|
||||
#include <wil/resource.h>
|
||||
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
@@ -38,15 +42,16 @@ namespace fs = std::filesystem;
|
||||
|
||||
std::optional<fs::path> CopySelfToTempDir()
|
||||
{
|
||||
// D5 fix: Use unique temp path with PID to avoid collision on concurrent updates
|
||||
std::error_code error;
|
||||
auto dst_path = fs::temp_directory_path() / "PowerToys.Update.exe";
|
||||
auto dst_path = fs::temp_directory_path() / (L"PowerToys.Update." + std::to_wstring(GetCurrentProcessId()) + L".exe");
|
||||
fs::copy_file(get_module_filename(), dst_path, fs::copy_options::overwrite_existing, error);
|
||||
if (error)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return std::move(dst_path);
|
||||
return dst_path;
|
||||
}
|
||||
|
||||
std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
|
||||
@@ -57,34 +62,9 @@ std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
|
||||
|
||||
auto state = UpdateState::read();
|
||||
|
||||
const auto new_version_info = std::move(get_github_version_info_async()).get();
|
||||
if (std::holds_alternative<version_up_to_date>(*new_version_info))
|
||||
{
|
||||
isUpToDate = true;
|
||||
Logger::error("Invoked with -update_now argument, but no update was available");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (state.state == UpdateState::readyToDownload || state.state == UpdateState::errorDownloading)
|
||||
{
|
||||
if (!new_version_info)
|
||||
{
|
||||
Logger::error(L"Couldn't obtain github version info: {}", new_version_info.error());
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Cleanup old updates before downloading the latest
|
||||
updating::cleanup_updates();
|
||||
|
||||
auto downloaded_installer = std::move(download_new_version_async(std::get<new_version_download_info>(*new_version_info))).get();
|
||||
if (!downloaded_installer)
|
||||
{
|
||||
Logger::error("Couldn't download new installer");
|
||||
}
|
||||
|
||||
return downloaded_installer;
|
||||
}
|
||||
else if (state.state == UpdateState::readyToInstall)
|
||||
// Handle readyToInstall first — the installer is already on disk,
|
||||
// so we don't need a GitHub API call (which may fail if offline).
|
||||
if (state.state == UpdateState::readyToInstall)
|
||||
{
|
||||
fs::path installer{ get_pending_updates_path() / state.downloadedInstallerFilename };
|
||||
if (fs::is_regular_file(installer))
|
||||
@@ -97,12 +77,44 @@ std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
else if (state.state == UpdateState::upToDate)
|
||||
|
||||
if (state.state == UpdateState::upToDate)
|
||||
{
|
||||
isUpToDate = true;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto new_version_info = std::move(get_github_version_info_async()).get();
|
||||
|
||||
// Check for error BEFORE dereferencing — the old code crashed here
|
||||
// when GitHub API was unreachable (new_version_info held an error string).
|
||||
if (!new_version_info)
|
||||
{
|
||||
Logger::error(L"Couldn't obtain github version info: {}", new_version_info.error());
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (std::holds_alternative<version_up_to_date>(*new_version_info))
|
||||
{
|
||||
isUpToDate = true;
|
||||
Logger::error("Invoked with -update_now argument, but no update was available");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (state.state == UpdateState::readyToDownload || state.state == UpdateState::errorDownloading)
|
||||
{
|
||||
// Cleanup old updates before downloading the latest
|
||||
updating::cleanup_updates();
|
||||
|
||||
auto downloaded_installer = std::move(download_new_version_async(std::get<new_version_download_info>(*new_version_info))).get();
|
||||
if (!downloaded_installer)
|
||||
{
|
||||
Logger::error("Couldn't download new installer");
|
||||
}
|
||||
|
||||
return downloaded_installer;
|
||||
}
|
||||
|
||||
Logger::error("Invoked with -update_now argument, but update state was invalid");
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -116,13 +128,29 @@ bool InstallNewVersionStage1(fs::path installer)
|
||||
|
||||
if (pt_main_window != nullptr)
|
||||
{
|
||||
// Get the process that owns the tray window so we can wait for it to exit
|
||||
DWORD ptProcessId = 0;
|
||||
GetWindowThreadProcessId(pt_main_window, &ptProcessId);
|
||||
|
||||
SendMessageW(pt_main_window, WM_CLOSE, 0, 0);
|
||||
|
||||
// D4 fix: Wait for PT to actually exit before launching installer.
|
||||
// Without this, the installer may find PT files locked.
|
||||
if (ptProcessId != 0)
|
||||
{
|
||||
wil::unique_handle ptProcess{ OpenProcess(SYNCHRONIZE, FALSE, ptProcessId) };
|
||||
if (ptProcess)
|
||||
{
|
||||
WaitForSingleObject(ptProcess.get(), 10000); // 10 second timeout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring arguments{ UPDATE_NOW_LAUNCH_STAGE2 };
|
||||
arguments += L" \"";
|
||||
arguments += installer.c_str();
|
||||
arguments += L"\"";
|
||||
// Pass the install directory so Stage 2 can relaunch PowerToys after install
|
||||
const std::wstring installDir = get_module_folderpath();
|
||||
|
||||
std::wstring arguments = updating::BuildStage2Arguments(
|
||||
UPDATE_NOW_LAUNCH_STAGE2, installer, fs::path(installDir));
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
|
||||
sei.lpFile = copy_in_temp->c_str();
|
||||
@@ -190,9 +218,16 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
LPWSTR* args = CommandLineToArgvW(GetCommandLineW(), &nArgs);
|
||||
if (!args || nArgs < 2)
|
||||
{
|
||||
if (args)
|
||||
{
|
||||
LocalFree(args);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// D3 fix: ensure args is freed on all exit paths
|
||||
auto freeArgs = wil::scope_exit([&] { LocalFree(args); });
|
||||
|
||||
std::wstring_view action{ args[1] };
|
||||
|
||||
std::filesystem::path logFilePath(PTSettingsHelper::get_root_save_folder_location());
|
||||
@@ -201,6 +236,10 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
|
||||
if (action == UPDATE_NOW_LAUNCH_STAGE1)
|
||||
{
|
||||
// Backup config files before the update to protect against corruption
|
||||
Logger::info("Backing up config files before update");
|
||||
updating::BackupConfigFiles(fs::path(PTSettingsHelper::get_root_save_folder_location()));
|
||||
|
||||
bool isUpToDate = false;
|
||||
auto installerPath = ObtainInstaller(isUpToDate);
|
||||
bool failed = !installerPath.has_value();
|
||||
@@ -217,6 +256,12 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
}
|
||||
else if (action == UPDATE_NOW_LAUNCH_STAGE2)
|
||||
{
|
||||
if (nArgs < 3)
|
||||
{
|
||||
Logger::error("Stage 2 invoked without installer path argument");
|
||||
return 1;
|
||||
}
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
const bool failed = !InstallNewVersionStage2(args[2]);
|
||||
if (failed)
|
||||
@@ -227,6 +272,37 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
state.state = UpdateState::errorDownloading;
|
||||
});
|
||||
}
|
||||
|
||||
// D7 fix: Always check for corrupted configs after Stage 2, regardless
|
||||
// of install success/failure. A failed install may still corrupt configs.
|
||||
Logger::info("Checking for corrupted config files after update");
|
||||
updating::RestoreCorruptedConfigs(fs::path(PTSettingsHelper::get_root_save_folder_location()));
|
||||
|
||||
if (!failed)
|
||||
{
|
||||
// Relaunch PowerToys from the install directory
|
||||
if (updating::CanRelaunchAfterUpdate(nArgs))
|
||||
{
|
||||
std::wstring ptExePath = updating::BuildPowerToysExePath(args[3]);
|
||||
|
||||
Logger::info(L"Relaunching PowerToys after update: {}", ptExePath);
|
||||
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
|
||||
sei.lpFile = ptExePath.c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
sei.lpParameters = UPDATE_REPORT_SUCCESS;
|
||||
|
||||
if (!ShellExecuteExW(&sei))
|
||||
{
|
||||
Logger::error(L"Failed to relaunch PowerToys after update");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::warn("Install directory not provided to Stage 2 - cannot relaunch PowerToys");
|
||||
}
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
|
||||
</packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.250325.1" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -105,6 +105,22 @@ namespace Microsoft.PowerToys.Common.UI.Controls
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case nameof(VirtualKey.Up):
|
||||
SetGlyphOrText("\uE0E4", VirtualKey.Up);
|
||||
break;
|
||||
|
||||
case nameof(VirtualKey.Down):
|
||||
SetGlyphOrText("\uE0E5", VirtualKey.Down);
|
||||
break;
|
||||
|
||||
case nameof(VirtualKey.Left):
|
||||
SetGlyphOrText("\uE0E2", VirtualKey.Left);
|
||||
break;
|
||||
|
||||
case nameof(VirtualKey.Right):
|
||||
SetGlyphOrText("\uE0E3", VirtualKey.Right);
|
||||
break;
|
||||
|
||||
case "Copilot":
|
||||
_keyPresenter.Style = (Style)Application.Current.Resources["CopilotKeyCharPresenterStyle"];
|
||||
break;
|
||||
@@ -141,19 +157,19 @@ namespace Microsoft.PowerToys.Common.UI.Controls
|
||||
break;
|
||||
|
||||
case VirtualKey.Up:
|
||||
_keyPresenter.Content = "\uE0E4";
|
||||
SetGlyphOrText("\uE0E4", virtualKey);
|
||||
break;
|
||||
|
||||
case VirtualKey.Down:
|
||||
_keyPresenter.Content = "\uE0E5";
|
||||
SetGlyphOrText("\uE0E5", virtualKey);
|
||||
break;
|
||||
|
||||
case VirtualKey.Left:
|
||||
_keyPresenter.Content = "\uE0E2";
|
||||
SetGlyphOrText("\uE0E2", virtualKey);
|
||||
break;
|
||||
|
||||
case VirtualKey.Right:
|
||||
_keyPresenter.Content = "\uE0E3";
|
||||
SetGlyphOrText("\uE0E3", virtualKey);
|
||||
break;
|
||||
|
||||
case VirtualKey.LeftWindows:
|
||||
|
||||
679
src/common/updating/UnitTests/UpdatingTests.cpp
Normal file
679
src/common/updating/UnitTests/UpdatingTests.cpp
Normal file
@@ -0,0 +1,679 @@
|
||||
// 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.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <common/updating/configBackup.h>
|
||||
#include <common/updating/updateLifecycle.h>
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace UpdatingUnitTests
|
||||
{
|
||||
// Helper to create a temp directory for test isolation.
|
||||
// Each instance gets a unique subdirectory to prevent test interference.
|
||||
class TempDir
|
||||
{
|
||||
public:
|
||||
TempDir()
|
||||
{
|
||||
wchar_t tempPath[MAX_PATH + 1];
|
||||
GetTempPathW(MAX_PATH, tempPath);
|
||||
static std::atomic<int> counter{0};
|
||||
m_path = fs::path(tempPath) / (L"PowerToysUpdateTests_" + std::to_wstring(counter++));
|
||||
|
||||
// Ensure clean state
|
||||
std::error_code ec;
|
||||
fs::remove_all(m_path, ec);
|
||||
fs::create_directories(m_path, ec);
|
||||
}
|
||||
|
||||
~TempDir()
|
||||
{
|
||||
std::error_code ec;
|
||||
fs::remove_all(m_path, ec);
|
||||
}
|
||||
|
||||
const fs::path& path() const { return m_path; }
|
||||
|
||||
// Write a file with the given content
|
||||
void WriteFile(const fs::path& relativePath, const std::string& content)
|
||||
{
|
||||
auto fullPath = m_path / relativePath;
|
||||
fs::create_directories(fullPath.parent_path());
|
||||
std::ofstream file(fullPath, std::ios::binary);
|
||||
file.write(content.data(), content.size());
|
||||
}
|
||||
|
||||
// Write a file with raw bytes (including null bytes for corruption testing)
|
||||
void WriteFileBytes(const fs::path& relativePath, const std::vector<char>& bytes)
|
||||
{
|
||||
auto fullPath = m_path / relativePath;
|
||||
fs::create_directories(fullPath.parent_path());
|
||||
std::ofstream file(fullPath, std::ios::binary);
|
||||
file.write(bytes.data(), bytes.size());
|
||||
}
|
||||
|
||||
// Read file content as string
|
||||
std::string ReadFile(const fs::path& relativePath)
|
||||
{
|
||||
auto fullPath = m_path / relativePath;
|
||||
std::ifstream file(fullPath, std::ios::binary);
|
||||
return std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
|
||||
}
|
||||
|
||||
bool FileExists(const fs::path& relativePath)
|
||||
{
|
||||
return fs::exists(m_path / relativePath);
|
||||
}
|
||||
|
||||
private:
|
||||
fs::path m_path;
|
||||
};
|
||||
|
||||
TEST_CLASS(IsJsonFileCorruptedTests)
|
||||
{
|
||||
public:
|
||||
// Tests IsJsonFileCorrupted: valid JSON with no null bytes returns false.
|
||||
// Covers: configBackup.h IsJsonFileCorrupted — happy path, full file scan.
|
||||
TEST_METHOD(CleanJsonFileIsNotCorrupted)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"settings.json", R"({"theme":"dark","startup":true})");
|
||||
|
||||
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"settings.json"));
|
||||
}
|
||||
|
||||
// Tests IsJsonFileCorrupted: zero-length file returns false (empty is not corrupted).
|
||||
// Covers: configBackup.h IsJsonFileCorrupted — file.read returns 0 bytes immediately.
|
||||
TEST_METHOD(EmptyFileIsNotCorrupted)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"empty.json", "");
|
||||
|
||||
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"empty.json"));
|
||||
}
|
||||
|
||||
// Tests IsJsonFileCorrupted: file containing embedded null bytes returns true.
|
||||
// Covers: configBackup.h IsJsonFileCorrupted — null byte detection within buffer.
|
||||
TEST_METHOD(FileWithNullBytesIsCorrupted)
|
||||
{
|
||||
TempDir dir;
|
||||
std::vector<char> corrupted = { '{', '"', 'a', '"', ':', '\0', '\0', '\0', '}' };
|
||||
dir.WriteFileBytes(L"corrupted.json", corrupted);
|
||||
|
||||
Assert::IsTrue(updating::IsJsonFileCorrupted(dir.path() / L"corrupted.json"));
|
||||
}
|
||||
|
||||
// Tests IsJsonFileCorrupted: file entirely filled with 0x00 bytes returns true.
|
||||
// Reproduces the exact bug from #46179 where installer zeroed out JSON files.
|
||||
// Covers: configBackup.h IsJsonFileCorrupted — first byte is null.
|
||||
TEST_METHOD(FileFilledWithNullBytesIsCorrupted)
|
||||
{
|
||||
TempDir dir;
|
||||
std::vector<char> allNulls(1024, '\0');
|
||||
dir.WriteFileBytes(L"workspaces.json", allNulls);
|
||||
|
||||
Assert::IsTrue(updating::IsJsonFileCorrupted(dir.path() / L"workspaces.json"));
|
||||
}
|
||||
|
||||
// Tests IsJsonFileCorrupted: path that does not exist returns false.
|
||||
// Covers: configBackup.h IsJsonFileCorrupted — file.is_open() check.
|
||||
TEST_METHOD(NonExistentFileIsNotCorrupted)
|
||||
{
|
||||
TempDir dir;
|
||||
|
||||
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"missing.json"));
|
||||
}
|
||||
|
||||
// Tests IsJsonFileCorrupted: file larger than the 4096-byte read chunk
|
||||
// with no null bytes returns false.
|
||||
// Covers: configBackup.h IsJsonFileCorrupted — multi-chunk while loop.
|
||||
TEST_METHOD(LargeCleanFileIsNotCorrupted)
|
||||
{
|
||||
TempDir dir;
|
||||
std::string largeContent(8192, 'x');
|
||||
dir.WriteFile(L"large.json", largeContent);
|
||||
|
||||
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"large.json"));
|
||||
}
|
||||
|
||||
// Tests IsJsonFileCorrupted: null byte placed after the first 4096-byte
|
||||
// chunk boundary is still detected.
|
||||
// Covers: configBackup.h IsJsonFileCorrupted — second chunk scan.
|
||||
TEST_METHOD(NullByteAtEndOfLargeFileIsDetected)
|
||||
{
|
||||
TempDir dir;
|
||||
std::string content(5000, 'x');
|
||||
content[4999] = '\0';
|
||||
std::vector<char> bytes(content.begin(), content.end());
|
||||
dir.WriteFileBytes(L"sneaky.json", bytes);
|
||||
|
||||
Assert::IsTrue(updating::IsJsonFileCorrupted(dir.path() / L"sneaky.json"));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CLASS(BackupConfigFilesTests)
|
||||
{
|
||||
public:
|
||||
// Tests BackupConfigFiles: root-level .json files are copied to ConfigBackup.
|
||||
// Covers: configBackup.h BackupConfigFiles — root directory_iterator,
|
||||
// is_regular_file && extension == ".json" branch.
|
||||
// Setup: Two root-level JSON files.
|
||||
TEST_METHOD(BackupCopiesRootJsonFiles)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
|
||||
dir.WriteFile(L"UpdateState.json", R"({"state":0})");
|
||||
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\settings.json"));
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\UpdateState.json"));
|
||||
Assert::AreEqual(std::string(R"({"theme":"dark"})"), dir.ReadFile(L"ConfigBackup\\settings.json"));
|
||||
}
|
||||
|
||||
// Tests BackupConfigFiles: .json files inside module subdirectories are
|
||||
// copied to ConfigBackup/<module>/.
|
||||
// Covers: configBackup.h BackupConfigFiles — is_directory branch,
|
||||
// module directory_iterator with extension filter.
|
||||
// Setup: Root JSON + two module directories with JSON files.
|
||||
TEST_METHOD(BackupCopiesModuleJsonFiles)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
|
||||
dir.WriteFile(L"FancyZones\\settings.json", R"({"zones":[]})");
|
||||
dir.WriteFile(L"Workspaces\\workspaces.json", R"({"workspaces":[]})");
|
||||
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\FancyZones\\settings.json"));
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\Workspaces\\workspaces.json"));
|
||||
Assert::AreEqual(std::string(R"({"zones":[]})"),
|
||||
dir.ReadFile(L"ConfigBackup\\FancyZones\\settings.json"));
|
||||
}
|
||||
|
||||
// Tests BackupConfigFiles: non-.json files at root level are not copied.
|
||||
// Covers: configBackup.h BackupConfigFiles — extension filter excludes .log.
|
||||
// Setup: One JSON file + one .log file at root.
|
||||
TEST_METHOD(BackupSkipsNonJsonFiles)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
|
||||
dir.WriteFile(L"debug.log", "log data");
|
||||
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\settings.json"));
|
||||
Assert::IsFalse(dir.FileExists(L"ConfigBackup\\debug.log"));
|
||||
}
|
||||
|
||||
// Tests BackupConfigFiles: the "Updates" directory is explicitly skipped.
|
||||
// Covers: configBackup.h BackupConfigFiles — dirName == L"Updates" continue.
|
||||
// Setup: Root JSON + Updates directory containing a file.
|
||||
TEST_METHOD(BackupSkipsUpdatesDirectory)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
|
||||
dir.WriteFile(L"Updates\\installer.exe", "fake exe");
|
||||
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
Assert::IsFalse(dir.FileExists(L"ConfigBackup\\Updates"));
|
||||
}
|
||||
|
||||
// Tests BackupConfigFiles: running backup twice overwrites the previous
|
||||
// backup with current file content.
|
||||
// Covers: configBackup.h BackupConfigFiles — fs::remove_all(backupDir) +
|
||||
// copy_options::overwrite_existing.
|
||||
// Setup: Backup, modify original, backup again.
|
||||
TEST_METHOD(BackupOverwritesPreviousBackup)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"settings.json", R"({"version":1})");
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
// Update the original
|
||||
dir.WriteFile(L"settings.json", R"({"version":2})");
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
Assert::AreEqual(std::string(R"({"version":2})"), dir.ReadFile(L"ConfigBackup\\settings.json"));
|
||||
}
|
||||
|
||||
// Tests BackupConfigFiles: non-.json files inside module subdirectories
|
||||
// (e.g., FancyZones/zones.dat) should NOT be backed up.
|
||||
// Covers: configBackup.h BackupConfigFiles — extension filter in module loop.
|
||||
TEST_METHOD(BackupSkipsNonJsonFilesInModuleDirs)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"settings.json", R"({})");
|
||||
dir.WriteFile(L"FancyZones\\settings.json", R"({"zones":[]})");
|
||||
dir.WriteFile(L"FancyZones\\zones.dat", "binary data");
|
||||
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\FancyZones\\settings.json"));
|
||||
Assert::IsFalse(dir.FileExists(L"ConfigBackup\\FancyZones\\zones.dat"));
|
||||
}
|
||||
|
||||
// Tests BackupConfigFiles: empty root directory with no files produces
|
||||
// an empty ConfigBackup dir without errors.
|
||||
// Covers: configBackup.h BackupConfigFiles — empty directory_iterator.
|
||||
TEST_METHOD(BackupEmptyRootDirSucceeds)
|
||||
{
|
||||
TempDir dir;
|
||||
// Root dir exists but has no files
|
||||
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup"));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CLASS(RestoreCorruptedConfigsTests)
|
||||
{
|
||||
public:
|
||||
// Tests RestoreCorruptedConfigs: corrupted root-level JSON file is restored
|
||||
// from the good backup copy.
|
||||
// Covers: configBackup.h RestoreCorruptedConfigs — root file restore branch,
|
||||
// fs::exists + IsJsonFileCorrupted + backup integrity check.
|
||||
// Setup: Good file -> backup -> corrupt original -> restore.
|
||||
TEST_METHOD(RestoreFixesCorruptedRootFile)
|
||||
{
|
||||
TempDir dir;
|
||||
const std::string goodContent = R"({"theme":"dark"})";
|
||||
dir.WriteFile(L"settings.json", goodContent);
|
||||
|
||||
// Backup
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
// Corrupt the original
|
||||
std::vector<char> corrupted(goodContent.size(), '\0');
|
||||
dir.WriteFileBytes(L"settings.json", corrupted);
|
||||
Assert::IsTrue(updating::IsJsonFileCorrupted(dir.path() / L"settings.json"));
|
||||
|
||||
// Restore
|
||||
updating::RestoreCorruptedConfigs(dir.path());
|
||||
|
||||
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"settings.json"));
|
||||
Assert::AreEqual(goodContent, dir.ReadFile(L"settings.json"));
|
||||
}
|
||||
|
||||
// Tests RestoreCorruptedConfigs: corrupted module-level JSON file is restored
|
||||
// from the good backup copy.
|
||||
// Covers: configBackup.h RestoreCorruptedConfigs — module directory branch,
|
||||
// moduleBackupEntry restore with integrity check.
|
||||
// Setup: Module file + root file -> backup -> corrupt module file -> restore.
|
||||
TEST_METHOD(RestoreFixesCorruptedModuleFile)
|
||||
{
|
||||
TempDir dir;
|
||||
const std::string goodContent = R"({"workspaces":[]})";
|
||||
dir.WriteFile(L"Workspaces\\workspaces.json", goodContent);
|
||||
dir.WriteFile(L"settings.json", R"({})");
|
||||
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
// Corrupt the module file
|
||||
std::vector<char> corrupted(goodContent.size(), '\0');
|
||||
dir.WriteFileBytes(L"Workspaces\\workspaces.json", corrupted);
|
||||
|
||||
updating::RestoreCorruptedConfigs(dir.path());
|
||||
|
||||
Assert::AreEqual(goodContent, dir.ReadFile(L"Workspaces\\workspaces.json"));
|
||||
}
|
||||
|
||||
// Tests RestoreCorruptedConfigs: clean (non-corrupted) files are NOT
|
||||
// overwritten by backup — preserves user changes made after backup.
|
||||
// Covers: configBackup.h RestoreCorruptedConfigs — IsJsonFileCorrupted
|
||||
// returns false, copy_file is skipped.
|
||||
// Setup: File -> backup -> modify (but keep valid) -> restore.
|
||||
TEST_METHOD(RestoreLeavesCleanFilesUntouched)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"settings.json", R"({"version":1})");
|
||||
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
// Modify original (but keep it clean JSON)
|
||||
dir.WriteFile(L"settings.json", R"({"version":2})");
|
||||
|
||||
updating::RestoreCorruptedConfigs(dir.path());
|
||||
|
||||
// Should NOT have been restored since it's not corrupted
|
||||
Assert::AreEqual(std::string(R"({"version":2})"), dir.ReadFile(L"settings.json"));
|
||||
}
|
||||
|
||||
// Tests RestoreCorruptedConfigs: when no ConfigBackup directory exists,
|
||||
// restore silently does nothing (no crash, no data loss).
|
||||
// Covers: configBackup.h RestoreCorruptedConfigs — !fs::exists(backupDir)
|
||||
// early return.
|
||||
// Setup: File with no prior backup.
|
||||
TEST_METHOD(RestoreHandlesMissingBackupDirectory)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
|
||||
|
||||
// No backup was created - restore should silently do nothing
|
||||
updating::RestoreCorruptedConfigs(dir.path());
|
||||
|
||||
Assert::AreEqual(std::string(R"({"theme":"dark"})"), dir.ReadFile(L"settings.json"));
|
||||
}
|
||||
|
||||
// Tests RestoreCorruptedConfigs: end-to-end scenario with multiple modules,
|
||||
// some corrupted and some clean, verifying selective restore.
|
||||
// Covers: configBackup.h RestoreCorruptedConfigs — both root and module
|
||||
// branches, selective restore based on corruption status.
|
||||
// Setup: 4 modules -> backup -> corrupt 2 -> restore -> verify all 4.
|
||||
TEST_METHOD(FullBackupAndRestoreRoundTrip)
|
||||
{
|
||||
TempDir dir;
|
||||
|
||||
// Set up a realistic config structure
|
||||
dir.WriteFile(L"settings.json", R"({"startup":true,"theme":"dark"})");
|
||||
dir.WriteFile(L"FancyZones\\settings.json", R"({"zones":[{"id":1}]})");
|
||||
dir.WriteFile(L"Workspaces\\workspaces.json", R"({"workspaces":[{"name":"dev"}]})");
|
||||
dir.WriteFile(L"KeyboardManager\\default.json", R"({"remaps":[]})");
|
||||
|
||||
// Backup
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
// Corrupt some files (simulating #46179 scenario)
|
||||
dir.WriteFileBytes(L"Workspaces\\workspaces.json", std::vector<char>(100, '\0'));
|
||||
dir.WriteFileBytes(L"settings.json", std::vector<char>(50, '\0'));
|
||||
// Leave FancyZones and KBM clean
|
||||
|
||||
// Restore
|
||||
updating::RestoreCorruptedConfigs(dir.path());
|
||||
|
||||
// Corrupted files should be restored
|
||||
Assert::AreEqual(std::string(R"({"startup":true,"theme":"dark"})"), dir.ReadFile(L"settings.json"));
|
||||
Assert::AreEqual(std::string(R"({"workspaces":[{"name":"dev"}]})"), dir.ReadFile(L"Workspaces\\workspaces.json"));
|
||||
|
||||
// Clean files should be unchanged
|
||||
Assert::AreEqual(std::string(R"({"zones":[{"id":1}]})"), dir.ReadFile(L"FancyZones\\settings.json"));
|
||||
Assert::AreEqual(std::string(R"({"remaps":[]})"), dir.ReadFile(L"KeyboardManager\\default.json"));
|
||||
}
|
||||
|
||||
// Tests RestoreCorruptedConfigs: when the original file has been deleted
|
||||
// (not corrupted), restore should NOT recreate it from backup. The installer
|
||||
// may have intentionally removed obsolete config files.
|
||||
// Covers: configBackup.h RestoreCorruptedConfigs — fs::exists guard.
|
||||
TEST_METHOD(RestoreSkipsDeletedOriginals)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"obsolete.json", R"({"old":true})");
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
// Installer deletes the file
|
||||
std::error_code ec;
|
||||
fs::remove(dir.path() / L"obsolete.json", ec);
|
||||
|
||||
updating::RestoreCorruptedConfigs(dir.path());
|
||||
|
||||
// Should NOT be recreated
|
||||
Assert::IsFalse(dir.FileExists(L"obsolete.json"));
|
||||
}
|
||||
|
||||
// Tests RestoreCorruptedConfigs: when the backup file itself is corrupted
|
||||
// (e.g., disk error during backup), restore should NOT copy corrupted
|
||||
// backup over the original — that would make things worse.
|
||||
// Covers: configBackup.h RestoreCorruptedConfigs — backup integrity check (B2 fix).
|
||||
TEST_METHOD(RestoreSkipsCorruptedBackup)
|
||||
{
|
||||
TempDir dir;
|
||||
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
// Corrupt BOTH the original AND the backup
|
||||
std::vector<char> nulls(50, '\0');
|
||||
dir.WriteFileBytes(L"settings.json", nulls);
|
||||
dir.WriteFileBytes(L"ConfigBackup\\settings.json", nulls);
|
||||
|
||||
updating::RestoreCorruptedConfigs(dir.path());
|
||||
|
||||
// Original should still be corrupted — we don't restore from bad backup
|
||||
Assert::IsTrue(updating::IsJsonFileCorrupted(dir.path() / L"settings.json"));
|
||||
}
|
||||
};
|
||||
|
||||
// Simulates what actually happens during a PowerToys upgrade:
|
||||
// 1. User has settings from normal use
|
||||
// 2. Updater backs up before install (Stage 1)
|
||||
// 3. Installer runs and corrupts some files (simulated)
|
||||
// 4. Updater restores corrupted files (Stage 2)
|
||||
// 5. PT relaunches and finds working configs
|
||||
TEST_CLASS(UpgradeSimulationTests)
|
||||
{
|
||||
public:
|
||||
// Tests full upgrade simulation: backup -> installer corrupts files -> restore.
|
||||
// Verifies that corrupted files are restored and clean files are untouched.
|
||||
// Covers: configBackup.h BackupConfigFiles + RestoreCorruptedConfigs —
|
||||
// end-to-end with 5 modules, 2 corrupted, 3 clean.
|
||||
// Setup: Realistic config structure with multiple modules.
|
||||
TEST_METHOD(SimulateUpgradeWithCorruption)
|
||||
{
|
||||
TempDir dir;
|
||||
|
||||
// === User's real config state before upgrade ===
|
||||
dir.WriteFile(L"settings.json",
|
||||
R"({"startup":true,"theme":"dark","run_elevated":false,"download_updates_automatically":true})");
|
||||
dir.WriteFile(L"FancyZones\\settings.json",
|
||||
R"({"zones":[{"id":1,"rect":{"x":0,"y":0,"w":960,"h":1080}}]})");
|
||||
dir.WriteFile(L"Workspaces\\workspaces.json",
|
||||
R"({"workspaces":[{"name":"dev","apps":["code","terminal"]}]})");
|
||||
dir.WriteFile(L"KeyboardManager\\default.json",
|
||||
R"({"remapKeys":{"inProcess":[{"original":"0x41","new":"0x42"}]}})");
|
||||
dir.WriteFile(L"MouseWithoutBorders\\settings.json",
|
||||
R"({"machineKey":"abc123","connectToAll":true})");
|
||||
|
||||
// Non-JSON files that should be left alone
|
||||
dir.WriteFile(L"update.log", "2026-04-11 update started");
|
||||
|
||||
// === Stage 1: Backup before killing PT ===
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
// Verify backup was created correctly
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\settings.json"));
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\FancyZones\\settings.json"));
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\Workspaces\\workspaces.json"));
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\KeyboardManager\\default.json"));
|
||||
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\MouseWithoutBorders\\settings.json"));
|
||||
Assert::IsFalse(dir.FileExists(L"ConfigBackup\\update.log"));
|
||||
|
||||
// === Installer runs: some files get corrupted (the #46179 scenario) ===
|
||||
// Workspaces JSON filled with null bytes
|
||||
dir.WriteFileBytes(L"Workspaces\\workspaces.json", std::vector<char>(512, '\0'));
|
||||
// Main settings partially corrupted (null bytes injected)
|
||||
std::vector<char> partialCorrupt = { '{', '"', 's', '\0', '\0', '\0', '\0', '}' };
|
||||
dir.WriteFileBytes(L"settings.json", partialCorrupt);
|
||||
|
||||
// FancyZones, KBM, and MWB survive the install fine
|
||||
// (this is realistic - not all files get corrupted)
|
||||
|
||||
// === Stage 2: Restore after install completes ===
|
||||
updating::RestoreCorruptedConfigs(dir.path());
|
||||
|
||||
// === Verify: PT relaunches and finds working configs ===
|
||||
|
||||
// Corrupted files should be restored from backup
|
||||
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"settings.json"));
|
||||
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"Workspaces\\workspaces.json"));
|
||||
Assert::AreEqual(
|
||||
std::string(R"({"startup":true,"theme":"dark","run_elevated":false,"download_updates_automatically":true})"),
|
||||
dir.ReadFile(L"settings.json"));
|
||||
Assert::AreEqual(
|
||||
std::string(R"({"workspaces":[{"name":"dev","apps":["code","terminal"]}]})"),
|
||||
dir.ReadFile(L"Workspaces\\workspaces.json"));
|
||||
|
||||
// Clean files should be untouched (not overwritten with backup)
|
||||
Assert::AreEqual(
|
||||
std::string(R"({"zones":[{"id":1,"rect":{"x":0,"y":0,"w":960,"h":1080}}]})"),
|
||||
dir.ReadFile(L"FancyZones\\settings.json"));
|
||||
Assert::AreEqual(
|
||||
std::string(R"({"remapKeys":{"inProcess":[{"original":"0x41","new":"0x42"}]}})"),
|
||||
dir.ReadFile(L"KeyboardManager\\default.json"));
|
||||
Assert::AreEqual(
|
||||
std::string(R"({"machineKey":"abc123","connectToAll":true})"),
|
||||
dir.ReadFile(L"MouseWithoutBorders\\settings.json"));
|
||||
}
|
||||
|
||||
// Tests upgrade from an old version that has fewer modules than the new version.
|
||||
// Verifies that new module configs (created by the installer) are not touched
|
||||
// by restore, while corrupted old configs are restored.
|
||||
// Covers: configBackup.h RestoreCorruptedConfigs — module dir in root that
|
||||
// has no corresponding backup entry.
|
||||
// Setup: Old version with 1 module -> backup -> new installer adds module -> corrupt old -> restore.
|
||||
TEST_METHOD(SimulateUpgradeFromVeryOldVersion)
|
||||
{
|
||||
TempDir dir;
|
||||
|
||||
// Old version had fewer modules - only settings.json
|
||||
dir.WriteFile(L"settings.json", R"({"theme":"dark","powertoys_version":"v0.60.0"})");
|
||||
|
||||
// Backup
|
||||
updating::BackupConfigFiles(dir.path());
|
||||
|
||||
// New installer creates new module dirs that didn't exist before
|
||||
dir.WriteFile(L"NewModule\\settings.json", R"({"enabled":true})");
|
||||
|
||||
// Old settings get corrupted during upgrade
|
||||
dir.WriteFileBytes(L"settings.json", std::vector<char>(100, '\0'));
|
||||
|
||||
// Restore
|
||||
updating::RestoreCorruptedConfigs(dir.path());
|
||||
|
||||
// Old settings restored
|
||||
Assert::AreEqual(
|
||||
std::string(R"({"theme":"dark","powertoys_version":"v0.60.0"})"),
|
||||
dir.ReadFile(L"settings.json"));
|
||||
|
||||
// New module settings untouched (no backup existed for them)
|
||||
Assert::AreEqual(
|
||||
std::string(R"({"enabled":true})"),
|
||||
dir.ReadFile(L"NewModule\\settings.json"));
|
||||
}
|
||||
};
|
||||
|
||||
// Tests for the update lifecycle: argument passing between Stage 1 and Stage 2,
|
||||
// relaunch path construction, and the handoff that was broken in #42004/#43011/#44071.
|
||||
TEST_CLASS(UpdateLifecycleTests)
|
||||
{
|
||||
public:
|
||||
// Tests BuildStage2Arguments: output contains the stage 2 flag, installer path,
|
||||
// and install directory — all three components needed for Stage 2.
|
||||
// Covers: updateLifecycle.h BuildStage2Arguments — concatenation logic.
|
||||
// Setup: Typical paths with spaces (Program Files).
|
||||
TEST_METHOD(BuildStage2ArgumentsContainsInstallerAndInstallDir)
|
||||
{
|
||||
const auto args = updating::BuildStage2Arguments(
|
||||
L"-update_now_stage_2",
|
||||
L"C:\\Users\\test\\AppData\\Local\\PowerToys\\Updates\\powertoyssetup-x64.exe",
|
||||
L"C:\\Program Files\\PowerToys");
|
||||
|
||||
// Must contain the stage 2 flag
|
||||
Assert::IsTrue(args.find(L"-update_now_stage_2") != std::wstring::npos);
|
||||
// Must contain the installer path (quoted)
|
||||
Assert::IsTrue(args.find(L"powertoyssetup-x64.exe") != std::wstring::npos);
|
||||
// Must contain the install directory (quoted) — this was MISSING before our fix
|
||||
Assert::IsTrue(args.find(L"C:\\Program Files\\PowerToys") != std::wstring::npos);
|
||||
}
|
||||
|
||||
// Tests BuildStage2Arguments: both paths are wrapped in double quotes to
|
||||
// survive CommandLineToArgvW parsing when paths contain spaces.
|
||||
// Covers: updateLifecycle.h BuildStage2Arguments — quote wrapping.
|
||||
// Setup: Installer path with spaces.
|
||||
TEST_METHOD(BuildStage2ArgumentsQuotesBothPaths)
|
||||
{
|
||||
const auto args = updating::BuildStage2Arguments(
|
||||
L"-update_now_stage_2",
|
||||
L"C:\\path with spaces\\installer.exe",
|
||||
L"C:\\Program Files\\PowerToys");
|
||||
|
||||
// Count quotes — should have 4 (open/close for each path)
|
||||
size_t quoteCount = std::count(args.begin(), args.end(), L'"');
|
||||
Assert::AreEqual(size_t{ 4 }, quoteCount);
|
||||
}
|
||||
|
||||
// Tests BuildPowerToysExePath: appends "PowerToys.exe" to the install dir.
|
||||
// Covers: updateLifecycle.h BuildPowerToysExePath — fs::path / operator.
|
||||
// Setup: Standard install path without trailing backslash.
|
||||
TEST_METHOD(BuildPowerToysExePathAppendsExeName)
|
||||
{
|
||||
const auto path = updating::BuildPowerToysExePath(L"C:\\Program Files\\PowerToys");
|
||||
Assert::AreEqual(std::wstring(L"C:\\Program Files\\PowerToys\\PowerToys.exe"), path);
|
||||
}
|
||||
|
||||
// Tests BuildPowerToysExePath: trailing backslash does not produce double
|
||||
// backslash (e.g., "...PowerToys\\PowerToys.exe").
|
||||
// Covers: updateLifecycle.h BuildPowerToysExePath — fs::path normalizes separators.
|
||||
// Setup: Install path with trailing backslash.
|
||||
TEST_METHOD(BuildPowerToysExePathHandlesTrailingBackslash)
|
||||
{
|
||||
const auto path = updating::BuildPowerToysExePath(L"C:\\Program Files\\PowerToys\\");
|
||||
Assert::AreEqual(std::wstring(L"C:\\Program Files\\PowerToys\\PowerToys.exe"), path);
|
||||
}
|
||||
|
||||
// Tests BuildPowerToysExePath: empty string produces just "PowerToys.exe".
|
||||
// Covers: updateLifecycle.h BuildPowerToysExePath — fs::path with empty input.
|
||||
// Setup: Empty install directory string.
|
||||
TEST_METHOD(BuildPowerToysExePathHandlesEmptyString)
|
||||
{
|
||||
const auto path = updating::BuildPowerToysExePath(L"");
|
||||
Assert::AreEqual(std::wstring(L"PowerToys.exe"), path);
|
||||
}
|
||||
|
||||
// Tests CanRelaunchAfterUpdate: returns true when Stage 2 receives
|
||||
// the install directory (argCount >= 4), false otherwise.
|
||||
// This is the gate that prevents relaunch when using an old Stage 1
|
||||
// that didn't pass the install dir (#42004/#43011/#44071).
|
||||
// Covers: updateLifecycle.h CanRelaunchAfterUpdate.
|
||||
TEST_METHOD(CanRelaunchReflectsArgCount)
|
||||
{
|
||||
// Old Stage 1 (pre-fix): only passed action + installer = 3 args
|
||||
Assert::IsFalse(updating::CanRelaunchAfterUpdate(0));
|
||||
Assert::IsFalse(updating::CanRelaunchAfterUpdate(1));
|
||||
Assert::IsFalse(updating::CanRelaunchAfterUpdate(2));
|
||||
Assert::IsFalse(updating::CanRelaunchAfterUpdate(3));
|
||||
|
||||
// New Stage 1 (post-fix): passes action + installer + installDir = 4 args
|
||||
Assert::IsTrue(updating::CanRelaunchAfterUpdate(4));
|
||||
Assert::IsTrue(updating::CanRelaunchAfterUpdate(5));
|
||||
}
|
||||
|
||||
// Tests BuildStage2Arguments + CommandLineToArgvW round-trip: the exact
|
||||
// scenario where Stage 1 builds args and Windows parses them in Stage 2.
|
||||
// Verifies quoting is correct so paths with spaces survive the round trip.
|
||||
// Covers: updateLifecycle.h BuildStage2Arguments — quote correctness.
|
||||
// Setup: Realistic paths with spaces and version numbers.
|
||||
TEST_METHOD(Stage2ArgumentsCanBeRoundTrippedThroughCommandLineToArgvW)
|
||||
{
|
||||
const std::wstring installerPath = L"C:\\Users\\test user\\AppData\\Local\\PowerToys\\Updates\\powertoyssetup-0.86.0-x64.exe";
|
||||
const std::wstring installDir = L"C:\\Program Files\\PowerToys";
|
||||
|
||||
const auto args = updating::BuildStage2Arguments(L"-update_now_stage_2", installerPath, installDir);
|
||||
|
||||
// Simulate what Windows does: prepend a fake exe name and parse
|
||||
std::wstring commandLine = L"PowerToys.Update.exe " + args;
|
||||
|
||||
int argc = 0;
|
||||
LPWSTR* argv = CommandLineToArgvW(commandLine.c_str(), &argc);
|
||||
Assert::IsNotNull(argv);
|
||||
Assert::AreEqual(4, argc);
|
||||
Assert::AreEqual(std::wstring(L"-update_now_stage_2"), std::wstring(argv[1]));
|
||||
Assert::AreEqual(installerPath, std::wstring(argv[2]));
|
||||
Assert::AreEqual(installDir, std::wstring(argv[3]));
|
||||
|
||||
LocalFree(argv);
|
||||
}
|
||||
};
|
||||
}
|
||||
45
src/common/updating/UnitTests/UpdatingUnitTests.vcxproj
Normal file
45
src/common/updating/UnitTests/UpdatingUnitTests.vcxproj
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>UpdatingUnitTests</RootNamespace>
|
||||
<ProjectSubType>NativeUnitTestProject</ProjectSubType>
|
||||
<ProjectName>Updating.UnitTests</ProjectName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\tests\UpdatingUnitTests\</OutDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\;..\..\;..\..\..\;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="UpdatingTests.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
5
src/common/updating/UnitTests/pch.cpp
Normal file
5
src/common/updating/UnitTests/pch.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// 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.
|
||||
|
||||
#include "pch.h"
|
||||
17
src/common/updating/UnitTests/pch.h
Normal file
17
src/common/updating/UnitTests/pch.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
#include <atomic>
|
||||
#include <Windows.h>
|
||||
|
||||
// Suppressing 26466 - Don't use static_cast downcasts - in CppUnitTest.h
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26466)
|
||||
#include "CppUnitTest.h"
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif //PCH_H
|
||||
170
src/common/updating/configBackup.h
Normal file
170
src/common/updating/configBackup.h
Normal file
@@ -0,0 +1,170 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
namespace updating
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// Check if a JSON file is corrupted (contains null bytes, as seen in #46179)
|
||||
inline bool IsJsonFileCorrupted(const fs::path& filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::ifstream file(filePath, std::ios::binary);
|
||||
if (!file.is_open())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr size_t c_readChunkSize{ 4096 };
|
||||
char buffer[c_readChunkSize];
|
||||
while (file.read(buffer, c_readChunkSize) || file.gcount() > 0)
|
||||
{
|
||||
const auto bytesRead = file.gcount();
|
||||
for (std::streamsize i = 0; i < bytesRead; ++i)
|
||||
{
|
||||
if (buffer[i] == '\0')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Backup all JSON config files before update to protect against corruption (#46179)
|
||||
inline void BackupConfigFiles(const fs::path& rootPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
const fs::path backupDir = rootPath / L"ConfigBackup";
|
||||
|
||||
std::error_code ec;
|
||||
fs::remove_all(backupDir, ec);
|
||||
// Note: remove_all failure means stale backup may persist; continue anyway
|
||||
// since create_directories will overlay
|
||||
fs::create_directories(backupDir, ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& entry : fs::directory_iterator(rootPath, ec))
|
||||
{
|
||||
if (ec)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (entry.is_regular_file() && entry.path().extension() == L".json")
|
||||
{
|
||||
fs::copy_file(entry.path(), backupDir / entry.path().filename(), fs::copy_options::overwrite_existing, ec);
|
||||
}
|
||||
else if (entry.is_directory())
|
||||
{
|
||||
const auto dirName = entry.path().filename().wstring();
|
||||
if (dirName == L"ConfigBackup" || dirName == L"Updates")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto moduleBackup = backupDir / entry.path().filename();
|
||||
fs::create_directories(moduleBackup, ec);
|
||||
|
||||
std::error_code moduleEc;
|
||||
for (const auto& moduleEntry : fs::directory_iterator(entry.path(), moduleEc))
|
||||
{
|
||||
if (moduleEc)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (moduleEntry.is_regular_file() && moduleEntry.path().extension() == L".json")
|
||||
{
|
||||
fs::copy_file(moduleEntry.path(), moduleBackup / moduleEntry.path().filename(), fs::copy_options::overwrite_existing, moduleEc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Intentionally swallowed — update must not fail due to backup errors.
|
||||
// Logging would require spdlog dependency which is unavailable in test context.
|
||||
}
|
||||
}
|
||||
|
||||
// Restore JSON configs from backup if corruption is detected after update
|
||||
inline void RestoreCorruptedConfigs(const fs::path& rootPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
const fs::path backupDir = rootPath / L"ConfigBackup";
|
||||
|
||||
if (!fs::exists(backupDir))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
for (const auto& backupEntry : fs::directory_iterator(backupDir, ec))
|
||||
{
|
||||
if (ec)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (backupEntry.is_regular_file() && backupEntry.path().extension() == L".json")
|
||||
{
|
||||
const auto originalPath = rootPath / backupEntry.path().filename();
|
||||
// Only restore if the backup itself is valid
|
||||
if (fs::exists(originalPath) && IsJsonFileCorrupted(originalPath) && !IsJsonFileCorrupted(backupEntry.path()))
|
||||
{
|
||||
fs::copy_file(backupEntry.path(), originalPath, fs::copy_options::overwrite_existing, ec);
|
||||
}
|
||||
}
|
||||
else if (backupEntry.is_directory())
|
||||
{
|
||||
const auto moduleDir = rootPath / backupEntry.path().filename();
|
||||
|
||||
std::error_code moduleEc;
|
||||
for (const auto& moduleBackupEntry : fs::directory_iterator(backupEntry.path(), moduleEc))
|
||||
{
|
||||
if (moduleEc)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (moduleBackupEntry.is_regular_file() && moduleBackupEntry.path().extension() == L".json")
|
||||
{
|
||||
const auto originalModulePath = moduleDir / moduleBackupEntry.path().filename();
|
||||
// Only restore if the backup itself is valid
|
||||
if (fs::exists(originalModulePath) && IsJsonFileCorrupted(originalModulePath) && !IsJsonFileCorrupted(moduleBackupEntry.path()))
|
||||
{
|
||||
fs::copy_file(moduleBackupEntry.path(), originalModulePath, fs::copy_options::overwrite_existing, moduleEc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Intentionally swallowed — update must not fail due to backup errors.
|
||||
// Logging would require spdlog dependency which is unavailable in test context.
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/common/updating/updateLifecycle.h
Normal file
47
src/common/updating/updateLifecycle.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
namespace updating
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// Build the command-line arguments for Stage 2.
|
||||
// Stage 1 passes the installer path and the PT install directory
|
||||
// so Stage 2 can run the installer and relaunch PowerToys afterward.
|
||||
// Note: paths containing embedded double-quote characters are not supported.
|
||||
// This is safe because install paths come from get_module_folderpath().
|
||||
inline std::wstring BuildStage2Arguments(
|
||||
const std::wstring& stage2Flag,
|
||||
const fs::path& installerPath,
|
||||
const fs::path& installDir)
|
||||
{
|
||||
std::wstring arguments{ stage2Flag };
|
||||
arguments += L" \"";
|
||||
arguments += installerPath.c_str();
|
||||
arguments += L"\" \"";
|
||||
arguments += installDir.c_str();
|
||||
arguments += L"\"";
|
||||
return arguments;
|
||||
}
|
||||
|
||||
// Build the full path to PowerToys.exe from the install directory.
|
||||
// Used by Stage 2 to relaunch PT after a successful update.
|
||||
inline std::wstring BuildPowerToysExePath(const std::wstring& installDir)
|
||||
{
|
||||
return (std::filesystem::path(installDir) / L"PowerToys.exe").wstring();
|
||||
}
|
||||
|
||||
// Determine whether Stage 2 has enough information to relaunch PT.
|
||||
// Returns true if the install directory argument was provided.
|
||||
inline bool CanRelaunchAfterUpdate(int argCount)
|
||||
{
|
||||
// args[0]=exe, args[1]=action, args[2]=installer, args[3]=installDir
|
||||
return argCount >= 4;
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ public class BaseDscTest
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the resource string.</param>
|
||||
/// <param name="args">The arguments to format the resource string with.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>The formatted resource string.</returns>
|
||||
public string GetResourceString(string name, params string[] args)
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, _resourceManager.GetString(name, CultureInfo.InvariantCulture), args);
|
||||
@@ -35,9 +35,9 @@ public class BaseDscTest
|
||||
/// <summary>
|
||||
/// Execute a dsc command with the provided arguments.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
/// <typeparam name="T">The type of the DSC command to execute.</typeparam>
|
||||
/// <param name="args">The command-line arguments to pass to the DSC command.</param>
|
||||
/// <returns>The result of the DSC command execution.</returns>
|
||||
protected DscExecuteResult ExecuteDscCommand<T>(params string[] args)
|
||||
where T : Command, new()
|
||||
{
|
||||
|
||||
@@ -47,6 +47,6 @@ public interface ISettingsFunctionData
|
||||
/// <summary>
|
||||
/// Gets the schema for the settings resource object.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <returns>The JSON schema string for the settings resource object.</returns>
|
||||
public string Schema();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class BaseResourceObject
|
||||
/// <summary>
|
||||
/// Generates a JSON representation of the resource object.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <returns>A JSON representation of the resource object.</returns>
|
||||
public JsonNode ToJson()
|
||||
{
|
||||
return JsonSerializer.SerializeToNode(this, GetType(), _options) ?? new JsonObject();
|
||||
|
||||
@@ -150,7 +150,6 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<!-- TEMPORARILY_DISABLED: PowerDisplay
|
||||
<policy name="ConfigureEnabledUtilityPowerDisplay" class="Both" displayName="$(string.ConfigureEnabledUtilityPowerDisplay)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityPowerDisplay">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_95_0" />
|
||||
@@ -161,7 +160,6 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
-->
|
||||
<policy name="ConfigureEnabledUtilityEnvironmentVariables" class="Both" displayName="$(string.ConfigureEnabledUtilityEnvironmentVariables)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityEnvironmentVariables">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_75_0" />
|
||||
|
||||
@@ -249,7 +249,7 @@ If you don't configure this policy, the user will be able to control the setting
|
||||
<string id="ConfigureEnabledUtilityCmdPal">CmdPal: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityCropAndLock">Crop And Lock: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityLightSwitch">Light Switch: Configure enabled state</string>
|
||||
<!-- <string id="ConfigureEnabledUtilityPowerDisplay">PowerDisplay: Configure enabled state</string> --><!-- TEMPORARILY_DISABLED: PowerDisplay -->
|
||||
<string id="ConfigureEnabledUtilityPowerDisplay">PowerDisplay: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityEnvironmentVariables">Environment Variables: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFancyZones">FancyZones: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileLocksmith">File Locksmith: Configure enabled state</string>
|
||||
|
||||
@@ -70,12 +70,12 @@
|
||||
Spacing="2">
|
||||
<TextBlock
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{x:Bind Header, Mode=OneWay}"
|
||||
Text="{x:Bind Header, Mode=OneTime}"
|
||||
TextWrapping="NoWrap" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Timestamp, Converter={StaticResource DateTimeToFriendlyStringConverter}, Mode=OneWay}" />
|
||||
Text="{x:Bind Timestamp, Converter={StaticResource DateTimeToFriendlyStringConverter}, Mode=OneTime}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -29,31 +29,31 @@
|
||||
Padding="-9,0,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
AutomationProperties.AcceleratorKey="{x:Bind ShortcutText, Mode=OneWay}"
|
||||
AutomationProperties.AcceleratorKey="{x:Bind ShortcutText, Mode=OneTime}"
|
||||
AutomationProperties.AutomationControlType="ListItem"
|
||||
AutomationProperties.FullDescription="{x:Bind ToolTip, Mode=OneWay}"
|
||||
AutomationProperties.HelpText="{x:Bind Name, Mode=OneWay}"
|
||||
AutomationProperties.Name="{x:Bind AccessibleName, Mode=OneWay}">
|
||||
AutomationProperties.FullDescription="{x:Bind ToolTip, Mode=OneTime}"
|
||||
AutomationProperties.HelpText="{x:Bind Name, Mode=OneTime}"
|
||||
AutomationProperties.Name="{x:Bind AccessibleName, Mode=OneTime}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="48" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock Text="{x:Bind ToolTip, Mode=OneWay}" />
|
||||
<TextBlock Text="{x:Bind ToolTip, Mode=OneTime}" />
|
||||
</ToolTipService.ToolTip>
|
||||
<FontIcon
|
||||
Margin="0,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontSize="16"
|
||||
Glyph="{x:Bind IconGlyph, Mode=OneWay}" />
|
||||
Glyph="{x:Bind IconGlyph, Mode=OneTime}" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
x:Phase="1"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Name, Mode=OneWay}" />
|
||||
Text="{x:Bind Name, Mode=OneTime}" />
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
Margin="0,0,8,0"
|
||||
@@ -61,7 +61,7 @@
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind ShortcutText, Mode=OneWay}" />
|
||||
Text="{x:Bind ShortcutText, Mode=OneTime}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</controls:PasteFormatTemplateSelector.ItemTemplate>
|
||||
@@ -83,13 +83,13 @@
|
||||
Margin="0,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Glyph="{x:Bind IconGlyph, Mode=OneWay}" />
|
||||
Glyph="{x:Bind IconGlyph, Mode=OneTime}" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
x:Phase="1"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Name, Mode=OneWay}" />
|
||||
Text="{x:Bind Name, Mode=OneTime}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</controls:PasteFormatTemplateSelector.ItemTemplateDisabled>
|
||||
@@ -198,7 +198,7 @@
|
||||
<ItemsView.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:ClipboardItem">
|
||||
<ItemContainer
|
||||
AutomationProperties.Name="{x:Bind Description, Mode=OneWay}"
|
||||
AutomationProperties.Name="{x:Bind Description, Mode=OneTime}"
|
||||
CornerRadius="16"
|
||||
ToolTipService.ToolTip="{x:Bind Content}">
|
||||
<Grid
|
||||
|
||||
180
src/modules/Hosts/Hosts.Tests/ValidationHelperTest.cs
Normal file
180
src/modules/Hosts/Hosts.Tests/ValidationHelperTest.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
// 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.Linq;
|
||||
|
||||
using HostsUILib;
|
||||
using HostsUILib.Helpers;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Hosts.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class ValidationHelperTest
|
||||
{
|
||||
[DataTestMethod]
|
||||
[DataRow("0.0.0.0")]
|
||||
[DataRow("127.0.0.1")]
|
||||
[DataRow("192.168.1.1")]
|
||||
[DataRow("255.255.255.255")]
|
||||
[DataRow("10.0.0.1")]
|
||||
[DataRow("172.16.0.1")]
|
||||
[DataRow("1.2.3.4")]
|
||||
[DataRow("01.01.01.01")]
|
||||
[DataRow("0.0.0.1")]
|
||||
public void ValidIPv4_ValidAddresses_ReturnsTrue(string address)
|
||||
{
|
||||
Assert.IsTrue(ValidationHelper.ValidIPv4(address));
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("256.0.0.0")]
|
||||
[DataRow("0.256.0.0")]
|
||||
[DataRow("0.0.256.0")]
|
||||
[DataRow("0.0.0.256")]
|
||||
[DataRow("999.999.999.999")]
|
||||
[DataRow("1.2.3")]
|
||||
[DataRow("1.2.3.4.5")]
|
||||
[DataRow("1.2.3.")]
|
||||
[DataRow(".1.2.3")]
|
||||
[DataRow("1..2.3")]
|
||||
[DataRow("abc.def.ghi.jkl")]
|
||||
[DataRow("192.168.1.1/24")]
|
||||
[DataRow("192.168.1.1:80")]
|
||||
[DataRow("192.168.1")]
|
||||
[DataRow("-1.0.0.0")]
|
||||
public void ValidIPv4_InvalidAddresses_ReturnsFalse(string address)
|
||||
{
|
||||
Assert.IsFalse(ValidationHelper.ValidIPv4(address));
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null)]
|
||||
[DataRow("")]
|
||||
[DataRow(" ")]
|
||||
[DataRow("\t")]
|
||||
[DataRow("\n")]
|
||||
public void ValidIPv4_NullOrWhitespace_ReturnsFalse(string address)
|
||||
{
|
||||
Assert.IsFalse(ValidationHelper.ValidIPv4(address));
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("::1")]
|
||||
[DataRow("::")]
|
||||
[DataRow("2001:0db8:85a3:0000:0000:8a2e:0370:7334")]
|
||||
[DataRow("2001:db8:85a3:0:0:8a2e:370:7334")]
|
||||
[DataRow("2001:db8:85a3::8a2e:370:7334")]
|
||||
[DataRow("fe80::1")]
|
||||
[DataRow("ff02::1")]
|
||||
[DataRow("2001:db8::1")]
|
||||
[DataRow("::ffff:192.168.1.1")]
|
||||
[DataRow("fe80::1%eth0")]
|
||||
public void ValidIPv6_ValidAddresses_ReturnsTrue(string address)
|
||||
{
|
||||
Assert.IsTrue(ValidationHelper.ValidIPv6(address));
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("2001:db8:85a3:0:0:8a2e:370:7334:extra")]
|
||||
[DataRow("gggg::1")]
|
||||
[DataRow("12345::1")]
|
||||
[DataRow("192.168.1.1")]
|
||||
[DataRow("::ffff:999.999.999.999")]
|
||||
[DataRow("hello")]
|
||||
[DataRow("2001:db8:85a3::8a2e:370:7334:1234:5678")]
|
||||
public void ValidIPv6_InvalidAddresses_ReturnsFalse(string address)
|
||||
{
|
||||
Assert.IsFalse(ValidationHelper.ValidIPv6(address));
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null)]
|
||||
[DataRow("")]
|
||||
[DataRow(" ")]
|
||||
[DataRow("\t")]
|
||||
public void ValidIPv6_NullOrWhitespace_ReturnsFalse(string address)
|
||||
{
|
||||
Assert.IsFalse(ValidationHelper.ValidIPv6(address));
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("localhost")]
|
||||
[DataRow("example.com")]
|
||||
[DataRow("sub.domain.example.com")]
|
||||
[DataRow("my-host")]
|
||||
[DataRow("host1 host2")]
|
||||
[DataRow("host1 host2 host3")]
|
||||
[DataRow("example.com www.example.com")]
|
||||
public void ValidHosts_ValidHostnames_ReturnsTrue(string hosts)
|
||||
{
|
||||
Assert.IsTrue(ValidationHelper.ValidHosts(hosts, validateHostsLength: false));
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null)]
|
||||
[DataRow("")]
|
||||
[DataRow(" ")]
|
||||
[DataRow("\t")]
|
||||
public void ValidHosts_NullOrWhitespace_ReturnsFalse(string hosts)
|
||||
{
|
||||
Assert.IsFalse(ValidationHelper.ValidHosts(hosts, validateHostsLength: false));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ValidHosts_WithLengthValidation_ExceedsMaxCount_ReturnsFalse()
|
||||
{
|
||||
// Create a host string with one more than MaxHostsCount hosts
|
||||
var hosts = string.Join(" ", Enumerable.Range(1, Consts.MaxHostsCount + 1).Select(i => $"h{i}"));
|
||||
Assert.IsFalse(ValidationHelper.ValidHosts(hosts, validateHostsLength: true));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ValidHosts_WithLengthValidation_AtMaxCount_ReturnsTrue()
|
||||
{
|
||||
// Create a host string with exactly MaxHostsCount hosts
|
||||
var hosts = string.Join(" ", Enumerable.Range(1, Consts.MaxHostsCount).Select(i => $"h{i}"));
|
||||
Assert.IsTrue(ValidationHelper.ValidHosts(hosts, validateHostsLength: true));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ValidHosts_WithLengthValidation_BelowMaxCount_ReturnsTrue()
|
||||
{
|
||||
string hosts = "host1 host2 host3";
|
||||
Assert.IsTrue(ValidationHelper.ValidHosts(hosts, validateHostsLength: true));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ValidHosts_WithoutLengthValidation_ExceedsMaxCount_ReturnsTrue()
|
||||
{
|
||||
// When validateHostsLength is false, exceeding max count should still return true
|
||||
var hosts = string.Join(" ", Enumerable.Range(1, Consts.MaxHostsCount + 1).Select(i => $"h{i}"));
|
||||
Assert.IsTrue(ValidationHelper.ValidHosts(hosts, validateHostsLength: false));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ValidHosts_SingleHost_ReturnsTrue()
|
||||
{
|
||||
Assert.IsTrue(ValidationHelper.ValidHosts("localhost", validateHostsLength: true));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ValidHosts_InvalidHostname_ReturnsFalse()
|
||||
{
|
||||
Assert.IsFalse(ValidationHelper.ValidHosts("host_with!invalid@chars", validateHostsLength: false));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ValidHosts_HostWithSubdomains_ReturnsTrue()
|
||||
{
|
||||
Assert.IsTrue(ValidationHelper.ValidHosts("sub.domain.example.com", validateHostsLength: true));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ValidHosts_MultipleValidHosts_WithLengthValidation_ReturnsTrue()
|
||||
{
|
||||
Assert.IsTrue(ValidationHelper.ValidHosts("example.com www.example.com api.example.com", validateHostsLength: true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
|
||||
</packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.250325.1" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
@@ -29,11 +30,12 @@ namespace PowerOCR;
|
||||
|
||||
internal sealed class ImageMethods
|
||||
{
|
||||
internal static Bitmap PadImage(Bitmap image, int minW = 64, int minH = 64)
|
||||
internal static bool PadImage(Bitmap image, [NotNullWhen(true)] out Bitmap? paddedBitmap, int minW = 64, int minH = 64)
|
||||
{
|
||||
if (image.Height >= minH && image.Width >= minW)
|
||||
{
|
||||
return image;
|
||||
paddedBitmap = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
int width = Math.Max(image.Width + 16, minW + 16);
|
||||
@@ -45,8 +47,9 @@ internal sealed class ImageMethods
|
||||
|
||||
gd.Clear(image.GetPixel(0, 0));
|
||||
gd.DrawImageUnscaled(image, 8, 8);
|
||||
paddedBitmap = destination;
|
||||
|
||||
return destination;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static ImageSource GetWindowBoundsImage(OCROverlay passedWindow)
|
||||
@@ -77,8 +80,15 @@ internal sealed class ImageMethods
|
||||
bmp.Size,
|
||||
CopyPixelOperation.SourceCopy);
|
||||
|
||||
bmp = PadImage(bmp);
|
||||
return bmp;
|
||||
if (PadImage(bmp, out var paddedBmp))
|
||||
{
|
||||
bmp.Dispose();
|
||||
return paddedBmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
return bmp;
|
||||
}
|
||||
}
|
||||
|
||||
internal static async Task<string> GetRegionsText(OCROverlay? passedWindow, Rectangle selectedRegion, Language? preferredLanguage)
|
||||
|
||||
48
src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/.github/copilot-instructions.md
vendored
Normal file
48
src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# Command Palette Extension – Copilot Instructions
|
||||
|
||||
Concise guidance for AI-assisted development of this Command Palette extension.
|
||||
|
||||
## Project Structure
|
||||
|
||||
| Folder | Purpose |
|
||||
|--------|---------|
|
||||
| `Pages/` | Extension pages (ListPage, ContentPage, DynamicListPage implementations) |
|
||||
| `Assets/` | Icons and images (StoreLogo.png, etc.) |
|
||||
| `Properties/` | Launch settings and publish profiles |
|
||||
| Root `.cs` files | Extension entry point, COM server (Program.cs), and CommandsProvider |
|
||||
|
||||
## Key Conventions
|
||||
|
||||
- Extensions run **out-of-process** via COM server registration
|
||||
- `Program.cs` hosts the COM server — do not modify the hosting pattern
|
||||
- The `CommandProvider` subclass is the entry point for all commands
|
||||
- Pages are **ICommand** implementations — they can be used anywhere commands are used
|
||||
- Always **Deploy** (not just Build) to register the MSIX package
|
||||
- After deploying, use the **Reload** command in Command Palette to refresh
|
||||
|
||||
## Build & Deploy
|
||||
|
||||
1. In Visual Studio, use **Build > Deploy** (not just Build)
|
||||
2. In Command Palette, run `Reload` → select "Reload Command Palette extensions"
|
||||
3. For debugging, run in Debug configuration (F5) and check Output window (Ctrl+Alt+O)
|
||||
|
||||
## Source Control
|
||||
|
||||
If using git, remove these lines from `.gitignore` (needed for deployment):
|
||||
- `**/Properties/launchSettings.json`
|
||||
- `*.pubxml`
|
||||
|
||||
## Available Skills
|
||||
|
||||
This project includes Copilot skills for common workflows:
|
||||
- **add-adaptive-card-form** — Create form-based UI with Adaptive Cards
|
||||
- **add-extension-settings** — Add a settings page to your extension
|
||||
- **add-dock-band** — Add persistent toolbar widgets
|
||||
- **add-fallback-commands** — Add catch-all search commands
|
||||
- **publish-extension** — Publish to Microsoft Store or WinGet
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Creating an extension](https://learn.microsoft.com/windows/powertoys/command-palette/creating-an-extension)
|
||||
- [Extension samples](https://learn.microsoft.com/windows/powertoys/command-palette/samples)
|
||||
- [Extensibility overview](https://learn.microsoft.com/windows/powertoys/command-palette/extensibility-overview)
|
||||
@@ -0,0 +1,353 @@
|
||||
---
|
||||
description: 'Comprehensive guide for developing Command Palette extensions — covers pages, content, commands, items, icons, settings, dock, and debugging'
|
||||
applyTo: '**/*.cs'
|
||||
---
|
||||
|
||||
# Command Palette Extension Development
|
||||
|
||||
Complete reference for building Command Palette (CmdPal) extensions. Extensions run out-of-process as MSIX-packaged COM servers.
|
||||
|
||||
## Extension Architecture
|
||||
|
||||
### IExtension Interface
|
||||
|
||||
The root class implements `IExtension` and `IDisposable`:
|
||||
|
||||
```csharp
|
||||
[Guid("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF")]
|
||||
public sealed partial class MyExtension : IExtension, IDisposable
|
||||
{
|
||||
private readonly ManualResetEvent _extensionDisposedEvent;
|
||||
private readonly MyCommandsProvider _provider = new();
|
||||
|
||||
public MyExtension(ManualResetEvent extensionDisposedEvent)
|
||||
{
|
||||
_extensionDisposedEvent = extensionDisposedEvent;
|
||||
}
|
||||
|
||||
public object? GetProvider(ProviderType providerType) => providerType switch
|
||||
{
|
||||
ProviderType.Commands => _provider,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
public void Dispose() => _extensionDisposedEvent.Set();
|
||||
}
|
||||
```
|
||||
|
||||
- Only `ProviderType.Commands` is currently supported
|
||||
- The `[Guid]` must match the CLSID in `Package.appxmanifest`
|
||||
|
||||
### CommandProvider
|
||||
|
||||
Override `TopLevelCommands()` to register main commands. Optionally override `FallbackCommands()` and `GetDockBands()`:
|
||||
|
||||
```csharp
|
||||
public partial class MyCommandsProvider : CommandProvider
|
||||
{
|
||||
public MyCommandsProvider()
|
||||
{
|
||||
DisplayName = "My Extension";
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.png");
|
||||
}
|
||||
|
||||
public override ICommandItem[] TopLevelCommands() => [
|
||||
new CommandItem(new MyPage()) { Title = DisplayName },
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### COM Server (Program.cs)
|
||||
|
||||
`Program.cs` hosts the COM server. Do not change this pattern:
|
||||
|
||||
```csharp
|
||||
public class Program
|
||||
{
|
||||
[MTAThread]
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
if (args.Length > 0 && args[0] == "-RegisterProcessAsComServer")
|
||||
{
|
||||
global::Shmuelie.WinRTServer.ComServer server = new();
|
||||
ManualResetEvent extensionDisposedEvent = new(false);
|
||||
var extensionInstance = new MyExtension(extensionDisposedEvent);
|
||||
server.RegisterClass<MyExtension, IExtension>(() => extensionInstance);
|
||||
server.Start();
|
||||
extensionDisposedEvent.WaitOne();
|
||||
server.Stop();
|
||||
server.UnsafeDispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Package.appxmanifest
|
||||
|
||||
Two critical extension registrations must be present:
|
||||
|
||||
1. **COM server** — `com:ComServer` with matching CLSID and `-RegisterProcessAsComServer` args
|
||||
2. **App extension** — `uap3:AppExtension` with `Name="com.microsoft.commandpalette"` and `CreateInstance ClassId` matching the GUID
|
||||
|
||||
The CLSID must be identical in three places: the `[Guid]` attribute, the `com:Class Id`, and the `CreateInstance ClassId`.
|
||||
|
||||
## Page Types
|
||||
|
||||
### ListPage (Most Common)
|
||||
|
||||
Displays a searchable list of items:
|
||||
|
||||
```csharp
|
||||
internal sealed partial class MyPage : ListPage
|
||||
{
|
||||
public MyPage()
|
||||
{
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.png");
|
||||
Title = "My page";
|
||||
Name = "Open";
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems() => [
|
||||
new ListItem(new OpenUrlCommand("https://example.com")) { Title = "Example" },
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### DynamicListPage (Search-Reactive)
|
||||
|
||||
Responds to search text changes for filtering or live queries:
|
||||
|
||||
```csharp
|
||||
internal sealed partial class MyDynamicPage : DynamicListPage
|
||||
{
|
||||
private IListItem[] _filteredItems = [];
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch)
|
||||
{
|
||||
_filteredItems = _allItems
|
||||
.Where(i => i.Title.Contains(newSearch, StringComparison.OrdinalIgnoreCase))
|
||||
.ToArray();
|
||||
RaiseItemsChanged();
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems() => _filteredItems;
|
||||
}
|
||||
```
|
||||
|
||||
- Supports `Filters` property for category filtering
|
||||
- Call `RaiseItemsChanged()` after updating items to notify the UI
|
||||
|
||||
### ContentPage (Rich Content)
|
||||
|
||||
Displays rich content like markdown, forms, or images:
|
||||
|
||||
```csharp
|
||||
internal sealed partial class MyContentPage : ContentPage
|
||||
{
|
||||
public override IContent[] GetContent() => [
|
||||
new MarkdownContent("# Hello\nThis is **markdown**."),
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
- Can return multiple `IContent` items (mix markdown, forms, images, etc.)
|
||||
- Supports `Commands` property for context menu items via `CommandContextItem`
|
||||
|
||||
## Content Types
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `MarkdownContent(string)` | Renders markdown with headers, links, code blocks, tables, images |
|
||||
| `FormContent` | Adaptive Cards forms with `TemplateJson`, optional `DataJson`, and `SubmitForm()` |
|
||||
| `PlainTextContent(string)` | Plain text; optional `FontFamily.Monospace` and `WrapWords` |
|
||||
| `ImageContent` | Images with `MaxWidth`/`MaxHeight` constraints |
|
||||
| `TreeContent` | Hierarchical nested content; override `GetChildren()` for child `IContent[]` |
|
||||
|
||||
### MarkdownContent Images
|
||||
|
||||
Supports `file:`, `data:` (base64), and `https:` URLs. Image hints control rendering:
|
||||
|
||||
```markdown
|
||||

|
||||
```
|
||||
|
||||
### FormContent (Adaptive Cards)
|
||||
|
||||
```csharp
|
||||
internal sealed partial class MyForm : FormContent
|
||||
{
|
||||
public MyForm()
|
||||
{
|
||||
TemplateJson = """{ "type": "AdaptiveCard", ... }""";
|
||||
DataJson = """{ "name": "default" }""";
|
||||
}
|
||||
|
||||
public override CommandResult SubmitForm(string payload)
|
||||
{
|
||||
var data = JsonSerializer.Deserialize<MyFormData>(payload);
|
||||
return CommandResult.Dismiss();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Design cards visually at [adaptivecards.io/designer](https://adaptivecards.io/designer)
|
||||
- Use `${...}` placeholders in `TemplateJson` bound to `DataJson` properties
|
||||
|
||||
## Commands
|
||||
|
||||
### InvokableCommand
|
||||
|
||||
Actions that do something when activated:
|
||||
|
||||
```csharp
|
||||
internal sealed partial class MyCommand : InvokableCommand
|
||||
{
|
||||
public override string Name => "Do it";
|
||||
public override IconInfo Icon => new("\uE945");
|
||||
|
||||
public override CommandResult Invoke()
|
||||
{
|
||||
// Do work here
|
||||
return CommandResult.Dismiss();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Built-in Command Helpers
|
||||
|
||||
| Helper | Purpose |
|
||||
|--------|---------|
|
||||
| `OpenUrlCommand(string url)` | Open URL in default browser |
|
||||
| `CopyTextCommand(string text)` | Copy to clipboard with toast |
|
||||
| `NoOpCommand()` | Does nothing (placeholder) |
|
||||
| `AnonymousCommand(Action? action)` | Lambda command; set `Result` property for navigation |
|
||||
|
||||
### CommandResult Types
|
||||
|
||||
| Result | Behavior |
|
||||
|--------|----------|
|
||||
| `CommandResult.Dismiss()` | Hide palette, go home |
|
||||
| `CommandResult.KeepOpen()` | Stay on current page |
|
||||
| `CommandResult.Hide()` | Hide palette, keep page state |
|
||||
| `CommandResult.GoBack()` | Navigate back one page |
|
||||
| `CommandResult.GoHome()` | Navigate to home page |
|
||||
| `CommandResult.ShowToast("msg")` | Show toast notification, then dismiss |
|
||||
| `CommandResult.Confirm(args)` | Show confirmation dialog before proceeding |
|
||||
|
||||
## ListItem Properties
|
||||
|
||||
```csharp
|
||||
new ListItem(command)
|
||||
{
|
||||
Title = "Display name",
|
||||
Subtitle = "Secondary text",
|
||||
Icon = new IconInfo("\uE8A7"),
|
||||
Tags = [new Tag("label") { Foreground = ColorHelpers.FromRgb(255, 0, 0) }],
|
||||
Details = new Details
|
||||
{
|
||||
Title = "Detail panel",
|
||||
Body = "**Markdown** body",
|
||||
HeroImage = IconHelpers.FromRelativePath("Assets\\hero.png"),
|
||||
Size = ContentSize.Medium,
|
||||
Metadata = [
|
||||
new DetailsLink("URL", "https://example.com"),
|
||||
new DetailsSeparator(),
|
||||
],
|
||||
},
|
||||
MoreCommands = [
|
||||
new CommandContextItem(deleteCommand)
|
||||
{
|
||||
RequestedShortcut = KeyChordHelpers.FromModifiers(
|
||||
true, false, false, (int)VirtualKey.Delete),
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Sections and Grid Layouts
|
||||
|
||||
### Sections
|
||||
|
||||
Group items under section headers:
|
||||
|
||||
```csharp
|
||||
public override ISection[] GetSections() => [
|
||||
new Section { Title = "Group A", Items = itemsA },
|
||||
new Section { Title = "Group B", Items = itemsB },
|
||||
];
|
||||
```
|
||||
|
||||
### Grid Layouts
|
||||
|
||||
Set `GridProperties` on a `ListPage`:
|
||||
|
||||
| Layout | Description |
|
||||
|--------|-------------|
|
||||
| `GalleryGridLayout()` | Large tiles with title + subtitle |
|
||||
| `SmallGridLayout()` | Compact grid |
|
||||
| `MediumGridLayout()` | Medium tiles with title |
|
||||
|
||||
## Icons
|
||||
|
||||
```csharp
|
||||
// Segoe Fluent UI icons (most common)
|
||||
new IconInfo("\uE8A5") // Document
|
||||
new IconInfo("\uE945") // Lightning bolt
|
||||
|
||||
// Emoji
|
||||
new IconInfo("📂")
|
||||
|
||||
// Image from package assets
|
||||
IconHelpers.FromRelativePath("Assets\\StoreLogo.png")
|
||||
|
||||
// Remote URL or SVG
|
||||
new IconInfo("https://example.com/icon.svg")
|
||||
|
||||
// From exe/dll resource
|
||||
new IconInfo("%systemroot%\\system32\\shell32.dll,3")
|
||||
```
|
||||
|
||||
## Dynamic Updates
|
||||
|
||||
- Call `RaiseItemsChanged()` on any page to trigger a UI refresh of its items
|
||||
- Call `RaisePropertyChanged(propertyName)` for individual property updates (e.g., title)
|
||||
- For top-level command changes, call `RaiseItemsChanged()` on the `CommandProvider`
|
||||
- Use `System.Timers.Timer` for periodic background updates
|
||||
|
||||
## Status Messages and Toasts
|
||||
|
||||
```csharp
|
||||
// Inline status message (e.g., loading indicator)
|
||||
var msg = new StatusMessage
|
||||
{
|
||||
Message = "Loading...",
|
||||
State = MessageState.Info,
|
||||
Progress = new ProgressState { IsIndeterminate = true },
|
||||
};
|
||||
ExtensionHost.ShowStatus(msg, StatusContext.Page);
|
||||
ExtensionHost.HideStatus(msg);
|
||||
|
||||
// Transient toast notification
|
||||
new ToastStatusMessage("Copied to clipboard").Show();
|
||||
```
|
||||
|
||||
## Build & Debug
|
||||
|
||||
1. Select **Debug** configuration
|
||||
2. **Deploy** via Build > Deploy (not just Build) — this registers the MSIX package
|
||||
3. Press **F5** to launch with debugger attached
|
||||
4. Use `Debug.Write()` / `Debug.WriteLine()` for diagnostic output
|
||||
5. Check Output window (**Ctrl+Alt+O**) set to "Debug"
|
||||
6. In Command Palette, run `Reload` → "Reload Command Palette extensions"
|
||||
|
||||
Use the `(Package)` launch profile, not `(Unpackaged)`.
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
| Mistake | Fix |
|
||||
|---------|-----|
|
||||
| Building without deploying | Use Build > Deploy so the MSIX package is updated |
|
||||
| Running "(Unpackaged)" profile | Select the "(Package)" launch profile |
|
||||
| Forgetting to reload extensions | Run `Reload` in Command Palette after deploying |
|
||||
| CLSID mismatch | Ensure `[Guid]` in .cs matches `ClassId` in Package.appxmanifest (both places) |
|
||||
| Logging in hot paths | `GetItems()` is called frequently — avoid expensive work or logging here |
|
||||
@@ -0,0 +1,145 @@
|
||||
---
|
||||
name: add-adaptive-card-form
|
||||
description: >-
|
||||
Create form-based UI for your Command Palette extension using Adaptive Cards.
|
||||
Use when asked to add forms, user input fields, toggle switches, text inputs,
|
||||
dropdown menus, data entry, surveys, configuration dialogs, or interactive
|
||||
content pages. Supports the Adaptive Cards Designer for visual form building.
|
||||
---
|
||||
|
||||
# Add Forms with Adaptive Cards
|
||||
|
||||
Create interactive forms in your Command Palette extension using Adaptive Cards. Forms allow you to collect user input through text fields, toggles, dropdowns, and other controls.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
- Adding a form to collect user input (name, settings, feedback)
|
||||
- Creating interactive configuration dialogs
|
||||
- Building data entry interfaces
|
||||
- Adding toggle switches or dropdown menus
|
||||
- Displaying complex layouts beyond simple lists
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Familiarity with [Adaptive Cards](https://adaptivecards.io/)
|
||||
- Optional: Use the [Adaptive Card Designer](https://adaptivecards.io/designer/) to visually build your form
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Step 1: Create a ContentPage with FormContent
|
||||
|
||||
Create a new file in your `Pages/` directory:
|
||||
|
||||
```csharp
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace YourExtension;
|
||||
|
||||
internal sealed partial class MyFormPage : ContentPage
|
||||
{
|
||||
private readonly MyForm _form = new();
|
||||
|
||||
public MyFormPage()
|
||||
{
|
||||
Name = "Open";
|
||||
Title = "My Form";
|
||||
Icon = new IconInfo("\uECA5");
|
||||
}
|
||||
|
||||
public override IContent[] GetContent() => [_form];
|
||||
}
|
||||
|
||||
internal sealed partial class MyForm : FormContent
|
||||
{
|
||||
public MyForm()
|
||||
{
|
||||
TemplateJson = """
|
||||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.6",
|
||||
"body": [
|
||||
{
|
||||
"type": "Input.Text",
|
||||
"label": "Name",
|
||||
"id": "Name",
|
||||
"isRequired": true,
|
||||
"errorMessage": "Name is required",
|
||||
"placeholder": "Enter your name"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.Submit",
|
||||
"title": "Submit"
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
public override CommandResult SubmitForm(string payload)
|
||||
{
|
||||
var formInput = JsonNode.Parse(payload)?.AsObject();
|
||||
if (formInput == null)
|
||||
{
|
||||
return CommandResult.GoHome();
|
||||
}
|
||||
|
||||
var name = formInput["Name"]?.ToString() ?? "Unknown";
|
||||
return CommandResult.ShowToast($"Hello, {name}!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Register the Page
|
||||
|
||||
In your `CommandsProvider`, add the form page:
|
||||
|
||||
```csharp
|
||||
_commands = [
|
||||
new CommandItem(new MyFormPage()) { Title = "My Form" },
|
||||
];
|
||||
```
|
||||
|
||||
### Step 3: Deploy and Test
|
||||
|
||||
1. Deploy your extension
|
||||
2. In Command Palette, run `Reload`
|
||||
3. Navigate to your form and submit it
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### TemplateJson
|
||||
The JSON layout of your form (from Adaptive Cards schema). Design it at https://adaptivecards.io/designer/
|
||||
|
||||
### DataJson (Optional)
|
||||
Dynamic data binding using `${...}` placeholders in your TemplateJson:
|
||||
```csharp
|
||||
TemplateJson = """{ "body": [{ "type": "TextBlock", "text": "${title}" }] }""";
|
||||
DataJson = """{ "title": "Dynamic Title" }""";
|
||||
```
|
||||
|
||||
### SubmitForm
|
||||
Called when the user submits. Parse `payload` as JSON to read input values by their `id`.
|
||||
|
||||
### Mixing Content Types
|
||||
You can combine forms with markdown on the same page:
|
||||
```csharp
|
||||
public override IContent[] GetContent() => [
|
||||
new MarkdownContent("# Instructions\nFill out the form below."),
|
||||
_form,
|
||||
];
|
||||
```
|
||||
|
||||
## Common Form Patterns
|
||||
|
||||
See [form-patterns.md](references/form-patterns.md) for template JSON for common form types.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Get user input with forms](https://learn.microsoft.com/windows/powertoys/command-palette/using-form-pages)
|
||||
- [Adaptive Card Designer](https://adaptivecards.io/designer/)
|
||||
- [Adaptive Cards Schema](https://adaptivecards.io/explorer/)
|
||||
@@ -0,0 +1,536 @@
|
||||
# Common Adaptive Card Form Patterns
|
||||
|
||||
Reusable template JSON and handler code for the most common form types in Command Palette extensions.
|
||||
|
||||
---
|
||||
|
||||
## Simple Text Input Form
|
||||
|
||||
A basic form with one or two text fields and a submit button.
|
||||
|
||||
### TemplateJson
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.6",
|
||||
"body": [
|
||||
{
|
||||
"type": "Input.Text",
|
||||
"id": "FirstName",
|
||||
"label": "First Name",
|
||||
"placeholder": "Enter your first name",
|
||||
"isRequired": true,
|
||||
"errorMessage": "First name is required"
|
||||
},
|
||||
{
|
||||
"type": "Input.Text",
|
||||
"id": "Email",
|
||||
"label": "Email Address",
|
||||
"placeholder": "user@example.com",
|
||||
"style": "Email",
|
||||
"isRequired": true,
|
||||
"errorMessage": "A valid email is required"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.Submit",
|
||||
"title": "Submit"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### SubmitForm Handler
|
||||
|
||||
```csharp
|
||||
public override CommandResult SubmitForm(string payload)
|
||||
{
|
||||
var input = JsonNode.Parse(payload)?.AsObject();
|
||||
if (input == null) return CommandResult.GoHome();
|
||||
|
||||
var firstName = input["FirstName"]?.ToString() ?? "";
|
||||
var email = input["Email"]?.ToString() ?? "";
|
||||
|
||||
return CommandResult.ShowToast($"Registered {firstName} ({email})");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Toggle/Checkbox Form
|
||||
|
||||
Use `Input.Toggle` for boolean on/off settings. Combine with `DataJson` for dynamic defaults.
|
||||
|
||||
### TemplateJson
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.6",
|
||||
"body": [
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "Preferences",
|
||||
"weight": "Bolder",
|
||||
"size": "Medium"
|
||||
},
|
||||
{
|
||||
"type": "Input.Toggle",
|
||||
"id": "AcceptsTerms",
|
||||
"title": "I accept the terms and conditions",
|
||||
"valueOn": "true",
|
||||
"valueOff": "false",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"type": "Input.Toggle",
|
||||
"id": "EnableNotifications",
|
||||
"title": "Enable notifications",
|
||||
"valueOn": "true",
|
||||
"valueOff": "false",
|
||||
"value": "${notificationsDefault}"
|
||||
},
|
||||
{
|
||||
"type": "Input.Toggle",
|
||||
"id": "DarkMode",
|
||||
"title": "Use dark mode",
|
||||
"valueOn": "true",
|
||||
"valueOff": "false",
|
||||
"value": "${darkModeDefault}"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.Submit",
|
||||
"title": "Save Preferences"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### DataJson (Dynamic Defaults)
|
||||
|
||||
```csharp
|
||||
DataJson = """
|
||||
{
|
||||
"notificationsDefault": "true",
|
||||
"darkModeDefault": "false"
|
||||
}
|
||||
""";
|
||||
```
|
||||
|
||||
### SubmitForm Handler
|
||||
|
||||
```csharp
|
||||
public override CommandResult SubmitForm(string payload)
|
||||
{
|
||||
var input = JsonNode.Parse(payload)?.AsObject();
|
||||
if (input == null) return CommandResult.GoHome();
|
||||
|
||||
var accepted = input["AcceptsTerms"]?.ToString() == "true";
|
||||
var notifications = input["EnableNotifications"]?.ToString() == "true";
|
||||
var darkMode = input["DarkMode"]?.ToString() == "true";
|
||||
|
||||
if (!accepted)
|
||||
{
|
||||
return CommandResult.ShowToast("You must accept the terms to continue.");
|
||||
}
|
||||
|
||||
// Save preferences...
|
||||
return CommandResult.ShowToast("Preferences saved!");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Choice Set (Dropdown/Radio) Form
|
||||
|
||||
Use `Input.ChoiceSet` for single-select dropdowns or radio buttons.
|
||||
|
||||
### Compact Style (Dropdown)
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.6",
|
||||
"body": [
|
||||
{
|
||||
"type": "Input.ChoiceSet",
|
||||
"id": "Priority",
|
||||
"label": "Priority Level",
|
||||
"style": "compact",
|
||||
"value": "medium",
|
||||
"choices": [
|
||||
{ "title": "Low", "value": "low" },
|
||||
{ "title": "Medium", "value": "medium" },
|
||||
{ "title": "High", "value": "high" },
|
||||
{ "title": "Critical", "value": "critical" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Input.ChoiceSet",
|
||||
"id": "Category",
|
||||
"label": "Category",
|
||||
"style": "compact",
|
||||
"choices": [
|
||||
{ "title": "Bug Report", "value": "bug" },
|
||||
{ "title": "Feature Request", "value": "feature" },
|
||||
{ "title": "Documentation", "value": "docs" },
|
||||
{ "title": "Question", "value": "question" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.Submit",
|
||||
"title": "Create Issue"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Expanded Style (Radio Buttons)
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.6",
|
||||
"body": [
|
||||
{
|
||||
"type": "Input.ChoiceSet",
|
||||
"id": "Theme",
|
||||
"label": "Select a theme",
|
||||
"style": "expanded",
|
||||
"value": "system",
|
||||
"choices": [
|
||||
{ "title": "Light", "value": "light" },
|
||||
{ "title": "Dark", "value": "dark" },
|
||||
{ "title": "System Default", "value": "system" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.Submit",
|
||||
"title": "Apply"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Multi-Section Form
|
||||
|
||||
Combine multiple input types with TextBlock headers to create organized, multi-section forms. Use `Action.ShowCard` for progressive disclosure of optional sections.
|
||||
|
||||
### TemplateJson
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.6",
|
||||
"body": [
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "Personal Information",
|
||||
"weight": "Bolder",
|
||||
"size": "Medium",
|
||||
"separator": true
|
||||
},
|
||||
{
|
||||
"type": "Input.Text",
|
||||
"id": "FullName",
|
||||
"label": "Full Name",
|
||||
"placeholder": "Enter your full name",
|
||||
"isRequired": true,
|
||||
"errorMessage": "Name is required"
|
||||
},
|
||||
{
|
||||
"type": "Input.Text",
|
||||
"id": "Email",
|
||||
"label": "Email",
|
||||
"placeholder": "user@example.com",
|
||||
"style": "Email"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "Preferences",
|
||||
"weight": "Bolder",
|
||||
"size": "Medium",
|
||||
"separator": true,
|
||||
"spacing": "Large"
|
||||
},
|
||||
{
|
||||
"type": "Input.ChoiceSet",
|
||||
"id": "Language",
|
||||
"label": "Preferred Language",
|
||||
"style": "compact",
|
||||
"value": "en",
|
||||
"choices": [
|
||||
{ "title": "English", "value": "en" },
|
||||
{ "title": "Spanish", "value": "es" },
|
||||
{ "title": "French", "value": "fr" },
|
||||
{ "title": "German", "value": "de" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Input.Toggle",
|
||||
"id": "Newsletter",
|
||||
"title": "Subscribe to newsletter",
|
||||
"valueOn": "true",
|
||||
"valueOff": "false",
|
||||
"value": "true"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.Submit",
|
||||
"title": "Save Profile"
|
||||
},
|
||||
{
|
||||
"type": "Action.ShowCard",
|
||||
"title": "Advanced Options",
|
||||
"card": {
|
||||
"type": "AdaptiveCard",
|
||||
"body": [
|
||||
{
|
||||
"type": "Input.Text",
|
||||
"id": "ApiKey",
|
||||
"label": "API Key (optional)",
|
||||
"placeholder": "Enter your API key"
|
||||
},
|
||||
{
|
||||
"type": "Input.Toggle",
|
||||
"id": "DebugMode",
|
||||
"title": "Enable debug mode",
|
||||
"valueOn": "true",
|
||||
"valueOff": "false",
|
||||
"value": "false"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.Submit",
|
||||
"title": "Save All"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Feedback Form
|
||||
|
||||
A common pattern for collecting user feedback with a multiline text area and a rating.
|
||||
|
||||
### TemplateJson
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.6",
|
||||
"body": [
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "We'd love your feedback!",
|
||||
"weight": "Bolder",
|
||||
"size": "Medium"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "Tell us what you think and how we can improve.",
|
||||
"wrap": true,
|
||||
"spacing": "Small"
|
||||
},
|
||||
{
|
||||
"type": "Input.ChoiceSet",
|
||||
"id": "Rating",
|
||||
"label": "How would you rate your experience?",
|
||||
"style": "expanded",
|
||||
"isRequired": true,
|
||||
"errorMessage": "Please select a rating",
|
||||
"choices": [
|
||||
{ "title": "⭐ Poor", "value": "1" },
|
||||
{ "title": "⭐⭐ Fair", "value": "2" },
|
||||
{ "title": "⭐⭐⭐ Good", "value": "3" },
|
||||
{ "title": "⭐⭐⭐⭐ Great", "value": "4" },
|
||||
{ "title": "⭐⭐⭐⭐⭐ Excellent", "value": "5" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Input.Text",
|
||||
"id": "Comments",
|
||||
"label": "Comments",
|
||||
"placeholder": "Share your thoughts...",
|
||||
"isMultiline": true,
|
||||
"maxLength": 500
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.Submit",
|
||||
"title": "Send Feedback"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### SubmitForm Handler with Confirmation Dialog
|
||||
|
||||
```csharp
|
||||
public override CommandResult SubmitForm(string payload)
|
||||
{
|
||||
var input = JsonNode.Parse(payload)?.AsObject();
|
||||
if (input == null) return CommandResult.GoHome();
|
||||
|
||||
var rating = input["Rating"]?.ToString() ?? "0";
|
||||
var comments = input["Comments"]?.ToString() ?? "";
|
||||
|
||||
return CommandResult.Confirm(new ConfirmationArgs
|
||||
{
|
||||
Title = "Submit feedback?",
|
||||
Description = $"Rating: {rating}/5\n\n{(string.IsNullOrEmpty(comments) ? "No comments" : comments)}",
|
||||
PrimaryCommand = new AnonymousCommand(() =>
|
||||
{
|
||||
// Process and store feedback
|
||||
new ToastStatusMessage("Thank you for your feedback!").Show();
|
||||
})
|
||||
{
|
||||
Name = "Submit",
|
||||
Result = CommandResult.Dismiss(),
|
||||
},
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tree Content with Forms (Comment/Reply Pattern)
|
||||
|
||||
Use `TreeContent` to create nested, threaded discussions where each node can contain a form for replies.
|
||||
|
||||
### Post Content (Tree Node)
|
||||
|
||||
```csharp
|
||||
internal sealed partial class PostContent : TreeContent
|
||||
{
|
||||
private readonly string _author;
|
||||
private readonly string _body;
|
||||
private readonly PostReplyForm _replyForm;
|
||||
private readonly List<PostContent> _childPosts = [];
|
||||
|
||||
public PostContent(string author, string body)
|
||||
{
|
||||
_author = author;
|
||||
_body = body;
|
||||
_replyForm = new PostReplyForm(this);
|
||||
|
||||
TemplateJson = """
|
||||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.6",
|
||||
"body": [
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "${author}",
|
||||
"weight": "Bolder"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "${body}",
|
||||
"wrap": true
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
DataJson = $$"""{ "author": "{{_author}}", "body": "{{_body}}" }""";
|
||||
}
|
||||
|
||||
public override IContent[] GetChildren() => [_replyForm, .. _childPosts];
|
||||
|
||||
public void AddReply(PostContent reply) => _childPosts.Add(reply);
|
||||
}
|
||||
```
|
||||
|
||||
### Reply Form (Child of Tree Node)
|
||||
|
||||
```csharp
|
||||
internal sealed partial class PostReplyForm : FormContent
|
||||
{
|
||||
private readonly PostContent _parent;
|
||||
|
||||
public PostReplyForm(PostContent parent)
|
||||
{
|
||||
_parent = parent;
|
||||
TemplateJson = """
|
||||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.6",
|
||||
"body": [
|
||||
{
|
||||
"type": "Input.Text",
|
||||
"id": "ReplyText",
|
||||
"placeholder": "Write a reply...",
|
||||
"isMultiline": true
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.Submit",
|
||||
"title": "Reply"
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
public override CommandResult SubmitForm(string payload)
|
||||
{
|
||||
var input = JsonNode.Parse(payload)?.AsObject();
|
||||
if (input == null) return CommandResult.GoHome();
|
||||
|
||||
var replyText = input["ReplyText"]?.ToString();
|
||||
if (!string.IsNullOrWhiteSpace(replyText))
|
||||
{
|
||||
_parent.AddReply(new PostContent("You", replyText));
|
||||
}
|
||||
|
||||
return CommandResult.KeepOpen();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Hosting the Thread on a ContentPage
|
||||
|
||||
```csharp
|
||||
internal sealed partial class ThreadPage : ContentPage
|
||||
{
|
||||
private readonly PostContent _rootPost;
|
||||
|
||||
public ThreadPage()
|
||||
{
|
||||
Name = "Discussion";
|
||||
Title = "Discussion Thread";
|
||||
Icon = new IconInfo("\uE90A");
|
||||
|
||||
_rootPost = new PostContent("Alice", "Has anyone tried the new API?");
|
||||
_rootPost.AddReply(new PostContent("Bob", "Yes! It works great."));
|
||||
}
|
||||
|
||||
public override IContent[] GetContent() => [_rootPost];
|
||||
}
|
||||
```
|
||||
149
src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/.github/skills/add-dock-band/SKILL.md
vendored
Normal file
149
src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/.github/skills/add-dock-band/SKILL.md
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
---
|
||||
name: add-dock-band
|
||||
description: >-
|
||||
Add dock band support to your Command Palette extension for persistent toolbar widgets.
|
||||
Use when asked to add dock support, toolbar buttons, persistent UI widgets,
|
||||
taskbar integration, live-updating status displays, quick-access buttons,
|
||||
or always-visible controls. Supports single buttons, multi-button strips,
|
||||
and live-updating content.
|
||||
---
|
||||
|
||||
# Add Dock Band Support
|
||||
|
||||
The Command Palette Dock is a persistent toolbar at the edge of the user's screen. Your extension can provide **dock bands** — strips of items that appear in the Dock — giving users quick access to commands without opening the full Command Palette.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
- Adding a quick-access button to the persistent toolbar
|
||||
- Creating a multi-button toolbar strip
|
||||
- Displaying live-updating information (clock, CPU usage, etc.)
|
||||
- Providing frequently-used commands without opening the full palette
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Command Palette Extension SDK version 0.9 or later (`Microsoft.CommandPalette.Extensions` ≥ 0.9.260303001)
|
||||
|
||||
## Quick Start: Single Button Dock Band
|
||||
|
||||
Override `GetDockBands()` in your `CommandProvider`:
|
||||
|
||||
```csharp
|
||||
public partial class MyCommandsProvider : CommandProvider
|
||||
{
|
||||
private readonly ICommandItem[] _commands;
|
||||
private readonly ICommandItem _dockBand;
|
||||
|
||||
public MyCommandsProvider()
|
||||
{
|
||||
DisplayName = "My Extension";
|
||||
Id = "com.mycompany.myextension"; // Unique ID required for dock
|
||||
|
||||
var mainPage = new MyPage();
|
||||
_dockBand = new CommandItem(mainPage) { Title = DisplayName };
|
||||
_commands = [new CommandItem(mainPage) { Title = DisplayName }];
|
||||
}
|
||||
|
||||
public override ICommandItem[] TopLevelCommands() => _commands;
|
||||
|
||||
public override ICommandItem[]? GetDockBands() => [_dockBand];
|
||||
}
|
||||
```
|
||||
|
||||
## Multi-Button Dock Band
|
||||
|
||||
Use `WrappedDockItem` to create a band with multiple buttons:
|
||||
|
||||
```csharp
|
||||
public override ICommandItem[]? GetDockBands()
|
||||
{
|
||||
var button1 = new ListItem(new OpenUrlCommand("https://github.com"))
|
||||
{
|
||||
Title = "GitHub",
|
||||
Icon = new IconInfo("\uE774"),
|
||||
};
|
||||
var button2 = new ListItem(new OpenUrlCommand("https://learn.microsoft.com"))
|
||||
{
|
||||
Title = "Learn",
|
||||
Icon = new IconInfo("\uE82D"),
|
||||
};
|
||||
|
||||
var band = new WrappedDockItem(
|
||||
[button1, button2],
|
||||
"com.mycompany.myextension.quicklinks", // Unique band ID
|
||||
"Quick Links");
|
||||
|
||||
return [band];
|
||||
}
|
||||
```
|
||||
|
||||
## Live-Updating Dock Band
|
||||
|
||||
Create a dock band that updates its content periodically (like a clock):
|
||||
|
||||
```csharp
|
||||
internal sealed partial class LiveStatusBand : ListItem
|
||||
{
|
||||
private readonly System.Timers.Timer _timer;
|
||||
|
||||
public LiveStatusBand()
|
||||
: base(new NoOpCommand() { Result = CommandResult.KeepOpen() })
|
||||
{
|
||||
Title = DateTime.Now.ToString("HH:mm");
|
||||
Icon = new IconInfo("\uE823"); // Clock icon
|
||||
|
||||
_timer = new System.Timers.Timer(60_000); // Update every minute
|
||||
_timer.Elapsed += (s, e) =>
|
||||
{
|
||||
Title = DateTime.Now.ToString("HH:mm");
|
||||
Subtitle = DateTime.Now.ToString("dddd, MMMM d");
|
||||
};
|
||||
_timer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
// In CommandProvider:
|
||||
public override ICommandItem[]? GetDockBands()
|
||||
{
|
||||
var band = new WrappedDockItem(
|
||||
[new LiveStatusBand()],
|
||||
"com.mycompany.myextension.status",
|
||||
"Live Status");
|
||||
return [band];
|
||||
}
|
||||
```
|
||||
|
||||
## How Dock Bands Render
|
||||
|
||||
| Command Type on ICommandItem | Dock Behavior |
|
||||
|------------------------------|---------------|
|
||||
| `IInvokableCommand` | Single button that executes the command |
|
||||
| `IListPage` | Each list item renders as a separate button in one band |
|
||||
| `IContentPage` | Single expandable button with a flyout |
|
||||
|
||||
## Support Pinning Nested Commands
|
||||
|
||||
By default, only top-level commands and dock bands can be pinned. To allow pinning nested commands:
|
||||
|
||||
```csharp
|
||||
public override ICommandItem? GetCommandItem(string id)
|
||||
{
|
||||
// Look up commands by their Id
|
||||
foreach (var item in GetAllCommands())
|
||||
{
|
||||
if (item?.Command is ICommand cmd && cmd.Id == id)
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
- All dock band `ICommandItem` objects must have a `Command` with a **non-empty `Id`** — items without an ID are ignored
|
||||
- Set `Id` on your `CommandProvider` (e.g., `Id = "com.mycompany.myextension"`)
|
||||
- Use `WrappedDockItem` for multi-button bands backed by a `ListPage`
|
||||
- Keep dock band updates lightweight — they run frequently
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Adding Dock support](https://learn.microsoft.com/windows/powertoys/command-palette/adding-dock-support)
|
||||
@@ -0,0 +1,202 @@
|
||||
---
|
||||
name: add-extension-settings
|
||||
description: >-
|
||||
Add a settings page to your Command Palette extension.
|
||||
Use when asked to add settings, preferences, configuration options,
|
||||
toggles, text inputs, dropdowns, or user-customizable behavior.
|
||||
Covers ToggleSetting, TextSetting, ChoiceSetSetting, and persistence.
|
||||
---
|
||||
|
||||
# Add Extension Settings
|
||||
|
||||
Add a settings page to your Command Palette extension using the built-in settings helpers. Settings are automatically persisted and restored by the extension host.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
- Adding user-configurable options to your extension
|
||||
- Creating toggle switches for features
|
||||
- Adding text input fields for configuration
|
||||
- Creating dropdown menus for option selection
|
||||
- Persisting user preferences across sessions
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Step 1: Create a Settings Manager
|
||||
|
||||
Create a new file `SettingsManager.cs`:
|
||||
|
||||
```csharp
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace YourExtension;
|
||||
|
||||
internal sealed class SettingsManager
|
||||
{
|
||||
private readonly Settings _settings;
|
||||
|
||||
public SettingsManager()
|
||||
{
|
||||
_settings = new Settings();
|
||||
|
||||
var maxResults = new TextSetting(
|
||||
"maxResults",
|
||||
"Maximum Results",
|
||||
"Maximum number of results to display",
|
||||
"10");
|
||||
|
||||
var showSubtitles = new ToggleSetting(
|
||||
"showSubtitles",
|
||||
"Show Subtitles",
|
||||
"Display subtitle text under each result",
|
||||
true);
|
||||
|
||||
var sortOrder = new ChoiceSetSetting(
|
||||
"sortOrder",
|
||||
"Sort Order",
|
||||
"How to sort results",
|
||||
[
|
||||
new ChoiceSetSetting.Choice("Alphabetical", "alpha"),
|
||||
new ChoiceSetSetting.Choice("Most Recent", "recent"),
|
||||
new ChoiceSetSetting.Choice("Most Used", "frequent"),
|
||||
],
|
||||
"alpha");
|
||||
|
||||
_settings.AddSetting(maxResults);
|
||||
_settings.AddSetting(showSubtitles);
|
||||
_settings.AddSetting(sortOrder);
|
||||
|
||||
// React to settings changes
|
||||
_settings.SettingsChanged += OnSettingsChanged;
|
||||
}
|
||||
|
||||
public ICommandSettings Settings => _settings;
|
||||
|
||||
public int MaxResults => int.TryParse(
|
||||
_settings.GetSetting<string>("maxResults"), out var val) ? val : 10;
|
||||
|
||||
public bool ShowSubtitles =>
|
||||
_settings.GetSetting<bool>("showSubtitles");
|
||||
|
||||
public string SortOrder =>
|
||||
_settings.GetSetting<string>("sortOrder") ?? "alpha";
|
||||
|
||||
private void OnSettingsChanged(object? sender, EventArgs e)
|
||||
{
|
||||
// React to settings changes (e.g., refresh data)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Wire into CommandProvider
|
||||
|
||||
In your `CommandsProvider`, expose the settings:
|
||||
|
||||
```csharp
|
||||
public partial class MyCommandsProvider : CommandProvider
|
||||
{
|
||||
private readonly SettingsManager _settingsManager = new();
|
||||
private readonly ICommandItem[] _commands;
|
||||
|
||||
public MyCommandsProvider()
|
||||
{
|
||||
DisplayName = "My Extension";
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.png");
|
||||
Settings = _settingsManager.Settings; // This exposes settings to CmdPal
|
||||
_commands = [
|
||||
new CommandItem(new MyPage(_settingsManager)) { Title = DisplayName },
|
||||
];
|
||||
}
|
||||
|
||||
public override ICommandItem[] TopLevelCommands() => _commands;
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Use Settings in Pages
|
||||
|
||||
```csharp
|
||||
internal sealed partial class MyPage : ListPage
|
||||
{
|
||||
private readonly SettingsManager _settings;
|
||||
|
||||
public MyPage(SettingsManager settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
{
|
||||
var items = GetAllItems();
|
||||
return items.Take(_settings.MaxResults).ToArray();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Setting Types
|
||||
|
||||
| Type | UI Control | Value Type | Constructor Parameters |
|
||||
|------|-----------|------------|----------------------|
|
||||
| `ToggleSetting` | Toggle switch | `bool` | `(id, label, description, defaultValue)` |
|
||||
| `TextSetting` | Text input | `string` | `(id, label, description, defaultValue)` |
|
||||
| `ChoiceSetSetting` | Dropdown | `string` | `(id, label, description, choices[], defaultValue)` |
|
||||
|
||||
## Key Points
|
||||
|
||||
- Settings are automatically persisted by the CmdPal host
|
||||
- Use `SettingsChanged` event to react to changes in real-time
|
||||
- Access values via `GetSetting<T>(id)` with the setting's string id
|
||||
- Pass the settings manager to pages/commands that need configuration
|
||||
- Settings page appears automatically when `Settings` is set on `CommandProvider`
|
||||
|
||||
## Grouping Settings
|
||||
|
||||
For extensions with many settings, organize them into logical groups:
|
||||
|
||||
```csharp
|
||||
public SettingsManager()
|
||||
{
|
||||
_settings = new Settings();
|
||||
|
||||
// Appearance group
|
||||
var theme = new ChoiceSetSetting("theme", "Theme", "UI theme",
|
||||
[
|
||||
new ChoiceSetSetting.Choice("Light", "light"),
|
||||
new ChoiceSetSetting.Choice("Dark", "dark"),
|
||||
new ChoiceSetSetting.Choice("System", "system"),
|
||||
],
|
||||
"system");
|
||||
|
||||
var fontSize = new TextSetting("fontSize", "Font Size", "Display font size", "14");
|
||||
|
||||
// Behavior group
|
||||
var autoRefresh = new ToggleSetting("autoRefresh", "Auto-Refresh",
|
||||
"Automatically refresh results", true);
|
||||
|
||||
var refreshInterval = new TextSetting("refreshInterval", "Refresh Interval",
|
||||
"Seconds between auto-refreshes", "30");
|
||||
|
||||
_settings.AddSetting(theme);
|
||||
_settings.AddSetting(fontSize);
|
||||
_settings.AddSetting(autoRefresh);
|
||||
_settings.AddSetting(refreshInterval);
|
||||
}
|
||||
```
|
||||
|
||||
## Reacting to Changes
|
||||
|
||||
Use the `SettingsChanged` event to update behavior when the user modifies settings:
|
||||
|
||||
```csharp
|
||||
private void OnSettingsChanged(object? sender, EventArgs e)
|
||||
{
|
||||
// Invalidate cached data
|
||||
_cachedItems = null;
|
||||
|
||||
// Notify pages to refresh
|
||||
OnItemsChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [SampleSettingsPage.cs](https://github.com/microsoft/PowerToys/blob/main/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleSettingsPage.cs)
|
||||
@@ -0,0 +1,164 @@
|
||||
---
|
||||
name: add-fallback-commands
|
||||
description: >-
|
||||
Add fallback commands to your Command Palette extension for catch-all search behavior.
|
||||
Use when asked to add search functionality, query matching, direct input handling,
|
||||
calculator-style evaluation, URL opening, command execution, or results that appear
|
||||
when no other extension matches. Used by 14 of 20 built-in extensions.
|
||||
---
|
||||
|
||||
# Add Fallback Commands
|
||||
|
||||
Fallback commands are shown in Command Palette when no other results match the user's query. They enable your extension to act as a catch-all handler — perfect for calculators, web search, command execution, file path opening, and more.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
- Adding search functionality that responds to any user input
|
||||
- Creating a calculator that evaluates expressions as the user types
|
||||
- Building a web search that triggers on unmatched queries
|
||||
- Opening files or URLs typed directly into the palette
|
||||
- Executing shell commands from the search bar
|
||||
|
||||
## How Fallback Commands Work
|
||||
|
||||
1. User types a query in Command Palette
|
||||
2. If no top-level commands match, CmdPal asks extensions for fallback results
|
||||
3. Your extension's `FallbackCommands()` provides items that respond to the query
|
||||
4. The fallback items can be static (always shown) or dynamic (filtered by query)
|
||||
|
||||
## Quick Start: Static Fallback
|
||||
|
||||
Override `FallbackCommands()` in your `CommandProvider`:
|
||||
|
||||
```csharp
|
||||
public partial class MyCommandsProvider : CommandProvider
|
||||
{
|
||||
private readonly ICommandItem[] _commands;
|
||||
private readonly FallbackCommandItem[] _fallbacks;
|
||||
|
||||
public MyCommandsProvider()
|
||||
{
|
||||
DisplayName = "Web Search";
|
||||
Icon = new IconInfo("\uE721"); // Search icon
|
||||
|
||||
var searchPage = new WebSearchPage();
|
||||
_commands = [new CommandItem(searchPage) { Title = DisplayName }];
|
||||
_fallbacks = [new FallbackCommandItem(searchPage) { Title = "Search the web" }];
|
||||
}
|
||||
|
||||
public override ICommandItem[] TopLevelCommands() => _commands;
|
||||
public override IFallbackCommandItem[] FallbackCommands() => _fallbacks;
|
||||
}
|
||||
```
|
||||
|
||||
## Dynamic Fallback with DynamicListPage
|
||||
|
||||
For fallbacks that filter results based on the query, use `DynamicListPage`:
|
||||
|
||||
```csharp
|
||||
internal sealed partial class WebSearchPage : DynamicListPage
|
||||
{
|
||||
private string _query = string.Empty;
|
||||
|
||||
public WebSearchPage()
|
||||
{
|
||||
Icon = new IconInfo("\uE721");
|
||||
Title = "Web Search";
|
||||
Name = "Search";
|
||||
PlaceholderText = "Type to search...";
|
||||
}
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch)
|
||||
{
|
||||
_query = newSearch;
|
||||
RaiseItemsChanged();
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_query))
|
||||
return [];
|
||||
|
||||
return [
|
||||
new ListItem(new OpenUrlCommand($"https://www.google.com/search?q={Uri.EscapeDataString(_query)}"))
|
||||
{
|
||||
Title = $"Search Google for \"{_query}\"",
|
||||
Icon = new IconInfo("\uE721"),
|
||||
},
|
||||
new ListItem(new OpenUrlCommand($"https://www.bing.com/search?q={Uri.EscapeDataString(_query)}"))
|
||||
{
|
||||
Title = $"Search Bing for \"{_query}\"",
|
||||
Icon = new IconInfo("\uE721"),
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Responsive Fallback with Cancellation
|
||||
|
||||
For expensive operations (API calls, file searches), use cancellation to stay responsive:
|
||||
|
||||
```csharp
|
||||
internal sealed partial class SmartSearchPage : DynamicListPage
|
||||
{
|
||||
private CancellationTokenSource? _cts;
|
||||
private IListItem[] _results = [];
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch)
|
||||
{
|
||||
// Cancel any in-flight search
|
||||
_cts?.Cancel();
|
||||
_cts = new CancellationTokenSource();
|
||||
var token = _cts.Token;
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
// Debounce: wait for user to stop typing
|
||||
await Task.Delay(300, token);
|
||||
if (token.IsCancellationRequested) return;
|
||||
|
||||
// Perform search
|
||||
_results = await SearchAsync(newSearch, token);
|
||||
RaiseItemsChanged();
|
||||
}, token);
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems() => _results;
|
||||
|
||||
private async Task<IListItem[]> SearchAsync(string query, CancellationToken token)
|
||||
{
|
||||
// Your search logic here
|
||||
// Check token.IsCancellationRequested periodically
|
||||
return [];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Real-World Examples (from built-in extensions)
|
||||
|
||||
| Extension | Fallback Behavior |
|
||||
|-----------|------------------|
|
||||
| **Apps** | Search installed applications by name |
|
||||
| **Calc** | Evaluate mathematical expressions directly |
|
||||
| **Shell** | Execute command-line commands |
|
||||
| **WebSearch** | Search the web with configured engine |
|
||||
| **Indexer** | Open files by path |
|
||||
| **TimeDate** | Parse time/date queries |
|
||||
| **WindowsSettings** | Jump to Windows Settings pages |
|
||||
| **WinGet** | Search WinGet packages |
|
||||
| **WindowWalker** | Find and switch to open windows |
|
||||
|
||||
## Key Points
|
||||
|
||||
- `FallbackCommands()` returns `IFallbackCommandItem[]` (not `ICommandItem[]`)
|
||||
- Use `FallbackCommandItem` wrapper (not `CommandItem`)
|
||||
- Wrap a `DynamicListPage` for query-reactive results
|
||||
- Cancel previous searches when new input arrives
|
||||
- Keep fallback responses fast — users expect instant results
|
||||
- Use `PlaceholderText` on your page to guide users
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Extension samples](https://learn.microsoft.com/windows/powertoys/command-palette/samples)
|
||||
- [Extensibility overview](https://learn.microsoft.com/windows/powertoys/command-palette/extensibility-overview)
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
name: publish-extension
|
||||
description: >-
|
||||
Publish your Command Palette extension to the Microsoft Store or WinGet.
|
||||
Use when asked to publish, distribute, release, deploy to store,
|
||||
create MSIX packages, submit to WinGet, set up CI/CD for releases,
|
||||
or automate builds with GitHub Actions.
|
||||
---
|
||||
|
||||
# Publish Your Command Palette Extension
|
||||
|
||||
Guide for distributing your Command Palette extension through the Microsoft Store, WinGet, or both.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
- Publishing your extension to the Microsoft Store
|
||||
- Submitting your extension to WinGet for `winget install` discovery
|
||||
- Setting up GitHub Actions to automate builds and releases
|
||||
- Creating MSIX packages for Store submission
|
||||
- Creating EXE installers for WinGet submission
|
||||
|
||||
## Publishing Options
|
||||
|
||||
| Channel | Package Format | Discovery | Auto-Updates |
|
||||
|---------|---------------|-----------|--------------|
|
||||
| Microsoft Store | MSIX bundle | Store app, `ms-windows-store://` link | Yes |
|
||||
| WinGet | EXE installer | `winget install`, CmdPal browse | Yes (via manifest) |
|
||||
|
||||
**Recommendation**: Publish to both for maximum reach. WinGet enables direct discovery from within Command Palette.
|
||||
|
||||
## Workflows
|
||||
|
||||
### Microsoft Store Publishing
|
||||
See [store-publishing.md](references/store-publishing.md) for the complete step-by-step guide.
|
||||
|
||||
**Summary:**
|
||||
1. Register for Partner Center
|
||||
2. Update `Package.appxmanifest` and `.csproj` with Partner Center identity
|
||||
3. Build MSIX for x64 and ARM64
|
||||
4. Create MSIX bundle
|
||||
5. Submit to Partner Center
|
||||
|
||||
### WinGet Publishing
|
||||
See [winget-publishing.md](references/winget-publishing.md) for the complete step-by-step guide.
|
||||
|
||||
**Summary:**
|
||||
1. Switch project to unpackaged mode
|
||||
2. Create Inno Setup installer script
|
||||
3. Build EXE installers
|
||||
4. Submit manifest via `wingetcreate new`
|
||||
5. Optionally automate with GitHub Actions
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Visual Studio](https://visualstudio.microsoft.com/) with C# and WinUI workloads
|
||||
- [Partner Center account](https://partner.microsoft.com/dashboard/home) (for Store publishing)
|
||||
- [GitHub CLI](https://cli.github.com/) (for WinGet publishing)
|
||||
- [WingetCreate](https://github.com/microsoft/winget-create) — `winget install Microsoft.WingetCreate`
|
||||
- [Inno Setup](https://jrsoftware.org/isdl.php) (for WinGet EXE packaging)
|
||||
|
||||
## Important Notes
|
||||
|
||||
- Your extension's CLSID (the `[Guid("...")]` in your main .cs file) must be unique and consistent across all files
|
||||
- WinGet manifests must include the `windows-commandpalette-extension` tag for CmdPal discovery
|
||||
- MSIX packages require both x64 and ARM64 builds for Store submission
|
||||
- WindowsAppSdk must be listed as a dependency in WinGet manifests
|
||||
@@ -0,0 +1,169 @@
|
||||
# Microsoft Store Publishing Guide
|
||||
|
||||
Complete step-by-step guide for publishing your Command Palette extension to the Microsoft Store.
|
||||
|
||||
## Step 1: Set Up Microsoft Store
|
||||
|
||||
1. Go to [Partner Center](https://partner.microsoft.com/dashboard/home)
|
||||
2. Navigate to **Apps and Games** → **New product** → **MSIX or PWA app**
|
||||
3. Reserve your app name (e.g., `My Extension for Command Palette`)
|
||||
4. Once created, go to **Product Management** → **Product Identity**
|
||||
5. Copy these three values — you'll need them in the next step:
|
||||
|
||||
| Partner Center Field | Where It Goes |
|
||||
|---------------------|---------------|
|
||||
| **Package/Identity/Name** | `Package.appxmanifest` → `Identity Name` and `.csproj` → `AppxPackageIdentityName` |
|
||||
| **Package/Identity/Publisher** | `Package.appxmanifest` → `Identity Publisher` and `.csproj` → `AppxPackagePublisher` |
|
||||
| **Package/Properties/PublisherDisplayName** | `Package.appxmanifest` → `Properties PublisherDisplayName` |
|
||||
|
||||
## Step 2: Prepare the Extension
|
||||
|
||||
### Update `Package.appxmanifest`
|
||||
|
||||
Replace the placeholder identity values with your Partner Center values:
|
||||
|
||||
```xml
|
||||
<Identity
|
||||
Name="YOUR_PACKAGE_IDENTITY_NAME_HERE"
|
||||
Publisher="YOUR_PACKAGE_IDENTITY_PUBLISHER_HERE"
|
||||
Version="0.0.1.0" />
|
||||
```
|
||||
|
||||
And update the publisher display name:
|
||||
|
||||
```xml
|
||||
<Properties>
|
||||
<DisplayName>Your Extension Name</DisplayName>
|
||||
<PublisherDisplayName>YOUR_PUBLISHER_DISPLAY_NAME_HERE</PublisherDisplayName>
|
||||
<!-- ... -->
|
||||
</Properties>
|
||||
```
|
||||
|
||||
### Update `.csproj`
|
||||
|
||||
Add or update the following properties in your `.csproj` file:
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<AppxPackageIdentityName>YOUR_PACKAGE_IDENTITY_NAME_HERE</AppxPackageIdentityName>
|
||||
<AppxPackagePublisher>YOUR_PACKAGE_IDENTITY_PUBLISHER_HERE</AppxPackagePublisher>
|
||||
<AppxPackageVersion>0.0.1.0</AppxPackageVersion>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
### Update Image Assets ItemGroup
|
||||
|
||||
Ensure all image assets are included in the package by updating the `ItemGroup`:
|
||||
|
||||
```xml
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\**\*.png" />
|
||||
</ItemGroup>
|
||||
```
|
||||
|
||||
> **Tip:** The `Assets` folder should contain your Store logos and extension icons at the required sizes (44x44, 150x150, etc.). You can generate these from a single high-resolution image.
|
||||
|
||||
## Step 3: Build MSIX Packages
|
||||
|
||||
Build for both x64 and ARM64 architectures:
|
||||
|
||||
```powershell
|
||||
# x64 build
|
||||
dotnet build --configuration Release -p:GenerateAppxPackageOnBuild=true -p:Platform=x64 -p:AppxPackageDir="AppPackages\x64\"
|
||||
|
||||
# ARM64 build
|
||||
dotnet build --configuration Release -p:GenerateAppxPackageOnBuild=true -p:Platform=ARM64 -p:AppxPackageDir="AppPackages\ARM64\"
|
||||
```
|
||||
|
||||
Verify the MSIX files were created:
|
||||
|
||||
```powershell
|
||||
dir AppPackages -Recurse -Filter "*.msix"
|
||||
```
|
||||
|
||||
You should see two `.msix` files, one for each architecture.
|
||||
|
||||
## Step 4: Create MSIX Bundle
|
||||
|
||||
### Create the bundle mapping file
|
||||
|
||||
Create a file named `bundle_mapping.txt` that maps each MSIX to its architecture:
|
||||
|
||||
```text
|
||||
[Files]
|
||||
"AppPackages\x64\YourExtension_0.0.1.0_x64\YourExtension_0.0.1.0_x64.msix" "YourExtension_0.0.1.0_x64.msix"
|
||||
"AppPackages\ARM64\YourExtension_0.0.1.0_ARM64\YourExtension_0.0.1.0_ARM64.msix" "YourExtension_0.0.1.0_ARM64.msix"
|
||||
```
|
||||
|
||||
> **Note:** Update the paths and filenames to match your actual build output. Check the `AppPackages` directory structure after building.
|
||||
|
||||
### Run makeappx
|
||||
|
||||
```powershell
|
||||
makeappx bundle /f bundle_mapping.txt /p YourExtension_0.0.1.0_Bundle.msixbundle
|
||||
```
|
||||
|
||||
> **Tip:** `makeappx.exe` is included with the Windows SDK. If it's not in your PATH, find it at:
|
||||
> `C:\Program Files (x86)\Windows Kits\10\bin\<version>\x64\makeappx.exe`
|
||||
|
||||
## Step 5: Submit to Partner Center
|
||||
|
||||
1. Go to [Partner Center](https://partner.microsoft.com/dashboard/home)
|
||||
2. Navigate to your app → **Start a new submission**
|
||||
3. In **Packages**, upload your `.msixbundle` file
|
||||
4. In **Store Listings** → **Description**, include a note like:
|
||||
|
||||
> `YourExtension` integrates with the Windows Command Palette to provide [describe your extension's functionality]. Requires PowerToys with Command Palette enabled.
|
||||
|
||||
5. In **Notes for certification**, add testing instructions:
|
||||
|
||||
> This extension requires Microsoft PowerToys (available from the Microsoft Store or https://github.com/microsoft/PowerToys) with the Command Palette feature enabled. To test:
|
||||
> 1. Install PowerToys and enable Command Palette
|
||||
> 2. Install this extension
|
||||
> 3. Open Command Palette (Win+Alt+Space by default)
|
||||
> 4. Search for [your extension's commands]
|
||||
|
||||
6. Set **Availability** and pricing as appropriate
|
||||
7. Click **Submit for certification**
|
||||
|
||||
Certification typically takes 1–3 business days.
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
Before submitting, verify:
|
||||
|
||||
- [ ] Partner Center identity values match exactly in both `Package.appxmanifest` and `.csproj`
|
||||
- [ ] `AppxPackageVersion` is set correctly and incremented from any previous submission
|
||||
- [ ] Both x64 and ARM64 MSIX files are built successfully
|
||||
- [ ] MSIX bundle is created without errors
|
||||
- [ ] Extension installs and runs correctly from the MSIX package locally
|
||||
- [ ] Store listing includes clear description mentioning Command Palette integration
|
||||
- [ ] Testing instructions mention the PowerToys/Command Palette prerequisite
|
||||
- [ ] All required Store logos and screenshots are provided
|
||||
- [ ] Privacy policy URL is set (if your extension accesses network or user data)
|
||||
|
||||
## Store-Only Discovery Limitations
|
||||
|
||||
> **Important:** Command Palette cannot currently search for extensions published only to the Microsoft Store via its built-in browse experience. Users can find Store-published extensions through:
|
||||
>
|
||||
> - Direct Store link shared by the developer
|
||||
> - The Store's extension tag URL:
|
||||
> ```
|
||||
> ms-windows-store://assoc/?Tags=AppExtension-com.microsoft.commandpalette
|
||||
> ```
|
||||
> - Searching the Store app directly
|
||||
>
|
||||
> For discoverability within Command Palette's browse experience, also publish to WinGet.
|
||||
> See [winget-publishing.md](winget-publishing.md) for details.
|
||||
|
||||
## Updating Your Extension
|
||||
|
||||
To publish an update:
|
||||
|
||||
1. Increment the version in `.csproj` (`AppxPackageVersion`) and `Package.appxmanifest`
|
||||
2. Rebuild MSIX packages for both architectures
|
||||
3. Recreate the MSIX bundle with updated filenames
|
||||
4. Create a new submission in Partner Center and upload the new bundle
|
||||
5. Submit for certification
|
||||
|
||||
The Store will automatically update users who have installed your extension.
|
||||
@@ -0,0 +1,413 @@
|
||||
# WinGet Publishing Guide
|
||||
|
||||
Complete step-by-step guide for publishing your Command Palette extension to WinGet for `winget install` discovery and installation.
|
||||
|
||||
## Why WinGet?
|
||||
|
||||
Publishing to WinGet enables:
|
||||
|
||||
- Users to install via `winget install YourPublisher.YourExtension`
|
||||
- Discovery directly inside Command Palette's built-in browse experience
|
||||
- Automatic update detection via WinGet manifests
|
||||
|
||||
## Step 1: Prepare the Project for Unpackaged Distribution
|
||||
|
||||
WinGet distribution uses an unpackaged (EXE-based) build instead of MSIX.
|
||||
|
||||
### Update `.csproj`
|
||||
|
||||
Remove any existing `<PublishProfile>` property and add unpackaged mode:
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<!-- Remove or comment out this line if present: -->
|
||||
<!-- <PublishProfile>win-$(Platform)</PublishProfile> -->
|
||||
|
||||
<!-- Add this for unpackaged distribution: -->
|
||||
<WindowsPackageType>None</WindowsPackageType>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
### Note Your CLSID
|
||||
|
||||
Find the `[Guid("...")]` attribute in your main `.cs` file (e.g., `SampleExtension.cs`):
|
||||
|
||||
```csharp
|
||||
[Guid("YOUR-GUID-HERE")]
|
||||
public sealed partial class SampleExtension : IExtension
|
||||
```
|
||||
|
||||
You'll need this exact GUID for the installer script. It must match across all files.
|
||||
|
||||
## Step 2: Create Installer Scripts
|
||||
|
||||
### Inno Setup Script: `setup-template.iss`
|
||||
|
||||
Create this file in your project root. Replace all `TODO` placeholders with your values:
|
||||
|
||||
```iss
|
||||
; Inno Setup script for Command Palette extension
|
||||
|
||||
#define MyAppName "TODO_YOUR_EXTENSION_NAME"
|
||||
#define MyAppVersion "TODO_YOUR_VERSION"
|
||||
#define MyAppPublisher "TODO_YOUR_PUBLISHER_NAME"
|
||||
#define MyAppURL "TODO_YOUR_PROJECT_URL"
|
||||
#define MyAppCLSID "TODO_YOUR_CLSID_WITH_BRACES"
|
||||
; Example CLSID: {12345678-1234-1234-1234-123456789012}
|
||||
|
||||
[Setup]
|
||||
AppId={#MyAppCLSID}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
DefaultDirName={autopf}\{#MyAppName}
|
||||
OutputBaseFilename={#MyAppName}_{#MyAppVersion}_{#SetupSetting("ArchitecturesAllowed")}
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
PrivilegesRequired=lowest
|
||||
OutputDir=Installer
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Files]
|
||||
Source: "publish\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
|
||||
[Registry]
|
||||
; Register the COM server for Command Palette discovery
|
||||
Root: HKCU; Subkey: "Software\Classes\CLSID\{#MyAppCLSID}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppName}"; Flags: uninsdeletekey
|
||||
Root: HKCU; Subkey: "Software\Classes\CLSID\{#MyAppCLSID}\InprocServer32"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppName}.dll"; Flags: uninsdeletekey
|
||||
Root: HKCU; Subkey: "Software\Classes\CLSID\{#MyAppCLSID}\InprocServer32"; ValueType: string; ValueName: "ThreadingModel"; ValueData: "Both"; Flags: uninsdeletekey
|
||||
|
||||
[UninstallDelete]
|
||||
Type: filesandordirs; Name: "{app}"
|
||||
```
|
||||
|
||||
> **Important:** The `AppId` must use your CLSID wrapped in braces. The registry entries register your extension's COM server so Command Palette can discover it.
|
||||
|
||||
### Build Script: `build-exe.ps1`
|
||||
|
||||
Create this PowerShell script in your project root:
|
||||
|
||||
```powershell
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Builds EXE installers for x64 and ARM64 using dotnet publish and Inno Setup.
|
||||
.DESCRIPTION
|
||||
Publishes the project for both architectures, then runs Inno Setup to create
|
||||
EXE installers suitable for WinGet submission.
|
||||
#>
|
||||
|
||||
param(
|
||||
[string]$Configuration = "Release",
|
||||
[string]$Version = "0.0.1"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$projectName = (Get-ChildItem -Filter "*.csproj" | Select-Object -First 1).BaseName
|
||||
if (-not $projectName) {
|
||||
Write-Error "No .csproj file found in the current directory."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$architectures = @("x64", "arm64")
|
||||
|
||||
foreach ($arch in $architectures) {
|
||||
Write-Host "`n=== Building $arch ===" -ForegroundColor Cyan
|
||||
|
||||
# Publish
|
||||
Write-Host "Publishing for $arch..."
|
||||
dotnet publish -c $Configuration -r "win-$arch" -o "publish" --self-contained=false
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "dotnet publish failed for $arch"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Create installer
|
||||
Write-Host "Creating installer for $arch..."
|
||||
$issFile = "setup-template.iss"
|
||||
if (-not (Test-Path $issFile)) {
|
||||
Write-Error "Inno Setup script not found: $issFile"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$archFlag = if ($arch -eq "arm64") { "arm64" } else { "x64" }
|
||||
& "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" `
|
||||
/DMyAppVersion="$Version" `
|
||||
/DArchitecturesAllowed="$archFlag" `
|
||||
$issFile
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "Inno Setup failed for $arch"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Clean publish directory for next architecture
|
||||
Remove-Item -Recurse -Force "publish" -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Host "=== $arch complete ===" -ForegroundColor Green
|
||||
}
|
||||
|
||||
Write-Host "`nInstallers created in the 'Installer' directory:" -ForegroundColor Cyan
|
||||
Get-ChildItem -Path "Installer" -Filter "*.exe" | ForEach-Object { Write-Host " $_" }
|
||||
```
|
||||
|
||||
## Step 3: Build EXE Installers
|
||||
|
||||
Run the build script from your project directory:
|
||||
|
||||
```powershell
|
||||
.\build-exe.ps1
|
||||
```
|
||||
|
||||
This produces two EXE files in the `Installer` directory:
|
||||
|
||||
```
|
||||
Installer\YourExtension_0.0.1_x64.exe
|
||||
Installer\YourExtension_0.0.1_arm64.exe
|
||||
```
|
||||
|
||||
Verify both installers work by running them locally and confirming your extension appears in Command Palette.
|
||||
|
||||
## Step 4: Create a GitHub Release
|
||||
|
||||
Tag your repository with the version and create a release with the EXE files:
|
||||
|
||||
```powershell
|
||||
# Tag the release
|
||||
git tag -a v0.0.1 -m "Release v0.0.1"
|
||||
git push origin v0.0.1
|
||||
|
||||
# Create release and upload assets (requires GitHub CLI)
|
||||
gh release create v0.0.1 `
|
||||
"Installer\YourExtension_0.0.1_x64.exe" `
|
||||
"Installer\YourExtension_0.0.1_arm64.exe" `
|
||||
--title "v0.0.1" `
|
||||
--notes "Initial release of YourExtension for Command Palette."
|
||||
```
|
||||
|
||||
After creating the release, copy the download URLs for both EXE files — you'll need them for the WinGet submission.
|
||||
|
||||
## Step 5: Submit to WinGet
|
||||
|
||||
Use `wingetcreate` to generate a WinGet manifest and submit a pull request:
|
||||
|
||||
```powershell
|
||||
wingetcreate new "<URL_TO_x64.exe>" "<URL_TO_arm64.exe>"
|
||||
```
|
||||
|
||||
`wingetcreate` will interactively prompt you for:
|
||||
|
||||
| Prompt | Example Value |
|
||||
|--------|---------------|
|
||||
| **PackageIdentifier** | `YourPublisher.YourExtension` |
|
||||
| **PackageVersion** | `0.0.1` |
|
||||
| **PackageLocale** | `en-US` |
|
||||
| **Publisher** | `Your Name` |
|
||||
| **PackageName** | `YourExtension for Command Palette` |
|
||||
| **License** | `MIT` |
|
||||
| **ShortDescription** | `A Command Palette extension that does X` |
|
||||
|
||||
After answering all prompts, `wingetcreate` will create a PR against the [winget-pkgs](https://github.com/microsoft/winget-pkgs) repository.
|
||||
|
||||
## Step 6: Add the Command Palette Tag (CRITICAL)
|
||||
|
||||
> **This step is required for your extension to appear in Command Palette's browse experience.**
|
||||
|
||||
After `wingetcreate` generates the manifest files, you **must** edit each `.locale.*.yaml` file to add the Command Palette tag.
|
||||
|
||||
In every locale YAML file (e.g., `YourPublisher.YourExtension.locale.en-US.yaml`), add:
|
||||
|
||||
```yaml
|
||||
Tags:
|
||||
- windows-commandpalette-extension
|
||||
```
|
||||
|
||||
Example of a complete locale file with the tag:
|
||||
|
||||
```yaml
|
||||
# yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.6.0.schema.json
|
||||
PackageIdentifier: YourPublisher.YourExtension
|
||||
PackageVersion: 0.0.1
|
||||
PackageLocale: en-US
|
||||
Publisher: Your Name
|
||||
PackageName: YourExtension for Command Palette
|
||||
License: MIT
|
||||
ShortDescription: A Command Palette extension that does X
|
||||
Tags:
|
||||
- windows-commandpalette-extension
|
||||
ManifestType: defaultLocale
|
||||
ManifestVersion: 1.6.0
|
||||
```
|
||||
|
||||
Without this tag, Command Palette will not discover your extension in its browse experience.
|
||||
|
||||
## Step 7: Ensure WindowsAppSdk Dependency
|
||||
|
||||
Your WinGet manifest must declare a dependency on the Windows App SDK so it gets installed automatically. In the `installer.yaml` manifest file, add:
|
||||
|
||||
```yaml
|
||||
Dependencies:
|
||||
PackageDependencies:
|
||||
- PackageIdentifier: Microsoft.WindowsAppRuntime.1.7
|
||||
MinimumVersion: 7001.632.252.0
|
||||
```
|
||||
|
||||
> **Note:** Update the version number to match the Windows App SDK version your project targets. Check your `.csproj` for the `WindowsAppSDK` package version.
|
||||
|
||||
## Step 8: GitHub Actions Automation (Optional)
|
||||
|
||||
Automate your build, release, and WinGet submission process with GitHub Actions.
|
||||
|
||||
### Release Workflow: `.github/workflows/release-extension.yml`
|
||||
|
||||
```yaml
|
||||
name: Release Extension
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
PROJECT_NAME: YourExtension
|
||||
DOTNET_VERSION: '9.0.x'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x64, arm64]
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
|
||||
- name: Install Inno Setup
|
||||
run: choco install innosetup -y --no-progress
|
||||
|
||||
- name: Detect version
|
||||
id: version
|
||||
run: |
|
||||
$tag = "${{ github.ref_name }}" -replace '^v', ''
|
||||
echo "VERSION=$tag" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- name: Publish
|
||||
run: |
|
||||
dotnet publish -c Release -r win-${{ matrix.arch }} -o publish --self-contained=false
|
||||
|
||||
- name: Create installer
|
||||
run: |
|
||||
& "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" `
|
||||
/DMyAppVersion="${{ steps.version.outputs.VERSION }}" `
|
||||
/DArchitecturesAllowed="${{ matrix.arch }}" `
|
||||
setup-template.iss
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: installer-${{ matrix.arch }}
|
||||
path: Installer/*.exe
|
||||
|
||||
release:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
merge-multiple: true
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: artifacts/*.exe
|
||||
generate_release_notes: true
|
||||
|
||||
winget-update:
|
||||
needs: release
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Detect version
|
||||
id: version
|
||||
run: |
|
||||
$tag = "${{ github.ref_name }}" -replace '^v', ''
|
||||
echo "VERSION=$tag" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- name: Update WinGet manifest
|
||||
run: |
|
||||
$baseUrl = "https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}"
|
||||
wingetcreate update YourPublisher.YourExtension `
|
||||
--version ${{ steps.version.outputs.VERSION }} `
|
||||
--urls "$baseUrl/${{ env.PROJECT_NAME }}_${{ steps.version.outputs.VERSION }}_x64.exe" "$baseUrl/${{ env.PROJECT_NAME }}_${{ steps.version.outputs.VERSION }}_arm64.exe" `
|
||||
--submit `
|
||||
--token ${{ secrets.WINGET_PAT }}
|
||||
```
|
||||
|
||||
### Required Secrets
|
||||
|
||||
| Secret | Description |
|
||||
|--------|-------------|
|
||||
| `WINGET_PAT` | GitHub Personal Access Token with `public_repo` scope, used by `wingetcreate` to submit PRs to `microsoft/winget-pkgs` |
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Push a version tag** (e.g., `git tag v0.0.2 && git push origin v0.0.2`)
|
||||
2. **Build job** runs in parallel for x64 and ARM64, creating EXE installers
|
||||
3. **Release job** creates a GitHub Release and uploads the EXE files
|
||||
4. **WinGet update job** automatically submits an updated manifest to `winget-pkgs`
|
||||
|
||||
> **Note:** The `winget-update` job uses `wingetcreate update` (not `new`) because it assumes you've already submitted your initial manifest manually. For the first submission, follow Steps 5–7 above.
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
Before submitting to WinGet, verify:
|
||||
|
||||
- [ ] `.csproj` has `<WindowsPackageType>None</WindowsPackageType>` set
|
||||
- [ ] CLSID in `setup-template.iss` matches the `[Guid("...")]` in your main `.cs` file
|
||||
- [ ] Both x64 and ARM64 EXE installers build successfully
|
||||
- [ ] Installer registers the COM server correctly (check `HKCU\Software\Classes\CLSID\{your-clsid}`)
|
||||
- [ ] Extension appears in Command Palette after installing via EXE
|
||||
- [ ] Extension is removed from Command Palette after uninstalling
|
||||
- [ ] GitHub Release contains both EXE files with correct download URLs
|
||||
- [ ] WinGet manifest includes `windows-commandpalette-extension` tag
|
||||
- [ ] WinGet manifest includes `WindowsAppRuntime` dependency
|
||||
- [ ] `winget validate` passes on all manifest files
|
||||
|
||||
## Updating Your Extension on WinGet
|
||||
|
||||
For subsequent releases:
|
||||
|
||||
```powershell
|
||||
wingetcreate update YourPublisher.YourExtension `
|
||||
--version "0.0.2" `
|
||||
--urls "<URL_TO_NEW_x64.exe>" "<URL_TO_NEW_arm64.exe>" `
|
||||
--submit
|
||||
```
|
||||
|
||||
Or simply push a new version tag if you've set up the GitHub Actions workflow above.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Extension not appearing in CmdPal browse | Verify the `windows-commandpalette-extension` tag is in your locale YAML |
|
||||
| COM registration fails | Check that the CLSID matches exactly and registry paths are correct |
|
||||
| `wingetcreate` validation errors | Run `winget validate --manifest <path>` and fix reported issues |
|
||||
| Installer doesn't run silently | Add `/VERYSILENT /SUPPRESSMSGBOXES` flags for silent install support |
|
||||
| Missing WindowsAppSdk at runtime | Ensure the `PackageDependencies` section is in your installer manifest |
|
||||
@@ -12,7 +12,7 @@ public struct InterlockedBoolean(bool initialValue = false)
|
||||
private int _value = initialValue ? 1 : 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the boolean value atomically
|
||||
/// Gets or sets a value indicating whether the atomic boolean is true.
|
||||
/// </summary>
|
||||
public bool Value
|
||||
{
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 Microsoft.Extensions.Logging;
|
||||
using MEL = Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Common.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="ILogger"/> implementation that delegates to <see cref="ManagedCommon.Logger"/>.
|
||||
/// Instances are created by <see cref="CmdPalLoggerProvider"/>.
|
||||
/// </summary>
|
||||
public sealed class CmdPalLogger(string categoryName) : MEL.ILogger
|
||||
{
|
||||
public IDisposable? BeginScope<TState>(TState state)
|
||||
where TState : notnull => null;
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;
|
||||
|
||||
public void Log<TState>(
|
||||
LogLevel logLevel,
|
||||
EventId eventId,
|
||||
TState state,
|
||||
Exception? exception,
|
||||
Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
if (!IsEnabled(logLevel))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ArgumentNullException.ThrowIfNull(formatter);
|
||||
|
||||
var message = $"[{categoryName}] {formatter(state, exception)}";
|
||||
|
||||
switch (logLevel)
|
||||
{
|
||||
case LogLevel.Trace:
|
||||
ManagedCommon.Logger.LogTrace(message);
|
||||
break;
|
||||
case LogLevel.Debug:
|
||||
ManagedCommon.Logger.LogDebug(message);
|
||||
break;
|
||||
case LogLevel.Information:
|
||||
ManagedCommon.Logger.LogInfo(message);
|
||||
break;
|
||||
case LogLevel.Warning:
|
||||
ManagedCommon.Logger.LogWarning(message);
|
||||
break;
|
||||
case LogLevel.Error:
|
||||
case LogLevel.Critical:
|
||||
if (exception is not null)
|
||||
{
|
||||
ManagedCommon.Logger.LogError(message, exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
ManagedCommon.Logger.LogError(message);
|
||||
}
|
||||
|
||||
break;
|
||||
case LogLevel.None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// 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.Collections.Concurrent;
|
||||
|
||||
using MEL = Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Common.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="MEL.ILoggerProvider"/> that creates <see cref="CmdPalLogger"/> instances
|
||||
/// backed by the <see cref="ManagedCommon.Logger"/> infrastructure.
|
||||
/// Register via <see cref="CmdPalLoggingExtensions.AddCmdPalLogging"/>.
|
||||
/// </summary>
|
||||
public sealed partial class CmdPalLoggerProvider : MEL.ILoggerProvider
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, CmdPalLogger> _loggers = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public MEL.ILogger CreateLogger(string categoryName) =>
|
||||
_loggers.GetOrAdd(categoryName, name => new CmdPalLogger(name));
|
||||
|
||||
public void Dispose() => _loggers.Clear();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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 Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using MEL = Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Common.Logging;
|
||||
|
||||
public static class CmdPalLoggingExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers the Microsoft.Extensions.Logging infrastructure and adds a
|
||||
/// <see cref="CmdPalLoggerProvider"/> that routes all <see cref="MEL.ILogger"/>
|
||||
/// output to <see cref="ManagedCommon.Logger"/>.
|
||||
/// </summary>
|
||||
public static IServiceCollection AddCmdPalLogging(this IServiceCollection services)
|
||||
{
|
||||
services.AddLogging(builder =>
|
||||
{
|
||||
builder.ClearProviders();
|
||||
builder.Services.TryAddEnumerable(
|
||||
ServiceDescriptor.Singleton<MEL.ILoggerProvider, CmdPalLoggerProvider>());
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -60,4 +61,8 @@
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Logging\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -8,6 +8,6 @@ public sealed class PinyinFuzzyMatcherOptions
|
||||
{
|
||||
public PinyinMode Mode { get; init; } = PinyinMode.AutoSimplifiedChineseUi;
|
||||
|
||||
/// <summary>Remove IME syllable separators (') for query secondary variant.</summary>
|
||||
/// <summary>Gets a value indicating whether IME syllable separators (') are removed for query secondary variant.</summary>
|
||||
public bool RemoveApostrophesForQuery { get; init; } = true;
|
||||
}
|
||||
|
||||
@@ -341,25 +341,25 @@ public sealed partial class AppearanceSettingsViewModel : ObservableObject, IDis
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the backdrop opacity slider should be visible.
|
||||
/// Gets a value indicating whether the backdrop opacity slider should be visible.
|
||||
/// </summary>
|
||||
public bool IsBackdropOpacityVisible =>
|
||||
BackdropStyles.Get(_settingsService.Settings.BackdropStyle).SupportsOpacity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the backdrop description (for styles without options) should be visible.
|
||||
/// Gets a value indicating whether the backdrop description (for styles without options) should be visible.
|
||||
/// </summary>
|
||||
public bool IsMicaBackdropDescriptionVisible =>
|
||||
!BackdropStyles.Get(_settingsService.Settings.BackdropStyle).SupportsOpacity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether background/colorization settings are available.
|
||||
/// Gets a value indicating whether background/colorization settings are available.
|
||||
/// </summary>
|
||||
public bool IsBackgroundSettingsEnabled =>
|
||||
BackdropStyles.Get(_settingsService.Settings.BackdropStyle).SupportsColorization;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the "not available" message should be shown (inverse of IsBackgroundSettingsEnabled).
|
||||
/// Gets a value indicating whether the "not available" message should be shown (inverse of IsBackgroundSettingsEnabled).
|
||||
/// </summary>
|
||||
public bool IsBackgroundNotAvailableVisible =>
|
||||
!BackdropStyles.Get(_settingsService.Settings.BackdropStyle).SupportsColorization;
|
||||
|
||||
Binary file not shown.
@@ -36,17 +36,17 @@ public sealed record BackdropStyleConfig
|
||||
public float FixedOpacity { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this backdrop style supports custom colorization (tint colors).
|
||||
/// Gets a value indicating whether this backdrop style supports custom colorization (tint colors).
|
||||
/// </summary>
|
||||
public bool SupportsColorization { get; init; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this backdrop style supports custom background images.
|
||||
/// Gets a value indicating whether this backdrop style supports custom background images.
|
||||
/// </summary>
|
||||
public bool SupportsBackgroundImage { get; init; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this backdrop style supports opacity adjustment.
|
||||
/// Gets a value indicating whether this backdrop style supports opacity adjustment.
|
||||
/// </summary>
|
||||
public bool SupportsOpacity { get; init; } = true;
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ internal sealed class ExtensionTemplateService : IExtensionTemplateService
|
||||
|
||||
private static readonly HashSet<string> _copyAsIsTemplateExtensions = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
".md",
|
||||
".png",
|
||||
};
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ public sealed class ThemeSnapshot
|
||||
public required float BackgroundBrightness { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether colorization is active (accent color, custom color, or image mode).
|
||||
/// Gets a value indicating whether colorization is active (accent color, custom color, or image mode).
|
||||
/// </summary>
|
||||
public required bool HasColorization { get; init; }
|
||||
}
|
||||
|
||||
@@ -93,19 +93,19 @@ public record DockBandSettings
|
||||
public required string CommandId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether titles are shown for items in this band.
|
||||
/// Gets whether titles are shown for items in this band.
|
||||
/// If null, falls back to dock-wide ShowLabels setting.
|
||||
/// </summary>
|
||||
public bool? ShowTitles { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether subtitles are shown for items in this band.
|
||||
/// Gets whether subtitles are shown for items in this band.
|
||||
/// If null, falls back to dock-wide ShowLabels setting.
|
||||
/// </summary>
|
||||
public bool? ShowSubtitles { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value for backward compatibility. Maps to ShowTitles.
|
||||
/// Gets a value for backward compatibility. Maps to ShowTitles.
|
||||
/// </summary>
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public bool? ShowLabels
|
||||
|
||||
@@ -9,37 +9,37 @@ namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
public sealed class WindowPosition
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets left position in device pixels.
|
||||
/// Gets the left position in device pixels.
|
||||
/// </summary>
|
||||
public int X { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets top position in device pixels.
|
||||
/// Gets the top position in device pixels.
|
||||
/// </summary>
|
||||
public int Y { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets width in device pixels.
|
||||
/// Gets the width in device pixels.
|
||||
/// </summary>
|
||||
public int Width { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets height in device pixels.
|
||||
/// Gets the height in device pixels.
|
||||
/// </summary>
|
||||
public int Height { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets width of the screen in device pixels where the window is located.
|
||||
/// Gets the width of the screen in device pixels where the window is located.
|
||||
/// </summary>
|
||||
public int ScreenWidth { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets height of the screen in device pixels where the window is located.
|
||||
/// Gets the height of the screen in device pixels where the window is located.
|
||||
/// </summary>
|
||||
public int ScreenHeight { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets DPI (dots per inch) of the display where the window is located.
|
||||
/// Gets the DPI (dots per inch) of the display where the window is located.
|
||||
/// </summary>
|
||||
public int Dpi { get; init; }
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Common;
|
||||
using Microsoft.CmdPal.Common.Helpers;
|
||||
using Microsoft.CmdPal.Common.Logging;
|
||||
using Microsoft.CmdPal.Common.Services;
|
||||
using Microsoft.CmdPal.Common.Text;
|
||||
using Microsoft.CmdPal.Ext.Apps;
|
||||
@@ -125,6 +126,8 @@ public partial class App : Application, IDisposable
|
||||
services.AddSingleton(TaskScheduler.FromCurrentSynchronizationContext());
|
||||
var dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
services.AddCmdPalLogging();
|
||||
|
||||
AddBuiltInCommands(services, appInfoService.ConfigDirectory);
|
||||
|
||||
AddCoreServices(services, appInfoService);
|
||||
|
||||
@@ -157,12 +157,6 @@ public sealed partial class SearchBar : UserControl,
|
||||
{
|
||||
// Clear the search box
|
||||
FilterBox.Text = string.Empty;
|
||||
|
||||
// hack TODO GH #245
|
||||
if (CurrentPageViewModel is not null)
|
||||
{
|
||||
CurrentPageViewModel.SearchTextBox = FilterBox.Text;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -170,14 +164,6 @@ public sealed partial class SearchBar : UserControl,
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == VirtualKey.Back)
|
||||
{
|
||||
// hack TODO GH #245
|
||||
if (CurrentPageViewModel is not null)
|
||||
{
|
||||
CurrentPageViewModel.SearchTextBox = FilterBox.Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FilterBox_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
|
||||
@@ -332,19 +318,6 @@ public sealed partial class SearchBar : UserControl,
|
||||
private void FilterBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
// Logger.LogInfo($"FilterBox_TextChanged: {FilterBox.Text}");
|
||||
|
||||
// TERRIBLE HACK TODO GH #245
|
||||
// There's weird wacky bugs with debounce currently. We're trying
|
||||
// to get them ingested, but while we wait for the toolkit feeds to
|
||||
// bubble, just manually send the first character, always
|
||||
// (otherwise aliases just stop working)
|
||||
if (FilterBox.Text.Length == 1)
|
||||
{
|
||||
DoFilterBoxUpdate();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (InSuggestion)
|
||||
{
|
||||
// Logger.LogInfo($"-- skipping, in suggestion --");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user