mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-30 08:56:33 +01:00
Compare commits
13 Commits
shawn/fixA
...
stable-bac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b545597997 | ||
|
|
b995ffabd7 | ||
|
|
3c439eed55 | ||
|
|
dd33a45aec | ||
|
|
ca6f993be1 | ||
|
|
29687d588f | ||
|
|
6c999c32da | ||
|
|
fd2a3915ef | ||
|
|
4345b95527 | ||
|
|
c0f7ec0265 | ||
|
|
c2d1214974 | ||
|
|
f732185885 | ||
|
|
ad207da3f3 |
7
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
7
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -7,13 +7,6 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Please make sure to [search for existing issues](https://github.com/microsoft/PowerToys/issues) before filing a new one!
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
We are aware of the following high-volume issues and are actively working on them. Please check if your issue is one of these before filing a new bug report:
|
||||
* **PowerToys Run crash related to "Desktop composition is disabled"**: This may appear as `COMException: 0x80263001`. For more details, see issue [#31226](https://github.com/microsoft/PowerToys/issues/31226).
|
||||
* **PowerToys Run crash with `COMException (0xD0000701)`**: For more details, see issue [#30769](https://github.com/microsoft/PowerToys/issues/30769).
|
||||
* **PowerToys Run crash with a "Cyclic reference" error**: This `System.InvalidOperationException` is detailed in issue [#36451](https://github.com/microsoft/PowerToys/issues/36451).
|
||||
- id: version
|
||||
type: input
|
||||
attributes:
|
||||
|
||||
7
.github/actions/spell-check/allow/code.txt
vendored
7
.github/actions/spell-check/allow/code.txt
vendored
@@ -321,10 +321,3 @@ REGSTR
|
||||
|
||||
# Misc Win32 APIs and PInvokes
|
||||
INVOKEIDLIST
|
||||
|
||||
# PowerRename metadata pattern abbreviations (used in tests and regex patterns)
|
||||
DDDD
|
||||
FFF
|
||||
HHH
|
||||
riday
|
||||
YYY
|
||||
|
||||
69
.github/actions/spell-check/expect.txt
vendored
69
.github/actions/spell-check/expect.txt
vendored
@@ -22,7 +22,6 @@ ADate
|
||||
ADDSTRING
|
||||
ADDUNDORECORD
|
||||
ADifferent
|
||||
adjacents
|
||||
ADMINS
|
||||
adml
|
||||
admx
|
||||
@@ -35,7 +34,6 @@ AFX
|
||||
AGGREGATABLE
|
||||
AHK
|
||||
AHybrid
|
||||
AIUI
|
||||
akv
|
||||
ALarger
|
||||
ALIGNRIGHT
|
||||
@@ -47,7 +45,6 @@ Allmodule
|
||||
ALLOWUNDO
|
||||
ALLVIEW
|
||||
ALPHATYPE
|
||||
amazonbedrock
|
||||
AModifier
|
||||
amr
|
||||
ANDSCANS
|
||||
@@ -97,10 +94,8 @@ ASSOCSTR
|
||||
ASYNCWINDOWPLACEMENT
|
||||
ASYNCWINDOWPOS
|
||||
atl
|
||||
ATX
|
||||
ATRIOX
|
||||
aumid
|
||||
authenticode
|
||||
Authenticode
|
||||
AUTOBUDDY
|
||||
AUTOCHECKBOX
|
||||
@@ -115,13 +110,9 @@ AValid
|
||||
AWAYMODE
|
||||
azcliversion
|
||||
azman
|
||||
azureaiinference
|
||||
azureinference
|
||||
azureopenai
|
||||
bbwe
|
||||
BCIE
|
||||
bck
|
||||
backticks
|
||||
BESTEFFORT
|
||||
bezelled
|
||||
bhid
|
||||
@@ -149,7 +140,6 @@ bmi
|
||||
BNumber
|
||||
BODGY
|
||||
BOklab
|
||||
Bootstrappers
|
||||
BOOTSTRAPPERINSTALLFOLDER
|
||||
BOTTOMALIGN
|
||||
boxmodel
|
||||
@@ -177,12 +167,9 @@ BYPOSITION
|
||||
CALCRECT
|
||||
CALG
|
||||
callbackptr
|
||||
cabstr
|
||||
calpwstr
|
||||
caub
|
||||
Cangjie
|
||||
CANRENAME
|
||||
Carlseibert
|
||||
Canvascustomlayout
|
||||
CAPTUREBLT
|
||||
CAPTURECHANGED
|
||||
@@ -206,11 +193,9 @@ changecursor
|
||||
CHILDACTIVATE
|
||||
CHILDWINDOW
|
||||
CHOOSEFONT
|
||||
CIBUILD
|
||||
cidl
|
||||
CIELCh
|
||||
cim
|
||||
claude
|
||||
CImage
|
||||
cla
|
||||
CLASSDC
|
||||
@@ -243,7 +228,6 @@ CODENAME
|
||||
codereview
|
||||
Codespaces
|
||||
Coen
|
||||
cognitiveservices
|
||||
COINIT
|
||||
colid
|
||||
colorconv
|
||||
@@ -258,7 +242,6 @@ cominterop
|
||||
commandnotfound
|
||||
commandpalette
|
||||
compmgmt
|
||||
COMPOSITIONDISABLED
|
||||
COMPOSITIONFULL
|
||||
CONFIGW
|
||||
CONFLICTINGMODIFIERKEY
|
||||
@@ -284,14 +267,12 @@ countof
|
||||
covrun
|
||||
cpcontrols
|
||||
cph
|
||||
cppcoreguidelines
|
||||
cplusplus
|
||||
CPower
|
||||
cpptools
|
||||
cppvsdbg
|
||||
cppwinrt
|
||||
createdump
|
||||
creativecommons
|
||||
CREATEPROCESS
|
||||
CREATESCHEDULEDTASK
|
||||
CREATESTRUCT
|
||||
@@ -315,8 +296,6 @@ CURRENTDIR
|
||||
CURSORINFO
|
||||
cursorpos
|
||||
CURSORSHOWING
|
||||
CURSORWRAP
|
||||
CursorWrap
|
||||
customaction
|
||||
CUSTOMACTIONTEST
|
||||
CUSTOMFORMATPLACEHOLDER
|
||||
@@ -356,7 +335,6 @@ Deact
|
||||
debugbreak
|
||||
decryptor
|
||||
Dedup
|
||||
dfx
|
||||
Deduplicator
|
||||
Deeplink
|
||||
DEFAULTBOOTSTRAPPERINSTALLFOLDER
|
||||
@@ -391,7 +369,7 @@ devmgmt
|
||||
DEVMODE
|
||||
DEVMODEW
|
||||
devpal
|
||||
dfx
|
||||
DFX
|
||||
DIALOGEX
|
||||
digicert
|
||||
DINORMAL
|
||||
@@ -405,7 +383,6 @@ DISPLAYFREQUENCY
|
||||
displayname
|
||||
DISPLAYORIENTATION
|
||||
divyan
|
||||
djwsxzxb
|
||||
Dlg
|
||||
DLGFRAME
|
||||
DLGMODALFRAME
|
||||
@@ -431,7 +408,6 @@ DROPFILES
|
||||
DSTINVERT
|
||||
DString
|
||||
DSVG
|
||||
dto
|
||||
DTo
|
||||
DUMMYUNIONNAME
|
||||
dutil
|
||||
@@ -467,7 +443,6 @@ EDITSHORTCUTS
|
||||
EDITTEXT
|
||||
EFile
|
||||
ekus
|
||||
eku
|
||||
emojis
|
||||
ENABLEDELAYEDEXPANSION
|
||||
ENABLEDPOPUP
|
||||
@@ -531,12 +506,9 @@ EXTRINSICPROPERTIES
|
||||
eyetracker
|
||||
FANCYZONESDRAWLAYOUTTEST
|
||||
FANCYZONESEDITOR
|
||||
FNumber
|
||||
FARPROC
|
||||
fdx
|
||||
fesf
|
||||
FFFF
|
||||
Figma
|
||||
FILEEXPLORER
|
||||
fileexploreraddons
|
||||
fileexplorerpreview
|
||||
@@ -563,7 +535,6 @@ FIXEDSYS
|
||||
flac
|
||||
flyouts
|
||||
FMask
|
||||
foundrylocal
|
||||
fmtid
|
||||
FOF
|
||||
FOFX
|
||||
@@ -628,8 +599,6 @@ GValue
|
||||
gwl
|
||||
GWLP
|
||||
GWLSTYLE
|
||||
googleai
|
||||
googlegemini
|
||||
hangeul
|
||||
Hanzi
|
||||
Hardlines
|
||||
@@ -666,7 +635,6 @@ Hiber
|
||||
Hiberboot
|
||||
HIBYTE
|
||||
hicon
|
||||
HICONSM
|
||||
HIDEREADONLY
|
||||
HIDEWINDOW
|
||||
Hif
|
||||
@@ -692,7 +660,6 @@ hmonitor
|
||||
homies
|
||||
homljgmgpmcbpjbnjpfijnhipfkiclkd
|
||||
HOOKPROC
|
||||
huggingface
|
||||
HORZRES
|
||||
HORZSIZE
|
||||
Hostbackdropbrush
|
||||
@@ -719,7 +686,6 @@ HTCLIENT
|
||||
hthumbnail
|
||||
HTOUCHINPUT
|
||||
HTTRANSPARENT
|
||||
hutchinsoniana
|
||||
HVal
|
||||
HValue
|
||||
Hvci
|
||||
@@ -741,9 +707,7 @@ IDCANCEL
|
||||
IDD
|
||||
idk
|
||||
idl
|
||||
IIM
|
||||
idlist
|
||||
ifd
|
||||
IDOK
|
||||
IDOn
|
||||
IDR
|
||||
@@ -760,7 +724,6 @@ Ijwhost
|
||||
ILD
|
||||
IMAGEHLP
|
||||
IMAGERESIZERCONTEXTMENU
|
||||
IPTC
|
||||
IMAGERESIZEREXT
|
||||
imageresizerinput
|
||||
imageresizersettings
|
||||
@@ -779,7 +742,7 @@ INITDIALOG
|
||||
INITGUID
|
||||
INITTOLOGFONTSTRUCT
|
||||
INLINEPREFIX
|
||||
inlines
|
||||
Inlines
|
||||
INPC
|
||||
inproc
|
||||
INPUTHARDWARE
|
||||
@@ -852,7 +815,6 @@ keyvault
|
||||
KILLFOCUS
|
||||
killrunner
|
||||
kmph
|
||||
ksa
|
||||
kvp
|
||||
Kybd
|
||||
LARGEICON
|
||||
@@ -900,7 +862,6 @@ LOCKTYPE
|
||||
LOGFONT
|
||||
LOGFONTW
|
||||
logon
|
||||
lon
|
||||
LOGMSG
|
||||
LOGPIXELSX
|
||||
LOGPIXELSY
|
||||
@@ -960,7 +921,6 @@ LWA
|
||||
lwin
|
||||
LZero
|
||||
MAGTRANSFORM
|
||||
makeappx
|
||||
MAKEINTRESOURCE
|
||||
MAKEINTRESOURCEA
|
||||
MAKEINTRESOURCEW
|
||||
@@ -992,7 +952,6 @@ MENUITEMINFOW
|
||||
MERGECOPY
|
||||
MERGEPAINT
|
||||
Metadatas
|
||||
metadatamatters
|
||||
metafile
|
||||
mfc
|
||||
Mgmt
|
||||
@@ -1060,7 +1019,6 @@ msiexec
|
||||
MSIFASTINSTALL
|
||||
MSIHANDLE
|
||||
MSIRESTARTMANAGERCONTROL
|
||||
MSIs
|
||||
msixbundle
|
||||
MSIXCA
|
||||
MSLLHOOKSTRUCT
|
||||
@@ -1152,11 +1110,9 @@ NONCLIENTMETRICSW
|
||||
NONELEVATED
|
||||
nonspace
|
||||
nonstd
|
||||
nullrefs
|
||||
NOOWNERZORDER
|
||||
NOPARENTNOTIFY
|
||||
NOPREFIX
|
||||
NPU
|
||||
NOREDIRECTIONBITMAP
|
||||
NOREDRAW
|
||||
NOREMOVE
|
||||
@@ -1192,7 +1148,6 @@ ntfs
|
||||
NTSTATUS
|
||||
NTSYSAPI
|
||||
NULLCURSOR
|
||||
nullref
|
||||
nullonfailure
|
||||
numberbox
|
||||
nwc
|
||||
@@ -1216,9 +1171,6 @@ opencode
|
||||
OPENFILENAME
|
||||
opensource
|
||||
openxmlformats
|
||||
ollama
|
||||
Olllama
|
||||
onnx
|
||||
OPTIMIZEFORINVOKE
|
||||
ORPHANEDDIALOGTITLE
|
||||
ORSCANS
|
||||
@@ -1300,7 +1252,6 @@ pinvoke
|
||||
pipename
|
||||
PKBDLLHOOKSTRUCT
|
||||
pkgfamily
|
||||
PKI
|
||||
plib
|
||||
ploc
|
||||
ploca
|
||||
@@ -1313,7 +1264,6 @@ pnid
|
||||
PNMLINK
|
||||
Poc
|
||||
Podcasts
|
||||
Photoshop
|
||||
POINTERID
|
||||
POINTERUPDATE
|
||||
Pokedex
|
||||
@@ -1408,8 +1358,6 @@ pwsz
|
||||
pwtd
|
||||
QDC
|
||||
qit
|
||||
QNN
|
||||
Qualcomm
|
||||
QITAB
|
||||
QITABENT
|
||||
qoi
|
||||
@@ -1518,7 +1466,6 @@ sacl
|
||||
safeprojectname
|
||||
SAMEKEYPREVIOUSLYMAPPED
|
||||
SAMESHORTCUTPREVIOUSLYMAPPED
|
||||
samsung
|
||||
sancov
|
||||
SAVEFAILED
|
||||
scanled
|
||||
@@ -1746,7 +1693,6 @@ syskeydown
|
||||
SYSKEYUP
|
||||
SYSLIB
|
||||
SYSMENU
|
||||
systemai
|
||||
SYSTEMAPPS
|
||||
SYSTEMMODAL
|
||||
SYSTEMTIME
|
||||
@@ -1881,7 +1827,6 @@ USEINSTALLERFORTEST
|
||||
USESHOWWINDOW
|
||||
USESTDHANDLES
|
||||
USRDLL
|
||||
utm
|
||||
UType
|
||||
uuidv
|
||||
uwp
|
||||
@@ -1958,7 +1903,6 @@ wcsicmp
|
||||
wcsncpy
|
||||
wcsnicmp
|
||||
WCT
|
||||
WCRAPI
|
||||
WDA
|
||||
wdm
|
||||
wdp
|
||||
@@ -1972,7 +1916,6 @@ wgpocpl
|
||||
WHEREID
|
||||
wic
|
||||
wifi
|
||||
wikimedia
|
||||
wikipedia
|
||||
WIL
|
||||
winapi
|
||||
@@ -2002,8 +1945,6 @@ WINL
|
||||
winlogon
|
||||
winmd
|
||||
WINNT
|
||||
windowsml
|
||||
winml
|
||||
winres
|
||||
winrt
|
||||
winsdk
|
||||
@@ -2038,7 +1979,7 @@ WORKSPACESEDITOR
|
||||
WORKSPACESLAUNCHER
|
||||
WORKSPACESSNAPSHOTTOOL
|
||||
WORKSPACESWINDOWARRANGER
|
||||
worktree
|
||||
Worktree
|
||||
wox
|
||||
wparam
|
||||
wpf
|
||||
@@ -2069,9 +2010,7 @@ XAxis
|
||||
XButton
|
||||
xclip
|
||||
xcopy
|
||||
xap
|
||||
XDeployment
|
||||
XDimension
|
||||
xdf
|
||||
XDocument
|
||||
XElement
|
||||
@@ -2089,7 +2028,6 @@ xsi
|
||||
XSpeed
|
||||
XStr
|
||||
xstyler
|
||||
xmp
|
||||
XTimer
|
||||
XUP
|
||||
XVIRTUALSCREEN
|
||||
@@ -2097,7 +2035,6 @@ xxxxxx
|
||||
YAxis
|
||||
ycombinator
|
||||
YIncrement
|
||||
YDimension
|
||||
yinle
|
||||
yinyue
|
||||
YPels
|
||||
|
||||
64
.github/copilot-instructions.md
vendored
64
.github/copilot-instructions.md
vendored
@@ -1,59 +1,43 @@
|
||||
---
|
||||
description: PowerToys AI contributor guidance.
|
||||
applyTo: pullRequests
|
||||
---
|
||||
|
||||
# PowerToys - Copilot guide (concise)
|
||||
# PowerToys – Copilot guide (concise)
|
||||
|
||||
This is the top-level guide for AI changes. Keep edits small, follow existing patterns, and cite exact paths in PRs.
|
||||
|
||||
# Repo map (1-line per area)
|
||||
Repo map (1‑line per area)
|
||||
- Core apps: `src/runner/**` (tray/loader), `src/settings-ui/**` (Settings app)
|
||||
- Shared libs: `src/common/**`
|
||||
- Modules: `src/modules/*` (one per utility; Command Palette in `src/modules/cmdpal/**`)
|
||||
- Build tools/docs: `tools/**`, `doc/devdocs/**`
|
||||
|
||||
# Build and test (defaults)
|
||||
Build and test (defaults)
|
||||
- Prerequisites: Visual Studio 2022 17.4+, minimal Windows 10 1803+.
|
||||
- Build discipline:
|
||||
- One terminal per operation (build -> test). Do not switch or open new ones mid-flow.
|
||||
- One terminal per operation (build → test). Don’t switch/open new ones mid-flow.
|
||||
- After making changes, `cd` to the project folder that changed (`.csproj`/`.vcxproj`).
|
||||
- Use scripts to build, synchronously block and wait in foreground for completion: `tools/build/build.ps1|.cmd` (current folder), `build-essentials.*` (once per brand new build for missing nuget packages).
|
||||
- Treat build exit code 0 as success; any non-zero exit code is a failure. Read the errors log in the build folder (such as `build.*.*.errors.log`) and surface problems.
|
||||
- Do not start tests or launch Runner until the previous step succeeded.
|
||||
- Tests (fast and targeted):
|
||||
- Find the test project by product code prefix (for example FancyZones, AdvancedPaste). Look for a sibling folder or one to two levels up named like `<Product>*UnitTests` or `<Product>*UITests`.
|
||||
- Build the test project, wait for exit, then run only those tests via VS Test Explorer or `vstest.console.exe` with filters. Avoid `dotnet test` in this repo.
|
||||
- Add or adjust tests when changing behavior; if skipped, state why (for example comment-only or string rename).
|
||||
- Use script(s) to build, synchronously block and wait in foreground for it to finish: `tools/build/build.ps1|.cmd` (current folder), `build-essentials.*` (once per brand new build for missing nuget packages)
|
||||
- Treat build **exit code 0** as success; any non-zero exit code is a failure, have Copilot read the errors log in the build folder (e.g., `build.*.*.errors.log`) and surface problems.
|
||||
- Don’t start tests or launch Runner until the previous step succeeded.
|
||||
- Tests (fast + targeted):
|
||||
- Find the test project by product code prefix (e.g., FancyZones, AdvancedPaste). Look for a sibling folder or 1–2 levels up named like `<Product>*UnitTests` or `<Product>*UITests`.
|
||||
- Build the test project, wait for **exit**, then run only those tests via VS Test Explorer or `vstest.console.exe` with filters. Avoid `dotnet test` in this repo.
|
||||
- Add/adjust tests when changing behavior; if skipped, state why (e.g., comment-only, string rename).
|
||||
|
||||
# Pull requests (expectations)
|
||||
- Atomic: one logical change; no drive-by refactors.
|
||||
- Describe: problem, approach, risk, test evidence.
|
||||
Pull requests (expectations)
|
||||
- Atomic: one logical change; no drive‑by refactors.
|
||||
- Describe: problem / approach / risk / test evidence.
|
||||
- List: touched paths if not obvious.
|
||||
|
||||
# When to ask for clarification
|
||||
When to ask for clarification
|
||||
- Ambiguous spec after scanning relevant docs (see below).
|
||||
- Cross-module impact (shared enum or struct) not clear.
|
||||
- Security, elevation, or installer changes.
|
||||
- Cross-module impact (shared enum/struct) not clear.
|
||||
- Security / elevation / installer changes.
|
||||
|
||||
# Logging (use existing stacks)
|
||||
- C++ logging lives in `src/common/logger/**` (`Logger::info`, `Logger::warn`, `Logger::error`, `Logger::debug`). Keep hot paths quiet (hooks, tight loops).
|
||||
- C# logging goes through `ManagedCommon.Logger` (`LogInfo`, `LogWarning`, `LogError`, `LogDebug`, `LogTrace`). Some UIs use injected `ILogger` via `LoggerInstance.Logger`.
|
||||
Logging (use existing stacks)
|
||||
- C++: `src/common/logger/**` (`Logger::info|warn|error|debug`). Keep hot paths quiet (hooks, tight loops).
|
||||
- C#: `ManagedCommon.Logger` (`LogInfo|LogWarning|LogError|LogDebug|LogTrace`). Some UIs use injected `ILogger` via `LoggerInstance.Logger`.
|
||||
|
||||
# Docs to consult
|
||||
Docs to consult
|
||||
- `tools/build/BUILD-GUIDELINES.md`
|
||||
- `doc/devdocs/core/architecture.md`
|
||||
- `doc/devdocs/core/runner.md`
|
||||
- `doc/devdocs/core/settings/readme.md`
|
||||
- `doc/devdocs/modules/readme.md`
|
||||
- `doc/devdocs/core/architecture.md`, `doc/devdocs/core/runner.md`, `doc/devdocs/core/settings/readme.md`, `doc/devdocs/modules/readme.md`
|
||||
|
||||
# Language style rules
|
||||
- Always enforce repo analyzers: root `.editorconfig` plus any `stylecop.json`.
|
||||
- C# code follows StyleCop.Analyzers and Microsoft.CodeAnalysis.NetAnalyzers.
|
||||
- C++ code honors `.clang-format` plus `.clang-tidy` (modernize/cppcoreguidelines/readability).
|
||||
- Markdown files wrap at 80 characters and use ATX headers with fenced code blocks that include language tags.
|
||||
- YAML files indent two spaces and add comments for complex settings while keeping keys clear.
|
||||
- PowerShell scripts use Verb-Noun names and prefer single-quoted literals while documenting parameters and satisfying PSScriptAnalyzer.
|
||||
|
||||
# Done checklist (self review before finishing)
|
||||
- Build clean? Tests updated or passed? No unintended formatting? Any new dependency? Documented skips?
|
||||
Done checklist (self review before finishing)
|
||||
- Build clean? Tests updated/passed? No unintended formatting? Any new dependency? Documented skips?
|
||||
16
.github/prompts/create-commit-title.prompt.md
vendored
16
.github/prompts/create-commit-title.prompt.md
vendored
@@ -1,16 +0,0 @@
|
||||
---
|
||||
mode: 'agent'
|
||||
model: GPT-5-Codex (Preview)
|
||||
description: 'Generate an 80-character git commit title for the local diff.'
|
||||
---
|
||||
|
||||
**Goal:** Provide a ready-to-paste git commit title (<= 80 characters) that captures the most important local changes since `HEAD`.
|
||||
|
||||
**Workflow:**
|
||||
1. Run a single command to view the local diff since the last commit:
|
||||
```@terminal
|
||||
git diff HEAD
|
||||
```
|
||||
2. From that diff, identify the dominant area (reference key paths like `src/modules/*`, `doc/devdocs/**`, etc.), the type of change (bug fix, docs update, config tweak), and any notable impact.
|
||||
3. Draft a concise, imperative commit title summarizing the dominant change. Keep it plain ASCII, <= 80 characters, and avoid trailing punctuation. Mention the primary component when obvious (for example `FancyZones:` or `Docs:`).
|
||||
4. Respond with only the final commit title on a single line so it can be pasted directly into `git commit`.
|
||||
22
.github/prompts/create-pr-summary.prompt.md
vendored
22
.github/prompts/create-pr-summary.prompt.md
vendored
@@ -1,22 +0,0 @@
|
||||
---
|
||||
mode: 'agent'
|
||||
model: GPT-5-Codex (Preview)
|
||||
description: 'Generate a PowerToys-ready pull request description from the local diff.'
|
||||
---
|
||||
|
||||
**Goal:** Produce a ready-to-paste PR title and description that follows PowerToys conventions by comparing the current branch against a user-selected target branch.
|
||||
|
||||
**Repo guardrails:**
|
||||
- Treat `.github/pull_request_template.md` as the single source of truth; load it at runtime instead of embedding hardcoded content in this prompt.
|
||||
- Preserve section order from the template but only surface checklist lines that are relevant for the detected changes, filling them with `[x]`/`[ ]` as appropriate.
|
||||
- Cite touched paths with inline backticks, matching the guidance in `.github/copilot-instructions.md`.
|
||||
- Call out test coverage explicitly: list automated tests run (unit/UI) or state why they are not applicable.
|
||||
|
||||
**Workflow:**
|
||||
1. Determine the target branch from user context; default to `main` when no branch is supplied.
|
||||
2. Run `git status --short` once to surface uncommitted files that may influence the summary.
|
||||
3. Run `git diff <target-branch>...HEAD` a single time to review the detailed changes. Only when confidence stays low dig deeper with focused calls such as `git diff <target-branch>...HEAD -- <path>`.
|
||||
4. From the diff, capture impacted areas, key file changes, behavioral risks, migrations, and noteworthy edge cases.
|
||||
5. Confirm validation: list tests executed with results or state why tests were skipped in line with repo guidance.
|
||||
6. Load `.github/pull_request_template.md`, mirror its section order, and populate it with the gathered facts. Include only relevant checklist entries, marking them `[x]/[ ]` and noting any intentional omissions as "N/A".
|
||||
7. Present the filled template inside a fenced ```markdown code block with no extra commentary so it is ready to paste into a PR, clearly flagging any placeholders that still need user input.
|
||||
22
.github/prompts/fix-spelling.prompt.md
vendored
22
.github/prompts/fix-spelling.prompt.md
vendored
@@ -1,22 +0,0 @@
|
||||
---
|
||||
mode: 'agent'
|
||||
model: GPT-5-Codex (Preview)
|
||||
description: 'Resolve Code scanning / check-spelling comments on the active PR.'
|
||||
---
|
||||
|
||||
**Goal:** Clear every outstanding GitHub pull request comment created by the `Code scanning / check-spelling` workflow by explicitly allowing intentional terms.
|
||||
|
||||
**Guardrails:**
|
||||
- Update only discussion threads authored by `github-actions` or `github-actions[bot]` that mention `Code scanning results / check-spelling`.
|
||||
- Resolve findings solely by editing `.github/actions/spell-check/expect.txt`; reuse existing entries.
|
||||
- Leave all other files and topics untouched.
|
||||
|
||||
**Prerequisites:**
|
||||
- Install GitHub CLI if it is not present: `winget install GitHub.cli`.
|
||||
- Run `gh auth login` once before the first CLI use.
|
||||
|
||||
**Workflow:**
|
||||
1. Determine the active pull request with a single `gh pr view --json number` call (default to the current branch).
|
||||
2. Fetch all PR discussion data once via `gh pr view --json comments,reviews` and filter to check-spelling comments authored by `github-actions` or `github-actions[bot]` that are not minimized; when several remain, process only the most recent comment body.
|
||||
3. For each flagged token, review `.github/actions/spell-check/expect.txt` for an equivalent term (for example an existing lowercase variant); when found, reuse that normalized term rather than adding a new entry, even if the flagged token differs only by casing. Only add a new entry after confirming no equivalent already exists.
|
||||
4. Add any remaining missing token to `.github/actions/spell-check/expect.txt`, keeping surrounding formatting intact.
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -349,7 +349,10 @@ src/common/Telemetry/*.etl
|
||||
/src/modules/powerrename/ui/RCb24464
|
||||
|
||||
# Generated installer file for Monaco source files.
|
||||
/installer/PowerToysSetup/MonacoSRC.wxs
|
||||
/installer/PowerToysSetup/DscResources.wxs
|
||||
/installer/PowerToysSetupVNext/MonacoSRC.wxs
|
||||
/installer/PowerToysSetupVNext/DscResources.wxs
|
||||
|
||||
# MSBuildCache
|
||||
/MSBuildCacheLogs/
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
{
|
||||
"MatchedPath": [
|
||||
"*.resources.dll",
|
||||
|
||||
"WinUI3Apps\\Assets\\Settings\\Scripts\\*.ps1",
|
||||
|
||||
"PowerToys.ActionRunner.exe",
|
||||
@@ -26,7 +27,6 @@
|
||||
"PowerToys.GPOWrapper.dll",
|
||||
"PowerToys.GPOWrapperProjection.dll",
|
||||
"PowerToys.AllExperiments.dll",
|
||||
"LanguageModelProvider.dll",
|
||||
|
||||
"Common.Search.dll",
|
||||
|
||||
@@ -181,7 +181,6 @@
|
||||
"PowerToys.MousePointerCrosshairs.dll",
|
||||
"PowerToys.MouseJumpUI.dll",
|
||||
"PowerToys.MouseJumpUI.exe",
|
||||
"PowerToys.CursorWrap.dll",
|
||||
|
||||
"PowerToys.MouseWithoutBorders.dll",
|
||||
"PowerToys.MouseWithoutBorders.exe",
|
||||
@@ -236,9 +235,7 @@
|
||||
"*Microsoft.CmdPal.UI_*.msix",
|
||||
|
||||
"PowerToys.DSC.dll",
|
||||
"PowerToys.DSC.exe",
|
||||
|
||||
"PowerToysSparse.msix"
|
||||
"PowerToys.DSC.exe"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
@@ -347,8 +344,6 @@
|
||||
"Testably.Abstractions.FileSystem.Interface.dll",
|
||||
"WinUI3Apps\\Testably.Abstractions.FileSystem.Interface.dll",
|
||||
"ColorCode.Core.dll",
|
||||
"Microsoft.SemanticKernel.Connectors.Ollama.dll",
|
||||
"OllamaSharp.dll",
|
||||
|
||||
"UnitsNet.dll",
|
||||
"UtfUnknown.dll",
|
||||
|
||||
53
.pipelines/ESRPSigning_installer.json
Normal file
53
.pipelines/ESRPSigning_installer.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"Version": "1.0.0",
|
||||
"UseMinimatch": false,
|
||||
"SignBatches": [
|
||||
{
|
||||
"MatchedPath": [
|
||||
"PowerToysSetupCustomActionsVNext.dll",
|
||||
"SilentFilesInUseBAFunction.dll",
|
||||
"PowerToys*Setup-*.exe",
|
||||
"PowerToys*Setup-*.msi"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolSign",
|
||||
"Parameters": [
|
||||
{
|
||||
"parameterName": "OpusName",
|
||||
"parameterValue": "Microsoft"
|
||||
},
|
||||
{
|
||||
"parameterName": "OpusInfo",
|
||||
"parameterValue": "http://www.microsoft.com"
|
||||
},
|
||||
{
|
||||
"parameterName": "FileDigest",
|
||||
"parameterValue": "/fd \"SHA256\""
|
||||
},
|
||||
{
|
||||
"parameterName": "PageHash",
|
||||
"parameterValue": "/NPH"
|
||||
},
|
||||
{
|
||||
"parameterName": "TimeStamp",
|
||||
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
}
|
||||
],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolVerify",
|
||||
"Parameters": [],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -65,28 +65,21 @@ if (-not (Test-Path $outputDir)) {
|
||||
New-Item -Path $outputDir -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
|
||||
# DSC v3 manifests go to DSCModules subfolder
|
||||
$dscOutputDir = Join-Path $outputDir 'DSCModules'
|
||||
if (-not (Test-Path $dscOutputDir)) {
|
||||
Write-Host "Creating DSCModules subfolder at '$dscOutputDir'."
|
||||
New-Item -Path $dscOutputDir -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
Write-Host "DSC manifests will be generated to: '$outputDir'"
|
||||
|
||||
Write-Host "DSC manifests will be generated to: '$dscOutputDir'"
|
||||
Write-Host "Cleaning previously generated DSC manifest files from '$outputDir'."
|
||||
Get-ChildItem -Path $outputDir -Filter 'microsoft.powertoys.*.settings.dsc.resource.json' -ErrorAction SilentlyContinue | Remove-Item -Force
|
||||
|
||||
Write-Host "Cleaning previously generated DSC manifest files from '$dscOutputDir'."
|
||||
Get-ChildItem -Path $dscOutputDir -Filter 'microsoft.powertoys.*.settings.dsc.resource.json' -ErrorAction SilentlyContinue | Remove-Item -Force
|
||||
|
||||
$arguments = @('manifest', '--resource', 'settings', '--outputDir', $dscOutputDir)
|
||||
$arguments = @('manifest', '--resource', 'settings', '--outputDir', $outputDir)
|
||||
Write-Host "Invoking DSC manifest generator: '$exePath' $($arguments -join ' ')"
|
||||
& $exePath @arguments
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "PowerToys.DSC.exe exited with code $LASTEXITCODE"
|
||||
}
|
||||
|
||||
$generatedFiles = Get-ChildItem -Path $dscOutputDir -Filter 'microsoft.powertoys.*.settings.dsc.resource.json' -ErrorAction Stop
|
||||
$generatedFiles = Get-ChildItem -Path $outputDir -Filter 'microsoft.powertoys.*.settings.dsc.resource.json' -ErrorAction Stop
|
||||
if ($generatedFiles.Count -eq 0) {
|
||||
throw "No DSC manifest files were generated in '$dscOutputDir'."
|
||||
throw "No DSC manifest files were generated in '$outputDir'."
|
||||
}
|
||||
|
||||
Write-Host "Generated $($generatedFiles.Count) DSC manifest file(s):"
|
||||
|
||||
@@ -32,7 +32,7 @@ parameters:
|
||||
- name: enableMsBuildCaching
|
||||
type: boolean
|
||||
displayName: "Enable MSBuild Caching"
|
||||
default: false
|
||||
default: true
|
||||
- name: runTests
|
||||
type: boolean
|
||||
displayName: "Run Tests"
|
||||
|
||||
@@ -266,26 +266,6 @@ jobs:
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: Generate DSC artifacts for ARM64
|
||||
condition: and(succeeded(), eq(variables['BuildPlatform'], 'arm64'))
|
||||
inputs:
|
||||
solution: PowerToys.sln
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
-restore
|
||||
/p:Configuration=$(BuildConfiguration)
|
||||
/p:Platform=x64
|
||||
/t:DSC\PowerToys_Settings_DSC_Schema_Generator
|
||||
/bl:$(LogOutputDirectory)\build-dsc-generator.binlog
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
$(MSBuildCacheParameters)
|
||||
$(RestoreAdditionalProjectSourcesArg)
|
||||
platform: x64
|
||||
configuration: $(BuildConfiguration)
|
||||
msbuildArchitecture: x64
|
||||
maximumCpuCount: true
|
||||
|
||||
# Build PowerToys.DSC.exe for ARM64 (x64 uses existing binary from previous build)
|
||||
- task: VSBuild@1
|
||||
displayName: Build PowerToys.DSC.exe (x64 for generating manifests)
|
||||
@@ -532,6 +512,14 @@ jobs:
|
||||
versionNumber: ${{ parameters.versionNumber }}
|
||||
additionalBuildOptions: ${{ parameters.additionalBuildOptions }}
|
||||
|
||||
- template: steps-build-installer-vnext.yml
|
||||
parameters:
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
versionNumber: ${{ parameters.versionNumber }}
|
||||
additionalBuildOptions: ${{ parameters.additionalBuildOptions }}
|
||||
buildUserInstaller: true # NOTE: This is the distinction between the above and below rules
|
||||
|
||||
# This saves ~1GiB per architecture. We won't need these later.
|
||||
# Removes:
|
||||
# - All .pdb files from any static libs .libs (which were only used during linking)
|
||||
|
||||
@@ -2,6 +2,9 @@ parameters:
|
||||
- name: versionNumber
|
||||
type: string
|
||||
default: "0.0.1"
|
||||
- name: buildUserInstaller
|
||||
type: boolean
|
||||
default: false
|
||||
- name: codeSign
|
||||
type: boolean
|
||||
default: false
|
||||
@@ -22,26 +25,43 @@ steps:
|
||||
arguments: 'install --global wix --version 5.0.2'
|
||||
|
||||
- pwsh: |-
|
||||
Write-Host "##vso[task.setvariable variable=InstallerMachineRoot]installer\PowerToysSetupVNext\$(BuildPlatform)\$(BuildConfiguration)\MachineSetup"
|
||||
Write-Host "##vso[task.setvariable variable=InstallerUserRoot]installer\PowerToysSetupVNext\$(BuildPlatform)\$(BuildConfiguration)\UserSetup"
|
||||
Write-Host "##vso[task.setvariable variable=InstallerMachineBasename]PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform)"
|
||||
Write-Host "##vso[task.setvariable variable=InstallerUserBasename]PowerToysUserSetup-${{ parameters.versionNumber }}-$(BuildPlatform)"
|
||||
displayName: Prepare Installer variables
|
||||
& git clean -xfd -e *exe -- .\installer\
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Clean installer to reduce cross-contamination
|
||||
|
||||
- pwsh: |-
|
||||
# Determine whether this is a per-user build
|
||||
$IsPerUser = $${{ parameters.buildUserInstaller }}
|
||||
|
||||
# Build slug used to locate the artifacts
|
||||
$InstallerBuildSlug = if ($IsPerUser) { 'UserSetup' } else { 'MachineSetup' }
|
||||
|
||||
# VNext bundle folder; base name intentionally omits the VNext suffix
|
||||
$InstallerFolder = 'PowerToysSetupVNext'
|
||||
if ($IsPerUser) {
|
||||
$InstallerBasename = "PowerToysUserSetup-${{ parameters.versionNumber }}-$(BuildPlatform)"
|
||||
}
|
||||
else {
|
||||
$InstallerBasename = "PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform)"
|
||||
}
|
||||
|
||||
# Export variables for downstream steps
|
||||
Write-Host "##vso[task.setvariable variable=InstallerBuildSlug]$InstallerBuildSlug"
|
||||
Write-Host "##vso[task.setvariable variable=InstallerRelativePath]$(BuildPlatform)\$(BuildConfiguration)\$InstallerBuildSlug"
|
||||
Write-Host "##vso[task.setvariable variable=InstallerBasename]$InstallerBasename"
|
||||
Write-Host "##vso[task.setvariable variable=InstallerFolder]$InstallerFolder"
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Prepare Installer variables
|
||||
|
||||
# This dll needs to be built and signed before building the MSI.
|
||||
# The Custom Actions project contains a pre-build event that prepares the .wxs files
|
||||
# by filling them out with all our components. We pass RunBuildEvents=true to force
|
||||
# that logic to run.
|
||||
- task: VSBuild@1
|
||||
displayName: Build Shared Support DLLs
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Build PowerToysSetupCustomActionsVNext
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
/t:PowerToysSetupCustomActionsVNext;SilentFilesInUseBAFunction
|
||||
/p:RunBuildEvents=true;RestorePackagesConfig=true;CIBuild=true
|
||||
/t:PowerToysSetupCustomActionsVNext
|
||||
/p:RunBuildEvents=true;PerUser=${{parameters.buildUserInstaller}};RestorePackagesConfig=true;CIBuild=true
|
||||
-restore -graph
|
||||
/bl:$(LogOutputDirectory)\installer-actions.binlog
|
||||
/bl:$(LogOutputDirectory)\installer-$(InstallerBuildSlug)-actions.binlog
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
@@ -50,53 +70,28 @@ steps:
|
||||
maximumCpuCount: true
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- template: steps-esrp-sign-files-authenticode.yml
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: Sign Shared Support DLLs
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign PowerToysSetupCustomActionsVNext
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
folder: 'installer'
|
||||
pattern: |-
|
||||
**/PowerToysSetupCustomActionsVNext.dll
|
||||
**/SilentFilesInUseBAFunction.dll
|
||||
inputs:
|
||||
FolderPath: 'installer/PowerToysSetupCustomActionsVNext/$(InstallerRelativePath)'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
|
||||
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
|
||||
|
||||
## INSTALLER START
|
||||
#### MSI BUILDING AND SIGNING
|
||||
#
|
||||
# The MSI build contains code that reverts the .wxs files to their in-tree versions.
|
||||
# This is only supposed to happen during local builds. Since this build system is
|
||||
# supposed to run side by side--machine and then user--we do NOT want to destroy
|
||||
# the .wxs files. Therefore, we pass RunBuildEvents=false to suppress all of that
|
||||
# logic.
|
||||
#
|
||||
# We pass BuildProjectReferences=false so that it does not recompile the DLLs we just built.
|
||||
# We only pass -restore on the first one because the second run should already have all
|
||||
# of the dependencies.
|
||||
- task: VSBuild@1
|
||||
displayName: 💻 Build VNext MSI
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Build VNext MSI
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
-restore
|
||||
/t:PowerToysInstallerVNext
|
||||
/p:RunBuildEvents=false;PerUser=false;BuildProjectReferences=false;CIBuild=true
|
||||
/bl:$(LogOutputDirectory)\installer-machine-msi.binlog
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
clean: false # don't undo our hard work above by deleting the CustomActions dll
|
||||
msbuildArchitecture: x64
|
||||
maximumCpuCount: true
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: 👤 Build VNext MSI
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
/t:PowerToysInstallerVNext
|
||||
/p:RunBuildEvents=false;PerUser=true;BuildProjectReferences=false;CIBuild=true
|
||||
/bl:$(LogOutputDirectory)\installer-user-msi.binlog
|
||||
/p:RunBuildEvents=false;PerUser=${{parameters.buildUserInstaller}};BuildProjectReferences=false;CIBuild=true
|
||||
/bl:$(LogOutputDirectory)\installer-$(InstallerBuildSlug)-msi.binlog
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
@@ -105,66 +100,77 @@ steps:
|
||||
maximumCpuCount: true
|
||||
|
||||
- script: |-
|
||||
wix msi decompile $(InstallerMachineRoot)\$(InstallerMachineBasename).msi -x $(build.sourcesdirectory)\extractedMachineMsi
|
||||
wix msi decompile $(InstallerUserRoot)\$(InstallerUserBasename).msi -x $(build.sourcesdirectory)\extractedUserMsi
|
||||
dir $(build.sourcesdirectory)\extractedMachineMsi
|
||||
dir $(build.sourcesdirectory)\extractedUserMsi
|
||||
displayName: "WiX5: Extract and verify MSIs"
|
||||
wix msi decompile installer\$(InstallerFolder)\$(InstallerRelativePath)\$(InstallerBasename).msi -x $(build.sourcesdirectory)\extractedMsi
|
||||
dir $(build.sourcesdirectory)\extractedMsi
|
||||
displayName: "${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} WiX5: Extract and verify MSI"
|
||||
|
||||
# Check if deps.json files don't reference different dll versions.
|
||||
- pwsh: |-
|
||||
& '.pipelines/verifyDepsJsonLibraryVersions.ps1' -targetDir '$(build.sourcesdirectory)\extractedMachineMsi\File'
|
||||
& '.pipelines/verifyDepsJsonLibraryVersions.ps1' -targetDir '$(build.sourcesdirectory)\extractedUserMsi\File'
|
||||
displayName: Audit deps.json in MSI extracted files
|
||||
& '.pipelines/verifyDepsJsonLibraryVersions.ps1' -targetDir '$(build.sourcesdirectory)\extractedMsi\File'
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Audit deps.json in MSI extracted files
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- pwsh: |-
|
||||
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedMachineMsi\File'
|
||||
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedMachineMsi\Binary'
|
||||
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedUserMsi\File'
|
||||
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedUserMsi\Binary'
|
||||
git clean -xfd ./extractedMachineMsi ./extractedUserMsi
|
||||
displayName: Verify all binaries are signed and versioned
|
||||
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedMsi\File'
|
||||
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedMsi\Binary'
|
||||
git clean -xfd ./extractedMsi
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Verify all binaries are signed and versioned
|
||||
|
||||
- template: steps-esrp-sign-files-authenticode.yml
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: Sign VNext MSIs
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign VNext MSI
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
folder: 'installer'
|
||||
pattern: '**/PowerToys*Setup-*.msi'
|
||||
inputs:
|
||||
FolderPath: 'installer/$(InstallerFolder)/$(InstallerRelativePath)'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
|
||||
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
|
||||
|
||||
#### END MSI
|
||||
|
||||
#### BOOTSTRAP BUILDING AND SIGNING
|
||||
# We pass BuildProjectReferences=false so that it does not recompile the DLLs we just built.
|
||||
# We only pass -restore on the first one because the second run should already have all
|
||||
# of the dependencies.
|
||||
#### BUILDING AND SIGNING SilentFilesInUseBAFunction DLL
|
||||
- task: VSBuild@1
|
||||
displayName: 💻 Build VNext Bootstrapper
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Build SilentFilesInUseBAFunction
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
/t:SilentFilesInUseBAFunction
|
||||
/p:RunBuildEvents=true;PerUser=${{parameters.buildUserInstaller}};RestorePackagesConfig=true;CIBuild=true
|
||||
-restore -graph
|
||||
/bl:$(LogOutputDirectory)\installer-$(InstallerBuildSlug)-SilentFilesInUseBAFunction.binlog
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
clean: false # don't undo our hard work above by deleting the msi
|
||||
msbuildArchitecture: x64
|
||||
maximumCpuCount: true
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign SilentFilesInUseBAFunction
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
inputs:
|
||||
FolderPath: 'installer/$(BuildPlatform)/$(BuildConfiguration)'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
|
||||
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
|
||||
|
||||
#### END BUILDING AND SIGNING SilentFilesInUseBAFunction DLL
|
||||
|
||||
#### BOOTSTRAP BUILDING AND SIGNING
|
||||
- task: VSBuild@1
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Build VNext Bootstrapper
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
-restore
|
||||
/t:PowerToysBootstrapperVNext
|
||||
/p:PerUser=false;BuildProjectReferences=false;CIBuild=true
|
||||
/bl:$(LogOutputDirectory)\installer-machine-bootstrapper.binlog
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
clean: false # don't undo our hard work above by deleting the MSI nor SilentFilesInUseBAFunction
|
||||
msbuildArchitecture: x64
|
||||
maximumCpuCount: true
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: 👤 Build VNext Bootstrapper
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
/t:PowerToysBootstrapperVNext
|
||||
/p:PerUser=true;BuildProjectReferences=false;CIBuild=true
|
||||
/bl:$(LogOutputDirectory)\installer-user-bootstrapper.binlog
|
||||
/p:PerUser=${{parameters.buildUserInstaller}};CIBuild=true
|
||||
/bl:$(LogOutputDirectory)\installer-$(InstallerBuildSlug)-bootstrapper.binlog
|
||||
-restore -graph
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
@@ -175,41 +181,54 @@ steps:
|
||||
# The entirety of bundle unpacking/re-packing is unnecessary if we are not code signing it.
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- script: |-
|
||||
wix burn detach $(InstallerMachineRoot)\$(InstallerMachineBasename).exe -engine installer\machine-engine.exe
|
||||
wix burn detach $(InstallerUserRoot)\$(InstallerUserBasename).exe -engine installer\user-engine.exe
|
||||
displayName: "WiX5: Extract Engines from Bundles"
|
||||
wix burn detach installer\$(InstallerFolder)\$(InstallerRelativePath)\$(InstallerBasename).exe -engine installer\engine.exe
|
||||
displayName: "${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} WiX5: Extract Engine from Bundle"
|
||||
|
||||
- template: steps-esrp-sign-files-authenticode.yml
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: Sign WiX Engines
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign WiX Engine
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
folder: "installer"
|
||||
pattern: '*-engine.exe'
|
||||
inputs:
|
||||
FolderPath: "installer"
|
||||
Pattern: engine.exe
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: |
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationCode": "SigntoolSign",
|
||||
"Parameters": {
|
||||
"OpusName": "Microsoft",
|
||||
"OpusInfo": "http://www.microsoft.com",
|
||||
"FileDigest": "/fd \"SHA256\"",
|
||||
"PageHash": "/NPH",
|
||||
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationCode": "SigntoolVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
|
||||
- script: |-
|
||||
wix burn reattach $(InstallerMachineRoot)\$(InstallerMachineBasename).exe -engine installer\machine-engine.exe -o $(InstallerMachineRoot)\$(InstallerMachineBasename).exe
|
||||
wix burn reattach $(InstallerUserRoot)\$(InstallerUserBasename).exe -engine installer\user-engine.exe -o $(InstallerUserRoot)\$(InstallerUserBasename).exe
|
||||
displayName: "WiX5: Reattach Engines to Bundles"
|
||||
wix burn reattach installer\$(InstallerFolder)\$(InstallerRelativePath)\$(InstallerBasename).exe -engine installer\engine.exe -o installer\$(InstallerFolder)\$(InstallerRelativePath)\$(InstallerBasename).exe
|
||||
displayName: "${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} WiX5: Reattach Engine to Bundle"
|
||||
|
||||
- pwsh: |-
|
||||
& wix burn extract -oba installer\ba\m "$(InstallerMachineRoot)\$(InstallerMachineBasename).exe"
|
||||
& wix burn extract -oba installer\ba\u "$(InstallerUserRoot)\$(InstallerUserBasename).exe"
|
||||
Get-ChildItem installer\ba -Recurse -Include *.exe,*.dll | Get-AuthenticodeSignature | ForEach-Object {
|
||||
If ($_.Status -Ne "Valid") {
|
||||
Write-Error $_.StatusMessage
|
||||
} Else {
|
||||
Write-Host $_.StatusMessage
|
||||
}
|
||||
}
|
||||
& git clean -fdx installer\ba
|
||||
displayName: "WiX5: Verify Bootstrapper content is signed"
|
||||
|
||||
- template: steps-esrp-sign-files-authenticode.yml
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: Sign Final Bootstrappers
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign Final Bootstrapper
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
folder: 'installer'
|
||||
pattern: '**/PowerToys*Setup-*.exe'
|
||||
inputs:
|
||||
FolderPath: 'installer/$(InstallerFolder)/$(InstallerRelativePath)'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
|
||||
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
|
||||
|
||||
#### END BOOTSTRAP
|
||||
## END INSTALLER
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
parameters:
|
||||
- name: displayName
|
||||
type: string
|
||||
default: Sign Specific Files
|
||||
- name: folder
|
||||
type: string
|
||||
- name: pattern
|
||||
type: string
|
||||
- name: signingIdentity
|
||||
type: object
|
||||
default: {}
|
||||
|
||||
steps:
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: ${{ parameters.displayName }}
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
inputs:
|
||||
FolderPath: ${{ parameters.folder }}
|
||||
Pattern: ${{ parameters.pattern }}
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: |-
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationCode": "SigntoolSign",
|
||||
"Parameters": {
|
||||
"OpusName": "Microsoft",
|
||||
"OpusInfo": "http://www.microsoft.com",
|
||||
"FileDigest": "/fd \"SHA256\"",
|
||||
"PageHash": "/NPH",
|
||||
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationCode": "SigntoolVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
13
.vscode/launch.json
vendored
13
.vscode/launch.json
vendored
@@ -38,17 +38,6 @@
|
||||
"env": {},
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": "Run AdvancedPaste (managed, no build, ARCH configurable)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}\\${input:arch}\\Debug\\WinUI3Apps\\PowerToys.AdvancedPaste.exe",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {},
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,56 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- Hybrid CRT configuration -->
|
||||
<PropertyGroup Condition="'$(HybridCrtConfiguration)'==''">
|
||||
<HybridCrtConfiguration>$(Configuration)</HybridCrtConfiguration>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Skip Hybrid CRT for AppContainer/UWP projects as they require MultiThreadedDLL -->
|
||||
<PropertyGroup Condition="'$(AppContainerApplication)'=='true' and '$(_VC_Target_Library_Platform)'!='Desktop'">
|
||||
<HybridCrtConfiguration></HybridCrtConfiguration>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(HybridCrtConfiguration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<!-- We use MultiThreadedDebug, rather than MultiThreadedDebugDLL, to avoid DLL dependencies on VCRUNTIME140d.dll and MSVCP140d.dll. -->
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<!-- Link statically against the runtime and STL, but link dynamically against the CRT by ignoring the static CRT
|
||||
lib and instead linking against the Universal CRT DLL import library. This "hybrid" linking mechanism is
|
||||
supported according to the CRT maintainer. Dynamic linking against the CRT makes the binaries a bit smaller
|
||||
than they would otherwise be if the CRT, runtime, and STL were all statically linked in. -->
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries);libucrtd.lib</IgnoreSpecificDefaultLibraries>
|
||||
<AdditionalOptions>%(AdditionalOptions) /defaultlib:ucrtd.lib</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(HybridCrtConfiguration)'=='Release'">
|
||||
<ClCompile>
|
||||
<!-- We use MultiThreaded, rather than MultiThreadedDLL, to avoid DLL dependencies on VCRUNTIME140.dll and MSVCP140.dll. -->
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<!-- Link statically against the runtime and STL, but link dynamically against the CRT by ignoring the static CRT
|
||||
lib and instead linking against the Universal CRT DLL import library. This "hybrid" linking mechanism is
|
||||
supported according to the CRT maintainer. Dynamic linking against the CRT makes the binaries a bit smaller
|
||||
than they would otherwise be if the CRT, runtime, and STL were all statically linked in. -->
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries);libucrt.lib</IgnoreSpecificDefaultLibraries>
|
||||
<AdditionalOptions>%(AdditionalOptions) /defaultlib:ucrt.lib</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- AppContainer/UWP projects must use MultiThreadedDLL -->
|
||||
<ItemDefinitionGroup Condition="'$(AppContainerApplication)'=='true' and '$(_VC_Target_Library_Platform)'!='Desktop' And '$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(AppContainerApplication)'=='true' and '$(_VC_Target_Library_Platform)'!='Desktop' And '$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- Project configurations -->
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
@@ -123,6 +73,7 @@
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -132,6 +83,7 @@
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project>
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
|
||||
@@ -9,6 +9,7 @@
|
||||
<PackageVersion Include="AdaptiveCards.Templating" Version="2.0.5" />
|
||||
<PackageVersion Include="Microsoft.Bot.AdaptiveExpressions.Core" Version="4.23.0" />
|
||||
<PackageVersion Include="Appium.WebDriver" Version="4.4.5" />
|
||||
<PackageVersion Include="Azure.AI.OpenAI" Version="1.0.0-beta.17" />
|
||||
<PackageVersion Include="CoenM.ImageSharp.ImageHash" Version="1.3.6" />
|
||||
<PackageVersion Include="CommunityToolkit.Common" Version="8.4.0" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
@@ -34,35 +35,23 @@
|
||||
<!-- Including MessagePack to force version, since it's used by StreamJsonRpc but contains vulnerabilities. After StreamJsonRpc updates the version of MessagePack, we can upgrade StreamJsonRpc instead. -->
|
||||
<PackageVersion Include="MessagePack" Version="3.1.3" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.8" />
|
||||
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.8" />
|
||||
<PackageVersion Include="Microsoft.Windows.CppWinRT" Version="2.0.240111.5" />
|
||||
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI" Version="9.9.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="9.9.1-preview.1.25474.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.AI.Foundry.Local" Version="0.3.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.66.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.OpenAI" Version="1.66.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Amazon" Version="1.66.0-alpha" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.AzureAIInference" Version="1.66.0-beta" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Google" Version="1.66.0-alpha" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.HuggingFace" Version="1.66.0-preview" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.MistralAI" Version="1.66.0-alpha" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Ollama" Version="1.66.0-alpha" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.8" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.15.0" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.3179.45" />
|
||||
<!-- Package Microsoft.Win32.SystemEvents added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Drawing.Common but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.8" />
|
||||
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.8" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.3.183" />
|
||||
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->
|
||||
<!--
|
||||
@@ -72,8 +61,6 @@
|
||||
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4948" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.250907003" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="1.8.37" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="1.8.250907003" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
|
||||
@@ -85,7 +72,7 @@
|
||||
<PackageVersion Include="NLog" Version="5.2.8" />
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
|
||||
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
|
||||
<PackageVersion Include="OpenAI" Version="2.5.0" />
|
||||
<PackageVersion Include="OpenAI" Version="2.0.0" />
|
||||
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
|
||||
<PackageVersion Include="RtfPipe" Version="2.0.7677.4303" />
|
||||
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
|
||||
@@ -95,29 +82,28 @@
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.21.69" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.10" />
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.8" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.10" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.8" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.8" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.8" />
|
||||
<!-- Package System.Data.SqlClient added to force it as a dependency of Microsoft.Windows.Compatibility to the latest version available at this time. -->
|
||||
<PackageVersion Include="System.Data.SqlClient" Version="4.9.0" />
|
||||
<!-- Package System.Diagnostics.EventLog added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Data.OleDb but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.8" />
|
||||
<!-- Package System.Diagnostics.PerformanceCounter added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.11. -->
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.10" />
|
||||
<PackageVersion Include="System.ClientModel" Version="1.7.0" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.8" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.8" />
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="22.0.13" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.8" />
|
||||
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.10" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.8" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.8" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.8" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.8" />
|
||||
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
|
||||
<PackageVersion Include="UnitsNet" Version="5.56.0" />
|
||||
@@ -139,4 +125,4 @@
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Client" Version="2.4.17140001" />
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Contract" Version="3.0.16990001" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1495,6 +1495,7 @@ SOFTWARE.
|
||||
- AdaptiveCards.Rendering.WinUI3
|
||||
- AdaptiveCards.Templating
|
||||
- Appium.WebDriver
|
||||
- Azure.AI.OpenAI
|
||||
- CoenM.ImageSharp.ImageHash
|
||||
- CommunityToolkit.Common
|
||||
- CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock
|
||||
|
||||
@@ -26,7 +26,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runner", "src\runner\runner
|
||||
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D} = {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}
|
||||
{D940E07F-532C-4FF3-883F-790DA014F19A} = {D940E07F-532C-4FF3-883F-790DA014F19A}
|
||||
{DA425894-6E13-404F-8DCB-78584EC0557A} = {DA425894-6E13-404F-8DCB-78584EC0557A}
|
||||
{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D} = {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}
|
||||
{E364F67B-BB12-4E91-B639-355866EBCD8B} = {E364F67B-BB12-4E91-B639-355866EBCD8B}
|
||||
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} = {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}
|
||||
EndProjectSection
|
||||
@@ -51,8 +50,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{1AFB64
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common.Lib.UnitTests", "src\common\UnitTests-CommonLib\UnitTests-CommonLib.vcxproj", "{1A066C63-64B3-45F8-92FE-664E1CCE8077}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PackageIdentity", "src\PackageIdentity\PackageIdentity.vcxproj", "{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FancyZonesEditor", "src\modules\fancyzones\editor\FancyZonesEditor\FancyZonesEditor.csproj", "{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "powerrename", "powerrename", "{89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}"
|
||||
@@ -822,16 +819,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WebSea
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Shell.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.Shell.UnitTests\Microsoft.CmdPal.Ext.Shell.UnitTests.csproj", "{E816D7B4-4688-4ECB-97CC-3D8E798F3833}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CursorWrap", "src\modules\MouseUtils\CursorWrap\CursorWrap.vcxproj", "{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{3DCCD936-D085-4869-A1DE-CA6A64152C94}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LightSwitch.UITests", "src\modules\LightSwitch\Tests\LightSwitch.UITests\LightSwitch.UITests.csproj", "{F5333ED7-06D8-4AB3-953A-36D63F08CB6F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.ClipboardHistory.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.ClipboardHistory.UnitTests\Microsoft.CmdPal.Ext.ClipboardHistory.UnitTests.csproj", "{4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LanguageModelProvider", "src\common\LanguageModelProvider\LanguageModelProvider.csproj", "{45354F4F-1414-45CE-B600-51CD1209FD19}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.UI.ViewModels.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.UI.ViewModels.UnitTests\Microsoft.CmdPal.UI.ViewModels.UnitTests.csproj", "{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}"
|
||||
EndProject
|
||||
Global
|
||||
@@ -874,14 +867,6 @@ Global
|
||||
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|x64.ActiveCfg = Release|x64
|
||||
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|x64.Build.0 = Release|x64
|
||||
{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Debug|x64.Build.0 = Debug|x64
|
||||
{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Release|x64.ActiveCfg = Release|x64
|
||||
{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Release|x64.Build.0 = Release|x64
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -2992,14 +2977,6 @@ Global
|
||||
{E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Release|x64.ActiveCfg = Release|x64
|
||||
{E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Release|x64.Build.0 = Release|x64
|
||||
{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Debug|x64.Build.0 = Debug|x64
|
||||
{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Release|x64.ActiveCfg = Release|x64
|
||||
{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Release|x64.Build.0 = Release|x64
|
||||
{F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
@@ -3020,14 +2997,6 @@ Global
|
||||
{4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Release|x64.ActiveCfg = Release|x64
|
||||
{4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Release|x64.Build.0 = Release|x64
|
||||
{45354F4F-1414-45CE-B600-51CD1209FD19}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{45354F4F-1414-45CE-B600-51CD1209FD19}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{45354F4F-1414-45CE-B600-51CD1209FD19}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{45354F4F-1414-45CE-B600-51CD1209FD19}.Debug|x64.Build.0 = Debug|x64
|
||||
{45354F4F-1414-45CE-B600-51CD1209FD19}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{45354F4F-1414-45CE-B600-51CD1209FD19}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{45354F4F-1414-45CE-B600-51CD1209FD19}.Release|x64.ActiveCfg = Release|x64
|
||||
{45354F4F-1414-45CE-B600-51CD1209FD19}.Release|x64.Build.0 = Release|x64
|
||||
{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -3361,11 +3330,9 @@ Global
|
||||
{E816D7B3-4688-4ECB-97CC-3D8E798F3832} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
|
||||
{E816D7B2-4688-4ECB-97CC-3D8E798F3831} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
|
||||
{E816D7B4-4688-4ECB-97CC-3D8E798F3833} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
|
||||
{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||
{3DCCD936-D085-4869-A1DE-CA6A64152C94} = {5B201255-53C8-490B-A34F-01F05D48A477}
|
||||
{F5333ED7-06D8-4AB3-953A-36D63F08CB6F} = {3DCCD936-D085-4869-A1DE-CA6A64152C94}
|
||||
{4E0FCF69-B06B-D272-76BF-ED3A559B4EDA} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
|
||||
{45354F4F-1414-45CE-B600-51CD1209FD19} = {1AFB6476-670D-4E80-A464-657E01DFF482}
|
||||
{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
|
||||
313
README.md
313
README.md
@@ -10,11 +10,11 @@
|
||||
|
||||
<h3 align="center">
|
||||
<a href="#-installation">Installation</a>
|
||||
<span> . </span>
|
||||
<span> · </span>
|
||||
<a href="https://aka.ms/powertoys-docs">Documentation</a>
|
||||
<span> . </span>
|
||||
<span> · </span>
|
||||
<a href="https://aka.ms/powertoys-releaseblog">Blog</a>
|
||||
<span> . </span>
|
||||
<span> · </span>
|
||||
<a href="#-whats-new">Release notes</a>
|
||||
</h3>
|
||||
<br/><br/>
|
||||
@@ -27,12 +27,11 @@ Microsoft PowerToys is a collection of utilities that help you customize Windows
|
||||
| [<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) |
|
||||
| [<img src="doc/images/icons/File%20Explorer%20Preview.png" alt="File Explorer Add-ons icon" height="16"> File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [<img src="doc/images/icons/File%20Locksmith.png" alt="File Locksmith icon" height="16"> File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) | [<img src="doc/images/icons/Host%20File%20Editor.png" alt="Hosts File Editor icon" height="16"> Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) |
|
||||
| [<img src="doc/images/icons/Image%20Resizer.png" alt="Image Resizer icon" height="16"> Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [<img src="doc/images/icons/Keyboard%20Manager.png" alt="Keyboard Manager icon" height="16"> Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) | [<img src="doc/images/icons/Light Switch.png" alt="Light Switch icon" height="16"> Light Switch](https://aka.ms/PowerToysOverview_LightSwitch) |
|
||||
| [<img src="doc/images/icons/Find My Mouse.png" alt="Mouse Utilities icon" height="16"> Mouse Utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [<img src="doc/images/icons/MouseWithoutBorders.png" alt="Mouse Without Borders icon" height="16"> Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) | [<img src="doc/images/icons/NewPlus.png" alt="New+ icon" height="16"> New+](https://aka.ms/PowerToysOverview_NewPlus) |
|
||||
| [<img src="doc/images/icons/Peek.png" alt="Peek icon" height="16"> Peek](https://aka.ms/PowerToysOverview_Peek) | [<img src="doc/images/icons/PowerRename.png" alt="PowerRename icon" height="16"> PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [<img src="doc/images/icons/PowerToys%20Run.png" alt="PowerToys Run icon" height="16"> PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) |
|
||||
| [<img src="doc/images/icons/PowerAccent.png" alt="Quick Accent icon" height="16"> Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | [<img src="doc/images/icons/Registry%20Preview.png" alt="Registry Preview icon" height="16"> Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [<img src="doc/images/icons/MeasureTool.png" alt="Screen Ruler icon" height="16"> Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) |
|
||||
| [<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) | | |
|
||||
| [<img src="doc/images/icons/Image%20Resizer.png" alt="Image Resizer icon" height="16"> Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [<img src="doc/images/icons/Keyboard%20Manager.png" alt="Keyboard Manager icon" height="16"> Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) | [<img src="doc/images/icons/Find My Mouse.png" alt="Mouse Utilities icon" height="16"> Mouse Utilities](https://aka.ms/PowerToysOverview_MouseUtilities) |
|
||||
| [<img src="doc/images/icons/MouseWithoutBorders.png" alt="Mouse Without Borders icon" height="16"> Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) | [<img src="doc/images/icons/NewPlus.png" alt="New+ icon" height="16"> New+](https://aka.ms/PowerToysOverview_NewPlus) | [<img src="doc/images/icons/Peek.png" alt="Peek icon" height="16"> Peek](https://aka.ms/PowerToysOverview_Peek) |
|
||||
| [<img src="doc/images/icons/PowerRename.png" alt="PowerRename icon" height="16"> PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [<img src="doc/images/icons/PowerToys%20Run.png" alt="PowerToys Run icon" height="16"> PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [<img src="doc/images/icons/PowerAccent.png" alt="Quick Accent icon" height="16"> Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) |
|
||||
| [<img src="doc/images/icons/Registry%20Preview.png" alt="Registry Preview icon" height="16"> Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [<img src="doc/images/icons/MeasureTool.png" alt="Screen Ruler icon" height="16"> Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [<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
|
||||
@@ -48,25 +47,25 @@ Before you begin, make sure your device meets the system requirements:
|
||||
|
||||
Choose one of the installation methods below:
|
||||
|
||||
<details open>
|
||||
<details>
|
||||
<summary>Download .exe from GitHub</summary>
|
||||
|
||||
Go to the [PowerToys GitHub releases][github-release-link], 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.
|
||||
|
||||
<!-- 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.96%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.95%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.95.1/PowerToysUserSetup-0.95.1-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.95.1/PowerToysUserSetup-0.95.1-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.95.1/PowerToysSetup-0.95.1-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.95.1/PowerToysSetup-0.95.1-arm64.exe
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.95%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.94%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.94.0/PowerToysUserSetup-0.94.0-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.94.0/PowerToysUserSetup-0.94.0-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.94.0/PowerToysSetup-0.94.0-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.94.0/PowerToysSetup-0.94.0-arm64.exe
|
||||
|
||||
| Description | Filename |
|
||||
|----------------|----------|
|
||||
| Per user - x64 | [PowerToysUserSetup-0.95.1-x64.exe][ptUserX64] |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.95.1-arm64.exe][ptUserArm64] |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.95.1-x64.exe][ptMachineX64] |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.95.1-arm64.exe][ptMachineArm64] |
|
||||
| Per user - x64 | [PowerToysUserSetup-0.94.0-x64.exe][ptUserX64] |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.94.0-arm64.exe][ptUserArm64] |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.94.0-x64.exe][ptMachineX64] |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.94.0-arm64.exe][ptMachineArm64] |
|
||||
|
||||
</details>
|
||||
|
||||
@@ -106,179 +105,175 @@ There are [community driven install methods](./doc/unofficialInstallMethods.md)
|
||||
</details>
|
||||
|
||||
## ✨ What's new
|
||||
**Version 0.95 (October 2025)**
|
||||
**Version 0.94 (September 2025)**
|
||||
|
||||
For an in-depth look at the latest changes, visit the [Windows Command Line blog](https://aka.ms/powertoys-releaseblog).
|
||||
|
||||
**✨ Highlights**
|
||||
- **NEW:** The **Light Switch** utility in PowerToys allows you to automatically switch between light and dark themes in Windows based on the time of day.
|
||||
- Command Palette delivered major search performance gains (new fuzzy matcher and smarter fallbacks) improving relevance and speed.
|
||||
- Peek can now be activated using just the Spacebar!
|
||||
- Find My Mouse added transparent spotlight with independent backdrop opacity, boosting focus and accessibility.
|
||||
- Settings now lets you delete shortcuts entirely and ignore conflicts.
|
||||
- Mouse Pointer Crosshairs gained orientation options (vertical / horizontal / both) for customizable accessibility. Thanks [@mikehall-ms](https://github.com/mikehall-ms)!
|
||||
- PowerRename fixed enumeration counter skipping ensuring reliable batch renames. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- ZoomIt restored legacy draw and snipping behaviors, and fixed recording issues, improving reliability. Thanks [@chakrik73](https://github.com/chakrik73)!
|
||||
|
||||
- PowerToys Settings added a Settings search with fuzzy matching, suggestions, a results page, and UX polish to make finding options faster.
|
||||
- A comprehensive hotkey conflict detection system was introduced in Settings to surface and help resolve conflicting shortcuts. Note that the default hotkey settings (Win+Ctrl+Shift+T, Win+Ctrl+V, Win+Ctrl+T, Win+Shift+T) may overlap with existing Windows system shortcuts. This is expected. You can resolve the conflict by assigning different hotkeys.
|
||||
- Mouse Utilities added a “Gliding cursor” accessibility feature to Mouse Pointer Crosshairs for single‑button cursor movement and clicking. Thanks [@mikehall-ms](https://github.com/mikehall-ms)!
|
||||
- The installer was upgraded to WiX 5 after WiX 3 reached end-of-life; this move improved installer security, reliability, and community support.
|
||||
- Tons of bug fixes and improvements for Command Palette, including visual updates and new support for filters on ListPages (handy for extension developers).
|
||||
- Hosts Editor now has a “No leading spaces” option so active host entries can start at column 0 even if others are disabled. Thanks [@mohammed-saalim](https://github.com/mohammed-saalim)!
|
||||
- Context menu registration was moved from the installer to runtime to avoid loading disabled modules (runtime registrations).
|
||||
- Quick Accent now supports Maltese, and frequently used accents appear first (and are remembered across sessions). Thanks [@rovercoder](https://github.com/rovercoder)! [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
|
||||
### Always On Top
|
||||
|
||||
- Fixed the border hover cursor so it shows the arrow instead of the wait cursor. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
|
||||
### Command Palette
|
||||
- Applied conditional margin for icon-only tags to tighten layout. Thanks [@samrueby](https://github.com/samrueby)
|
||||
- Improved the reliability of accessing Command Palette settings through PowerToys Settings and executing other x-cmdpal:// protocol commands. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Enabled AOT by default for improved performance while simplifying publish configs.
|
||||
- Replaced service state color dots with play/pause/stop icons for enhanced accessibility. Thanks [@samrueby](https://github.com/samrueby)
|
||||
- Fixed filter dropdown sync and crash by binding SelectedValue and raising UI-thread notifications. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Ensured long links wrap correctly in details view.
|
||||
- Removed animation and enforced minimum width on filter dropdown for clarity. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Restored focus to More button after ESC closes context menu, improving keyboard flow. Thanks [@chatasweetie](https://github.com/chatasweetie)
|
||||
- Marked main and toast windows as tool windows to keep them out of Alt+Tab while preserving style. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Fixed AOT template and theming issues for filter separators. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Introduced grid layouts (small, medium, gallery) for richer page presentation.
|
||||
- Materialized result lists to avoid rescoring overhead.
|
||||
- Disabled problematic selection TextToSuggest behind environment flag.
|
||||
- Major search performance improvements (new fuzzy matcher, smarter fallbacks, fewer exceptions).
|
||||
- Added context menu "Show Details" command when details pane is hidden.
|
||||
- Reduced window flicker by avoiding unnecessary cloaking. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Restored EmptyContent rendering for blank states. Thanks [@DevLGuilherme](https://github.com/DevLGuilherme)
|
||||
- Saved new state even if prior app state file was corrupt (better resilience). Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Migrated settings window to WinUI TitleBar control. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Prevented crash on duplicate keybindings and simplified matching. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Hotkeys now always respect the “Ignore shortcut in fullscreen” setting. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Hid search box on content pages, improving focus and accessibility, and added Home title. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Blocked Ctrl+I from inserting stray tabs in search box.
|
||||
- Logged HRESULT codes in error logs for deeper diagnostics. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Advanced font and emoji icon classification and alignment improvements. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Ensured that fallback command icons are visible on the extension settings page. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Fixed breadcrumb margin misalignment (visual polish). Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Truncated overly long command labels with ellipsis to prevent overflow.
|
||||
- Added a setting to configure the page transition animation.
|
||||
- Collection of small improvements and nits for Run Commands.
|
||||
- Improved bookmarks performance and experience. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Added Ctrl+O shortcut in Clipboard History to open links directly.
|
||||
- Resolved conflict with external software that blocked Command Palette from hiding.
|
||||
- Updated context menu items to reflect name and icon changes, and ensured application icons are displayed correctly. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Added Alt+Home shortcut to return immediately to the Command Palette home page. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Fixed a crash when displaying code blocks in markdown on detail or content pages. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Fixed an issue where the search bar icon and title were not updated when rapidly switching pages. Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Improved the appearance of the search box in the context menu.
|
||||
|
||||
- Applied single-click activation only to pointer input; keyboard always activates immediately. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Let context menus open at the cursor by removing window-bound constraints. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Made error messages clearer with timestamps, HRESULTs, and full details for easier diagnosis. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Prevented crashes and improved robustness when updating providers without commands. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Ensured the Settings window reliably comes to the front when opened. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Replaced the Clipboard History icon with a colorful Fluent icon. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Hardened ContentIcon to avoid duplicate parenting and improve diagnostics. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Standardized null checks using C# pattern matching for safer behavior.
|
||||
- Improved accessibility by focusing the activation shortcut dialog and making text reachable. Thanks [@chatasweetie](https://github.com/chatasweetie)!
|
||||
- Moved the extension SDK to a stable Windows SDK and cleaned up message namespaces.
|
||||
- Added path shortcuts: ~ to home, and / or \\ to system root, plus UNC support. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed a race in cancellation handling to avoid InvalidOperationException. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Aligned separator styling with WinUI 3 for consistent visuals. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Added ARM64 PDBs to the Extensions SDK NuGet for better debugging.
|
||||
- Added single-select filters to DynamicListPage and updated Windows Services sample.
|
||||
- Updated main page placeholder text to better describe what can be searched. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Removed explicit WinAppSDK/WebView2 dependencies from toolkit and API. Thanks [@rluengen](https://github.com/rluengen)!
|
||||
- Added a local keyboard hook to handle the GoBack key reliably. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Propagated alias changes safely and resolved conflicts across view models.
|
||||
- Allowed providers to override Dispose with a virtual method.
|
||||
- Fixed memory leaks by cleaning up removed or cancelled list items.
|
||||
- Sorted DateTime extension results by relevance for better usability.
|
||||
- Reduced search text "jiggling" by avoiding redundant change notifications.
|
||||
- Centralized automation notifications in a UIHelper for better accessibility. Thanks [@chatasweetie](https://github.com/chatasweetie)!
|
||||
- Preserved Adaptive Card action types during trimming via DynamicDependency.
|
||||
- Added an acrylic backdrop and refined styling to the context menu. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Prevented disposed pages and Settings windows from handling stale messages. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Made the extension API easier to evolve without breaking clients.
|
||||
- Added "evil" sample pages to help reproduce tricky bugs.
|
||||
- Fixed WinGet trim-safety issues by replacing LINQ with manual iteration.
|
||||
- Cancelled stale list fetches to avoid older results overwriting newer ones in CmdPal.
|
||||
|
||||
### Command Palette Extensions
|
||||
- Replaced localized WebSearch setting keys with stable literals and numeric history count. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Enabled advanced markdown tables and emphasis extensions. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Added setting to choose Clipboard History primary action (Paste vs Copy). Thanks [@jiripolasek](https://github.com/jiripolasek)
|
||||
- Added actionable empty-state hints for File Search (search PC / open indexing settings). Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Ensured all WinGet extension assets copy reliably to output. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Improved Run command line parsing for paths with spaces; sped up related tests.
|
||||
- Updated WebSearch extension icon set for enhanced clarity and contrast. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Added Terminal profile sort order setting including MRU tracking. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Added Uninstall Application command (UWP direct, Win32 via Settings). Thanks [@mKpwnz](https://github.com/mKpwnz)!
|
||||
- Deferred WinGet details loading and added timing logs.
|
||||
- Removed LINQ from All Apps extension for performance.
|
||||
- Added standardized key chord system + shortcuts to File Search commands. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Added Terminal channel filter & remembered selection option. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Enabled loading local/data/app images in markdown with sizing hints. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Added external extension reload via x-cmdpal://reload (configurable). Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Instant WebSearch history updates with in-memory store & events. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Added keep-after-paste option and safe delete with confirmation for Clipboard History. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
### Command Palette extensions
|
||||
|
||||
### Environment Variables
|
||||
- Replaced custom window chrome with WinUI TitleBar for cleaner, maintainable Environment Variables UI.
|
||||
|
||||
### File Locksmith
|
||||
- Adopted WinUI TitleBar to simplify window chrome while preserving appearance.
|
||||
|
||||
### Find My Mouse
|
||||
- Added transparent spotlight support with separate backdrop opacity; migrated to Windows App SDK composition APIs.
|
||||
- Improved empty states and ranking logic for multiple extensions. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added app icons to the All Apps "Run" context command when available.
|
||||
- Restored missing builtin icons by standardizing extension dependencies.
|
||||
- Unblocked local deployment by adding WinAppSDK to two sample extensions.
|
||||
|
||||
### Hosts File Editor
|
||||
- Migrated to native WinUI TitleBar for cleaner, maintainable window chrome.
|
||||
|
||||
### Light Switch
|
||||
- Introduced as a brand-new PowerToy module.
|
||||
- Automatically switches between light and dark themes.
|
||||
- Supports time-based scheduling or location-based sunrise/sunset switching.
|
||||
- Supports using a keyboard shortcut to force a change.
|
||||
- Supports filtering changes for Apps and/or System Theme.
|
||||
- Added a "No leading spaces" option so active hosts entries can start at column 0 even when others are disabled. Thanks [@mohammed-saalim](https://github.com/mohammed-saalim)!
|
||||
|
||||
### Mouse Pointer Crosshairs
|
||||
- Added Esc key to cancel active gliding cursor sequence. Thanks [@mikehall-ms](https://github.com/mikehall-ms)!
|
||||
- Added orientation option (vertical / horizontal / both) for crosshairs customization. Thanks [@mikehall-ms](https://github.com/mikehall-ms)!
|
||||
### Image Resizer
|
||||
|
||||
- Fixed Image Resizer localization by installing satellite resources under the WinUI 3 apps culture path.
|
||||
|
||||
### Mouse Utilities
|
||||
|
||||
- Introduced "Gliding cursor" to control the pointer and click with a single hotkey for better accessibility. Thanks [@mikehall-ms](https://github.com/mikehall-ms)!
|
||||
|
||||
### Mouse Without Borders
|
||||
- Continued Common class refactor (part 5/7) by extracting clipboard and init/cleanup logic into focused classes. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
|
||||
- Fix connection failures caused by conflicting MachineId across machines. Thanks [@noraa-junker](https://github.com/noraa-junker) for troubleshooting!
|
||||
- Blocked Easy Mouse from switching machines during fullscreen apps, with an allow-list for exceptions. Thanks [@dot-tb](https://github.com/dot-tb)!
|
||||
|
||||
### Peek
|
||||
- Added the option to activate Peek with just the Spacebar.
|
||||
|
||||
- Added Visual Studio shared project file types to XML preview and fixed bgcode handler registration. Thanks [@rezanid](https://github.com/rezanid)!
|
||||
- Fixes bgcode preview handler registration and events for reliable previews. Thanks [@pedrolamas](https://github.com/pedrolamas)!
|
||||
|
||||
### PowerRename
|
||||
- Fixed enumeration counter skipping when regex replacement equals original filename (counters now advance reliably). Thanks [@daverayment](https://github.com/daverayment)!
|
||||
|
||||
- Changed the Explorer accelerator key to PowErRename to avoid clashing with the New menu. Thanks [@aaron-ni](https://github.com/aaron-ni)!
|
||||
|
||||
### Quick Accent
|
||||
- Expanded Welsh layout with acute, grave, and dieresis variants for vowels (consistent ordering). Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
|
||||
### Registry Preview
|
||||
- Migrated to native TitleBar and AppWindow APIs for cleaner window chrome.
|
||||
|
||||
### Screen Ruler
|
||||
- Fixed ARM64 crash by aligning cursor position structure to 8-byte boundary.
|
||||
- Remembered character usage across sessions so frequently used accents appear first. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Added Maltese language support with specific characters and the Euro symbol. Thanks [@rovercoder](https://github.com/rovercoder)!
|
||||
- Reduced GPU usage issues by making the window Topmost only when the picker is visible. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
|
||||
### Settings
|
||||
- Added ability to ignore specific hotkey conflicts to reduce noise.
|
||||
- Stopped creating backup directory during dry-run status checks (cleaner first-run).
|
||||
- Standardized casing and localization for ZoomIt and modules header.
|
||||
- Improved search results page accessibility and conditional module grouping.
|
||||
|
||||
### ZoomIt
|
||||
- Updated resource file to reflect standalone v9.01 and current copyright year. Thanks [@foxmsft](https://github.com/foxmsft)!
|
||||
- Restored legacy draw/snipping behaviors and fixed recording race conditions. Thanks [@chakrik73](https://github.com/chakrik73)!
|
||||
- Added smooth image option for improved zoom quality using GDI+ for static zoom and Magnifier API for live zoom. Thanks [@markrussinovich](https://github.com/markrussinovich)!
|
||||
- Added telemetry to track usage of the new shortcut conflict detection workflow.
|
||||
- Moved the shutdown action from the title bar to a footer menu item with confirmation. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Implemented comprehensive hotkey conflict detection with a dedicated resolution dialog.
|
||||
- Added branded visuals for Office and Copilot keys in the KeyVisual control.
|
||||
- Introduced Settings search with fuzzy matching and navigation to specific controls.
|
||||
- Corrected Spanish localization so product names like Awake remain in English across Settings and OOBE.
|
||||
- Simplified the Advanced Paste description in Settings for quicker reading and consistent capitalization. Thanks [@OldUser101](https://github.com/OldUser101)!
|
||||
- Localized conflict messages in the conflict window and dialog.
|
||||
|
||||
### Documentation
|
||||
- New Microsoft Learn documentation for the Light Switch module.
|
||||
- New dev docs for the Light Switch module.
|
||||
### Installer
|
||||
|
||||
### Development (Area-Build & Area-Tests)
|
||||
- Allowed debug launches to continue when modules fail to load, speeding developer iteration.
|
||||
- Fixed spell checker dictionary entry (advapi) to eliminate false error.
|
||||
- Added VS Code development guide and launch configs to streamline cross-editor workflows.
|
||||
- Upgraded Windows App SDK and related dependencies to 1.8 for newer platform features.
|
||||
- Rewrote YAML comment to resolve new spell checker forbidden pattern. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Corrected solution structure by returning misplaced Common project, reducing build confusion.
|
||||
- Modernized build scripts with shared helpers and VS environment autodetection for simpler CLI builds.
|
||||
- Standardized build scripts and platform detection to improve reliability and reuse.
|
||||
- Added missing Command Palette version bump to align module release cadence.
|
||||
- Added EXECUTEDEFAULT term to dictionary to prevent regression build failures. Thanks [@jiripolasek](https://github.com/jiripolasek)!
|
||||
- Introduced nightly pre-warm pipeline and configurable MSBuild cache mode to improve CI performance.
|
||||
- Resolved CI forbidden pattern spelling complaint to keep pipelines green.
|
||||
- Added AI contributor instruction set to clarify code area expectations.
|
||||
- Added accessibility IDs to settings and FancyZones toggles, stabilizing UI tests.
|
||||
- Added automatic log collection on UI test failures to speed root cause analysis.
|
||||
- Stabilized Mouse Utils tests by switching to AccessibilityId selectors.
|
||||
- Added Screen Ruler UI test coverage to validate core measurement workflows.
|
||||
- Upgraded the installer to WiX 5 with silent "Files in Use" handling for smoother winget installs.
|
||||
- Switched Win10 context menu modules to runtime registration and added cleanup on uninstall to avoid stale entries.
|
||||
|
||||
## 🛣️ Roadmap
|
||||
We are planning some nice new features and improvements for the next releases – a revamped Keyboard Manager UI, custom endpoint and local model support for Advanced Paste, Command Palette improvements and a brand-new Shortcut Guide experience! Stay tuned for [v0.96][github-next-release-work]!
|
||||
### Documentation
|
||||
|
||||
- Adds docs for building the installer locally and testing winget installs.
|
||||
- Fixed a broken style guide link in developer documentation. Thanks [@denizmaral](https://github.com/denizmaral)!
|
||||
|
||||
### Development
|
||||
|
||||
- Excluded test and coverage DLLs from BinSkim scans to cut false positives and speed up security analysis.
|
||||
- Simplified NOTICE maintenance by removing version numbers and filtering out Microsoft/System packages.
|
||||
- Improved NuGet dependency validation to prevent package downgrades and catch issues during restore.
|
||||
- Updated UTF.Unknown to a modern version to improve compatibility without breaking changes. Thanks [@304NotModified](https://github.com/304NotModified)!
|
||||
- Refreshed package catalog in CI before installing dependencies to prevent Linux workflow failures.
|
||||
- Refactored CmdPal tests with dependency injection and added coverage for queries and settings.
|
||||
- Added unit tests to verify Close on Enter swaps Copy/Save as expected. Thanks [@mohammed-saalim](https://github.com/mohammed-saalim)!
|
||||
- Added accessibility IDs to CmdPal UI for stable UI tests.
|
||||
- Rewrote system command tests with a new test base and cleaner patterns.
|
||||
- Added unit tests for WebSearch and Shell extensions with mockable settings.
|
||||
- Added unit tests and abstractions for Apps and Bookmarks extensions.
|
||||
- Cleans up AI-generated tests; adds meaningful query tests across extensions.
|
||||
- Removed the obsolete debug dialog from Settings for a smoother developer loop.
|
||||
|
||||
## 🛣️ Roadmap
|
||||
|
||||
For [v0.95][github-next-release-work], we'll work on the items below:
|
||||
|
||||
- Continued Command Palette polish
|
||||
- Working on Shortcut Guide v2 (Thanks [@noraa-junker](https://github.com/noraa-junker)!)
|
||||
- Upgrading Keyboard Manager's editor UI
|
||||
- UI tweaking utility with day/night theme switcher
|
||||
- DSC v3 support for top utilities
|
||||
- New UI automation tests
|
||||
- Stability, bug fixes
|
||||
|
||||
## ❤️ 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.
|
||||
|
||||
## 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).
|
||||
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.
|
||||
|
||||
[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
|
||||
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.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
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
|
||||
[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=
|
||||
[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
|
||||
|
||||
87
installer/PowerToysSetup/generateDscResourcesWxs.ps1
Normal file
87
installer/PowerToysSetup/generateDscResourcesWxs.ps1
Normal file
@@ -0,0 +1,87 @@
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string]$dscWxsFile,
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string]$Platform,
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string]$Configuration
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$buildOutputDir = Join-Path $scriptDir "..\..\$Platform\$Configuration"
|
||||
|
||||
if (-not (Test-Path $buildOutputDir)) {
|
||||
Write-Error "Build output directory not found: '$buildOutputDir'"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$dscFiles = Get-ChildItem -Path $buildOutputDir -Filter "microsoft.powertoys.*.settings.dsc.resource.json" -File
|
||||
|
||||
if (-not $dscFiles) {
|
||||
Write-Warning "No DSC manifest files found in '$buildOutputDir'"
|
||||
$wxsContent = @"
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<?include `$(sys.CURRENTDIR)\Common.wxi?>
|
||||
<Fragment>
|
||||
<ComponentGroup Id="DscResourcesComponentGroup">
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
"@
|
||||
Set-Content -Path $dscWxsFile -Value $wxsContent
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host "Found $($dscFiles.Count) DSC manifest file(s)"
|
||||
|
||||
$wxsContent = @"
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<?include `$(sys.CURRENTDIR)\Common.wxi?>
|
||||
<Fragment>
|
||||
<DirectoryRef Id="DSCModulesReferenceFolder">
|
||||
"@
|
||||
|
||||
$componentRefs = @()
|
||||
foreach ($file in $dscFiles) {
|
||||
$componentId = "DscResource_" + ($file.BaseName -replace '[^A-Za-z0-9_]', '_')
|
||||
$fileId = $componentId + "_File"
|
||||
$guid = [System.Guid]::NewGuid().ToString().ToUpper()
|
||||
$componentRefs += $componentId
|
||||
|
||||
$wxsContent += @"
|
||||
|
||||
<Component Id="$componentId" Guid="{$guid}">
|
||||
<RegistryKey Root="`$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="$componentId" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Id="$fileId" Source="`$(var.BinDir)$($file.Name)" Vital="no"/>
|
||||
</Component>
|
||||
"@
|
||||
}
|
||||
|
||||
$wxsContent += @"
|
||||
|
||||
</DirectoryRef>
|
||||
</Fragment>
|
||||
<Fragment>
|
||||
<ComponentGroup Id="DscResourcesComponentGroup">
|
||||
"@
|
||||
|
||||
foreach ($componentId in $componentRefs) {
|
||||
$wxsContent += @"
|
||||
|
||||
<ComponentRef Id="$componentId"/>
|
||||
"@
|
||||
}
|
||||
|
||||
$wxsContent += @"
|
||||
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
"@
|
||||
|
||||
Set-Content -Path $dscWxsFile -Value $wxsContent
|
||||
Write-Host "Generated DSC resources WiX fragment: '$dscWxsFile'"
|
||||
@@ -594,216 +594,6 @@ LExit:
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall InstallPackageIdentityMSIXCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
LPWSTR customActionData = nullptr;
|
||||
std::wstring installFolderPath;
|
||||
std::wstring installScope;
|
||||
std::wstring msixPath;
|
||||
std::wstring data;
|
||||
size_t delimiterPos;
|
||||
bool isMachineLevel = false;
|
||||
|
||||
hr = WcaInitialize(hInstall, "InstallPackageIdentityMSIXCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
hr = WcaGetProperty(L"CustomActionData", &customActionData);
|
||||
ExitOnFailure(hr, "Failed to get CustomActionData property");
|
||||
|
||||
// Parse CustomActionData: "[INSTALLFOLDER];[InstallScope]"
|
||||
data = customActionData;
|
||||
delimiterPos = data.find(L';');
|
||||
installFolderPath = data.substr(0, delimiterPos);
|
||||
installScope = data.substr(delimiterPos + 1);
|
||||
|
||||
// Check if this is a machine-level installation
|
||||
if (installScope == L"perMachine")
|
||||
{
|
||||
isMachineLevel = true;
|
||||
}
|
||||
|
||||
Logger::info(L"Installing PackageIdentity MSIX - perUser: {}", !isMachineLevel);
|
||||
|
||||
// Construct path to PackageIdentity MSIX
|
||||
msixPath = installFolderPath;
|
||||
msixPath += L"PowerToysSparse.msix";
|
||||
|
||||
if (std::filesystem::exists(msixPath))
|
||||
{
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
std::wstring externalLocation = installFolderPath; // External content location (PowerToys install folder)
|
||||
Uri externalUri{ externalLocation }; // External location URI for sparse package content
|
||||
Uri packageUri{ msixPath }; // The MSIX file URI
|
||||
|
||||
PackageManager packageManager;
|
||||
|
||||
if (isMachineLevel)
|
||||
{
|
||||
// Machine-level installation
|
||||
|
||||
StagePackageOptions stageOptions;
|
||||
stageOptions.ExternalLocationUri(externalUri);
|
||||
|
||||
auto stageResult = packageManager.StagePackageByUriAsync(packageUri, stageOptions).get();
|
||||
|
||||
uint32_t stageErrorCode = static_cast<uint32_t>(stageResult.ExtendedErrorCode());
|
||||
if (stageErrorCode == 0)
|
||||
{
|
||||
std::wstring packageFamilyName = L"Microsoft.PowerToys.SparseApp_8wekyb3d8bbwe";
|
||||
|
||||
try
|
||||
{
|
||||
auto provisionResult = packageManager.ProvisionPackageForAllUsersAsync(packageFamilyName).get();
|
||||
uint32_t provisionErrorCode = static_cast<uint32_t>(provisionResult.ExtendedErrorCode());
|
||||
|
||||
if (provisionErrorCode != 0)
|
||||
{
|
||||
Logger::error(L"Machine-level provisioning failed: 0x{:08X}", provisionErrorCode);
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& ex)
|
||||
{
|
||||
Logger::error(L"Provisioning exception: HRESULT 0x{:08X}", static_cast<uint32_t>(ex.code()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::error(L"Package staging failed: 0x{:08X}", stageErrorCode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPackageOptions addOptions;
|
||||
addOptions.ExternalLocationUri(externalUri);
|
||||
|
||||
auto addResult = packageManager.AddPackageByUriAsync(packageUri, addOptions).get();
|
||||
|
||||
if (!addResult.IsRegistered())
|
||||
{
|
||||
uint32_t errorCode = static_cast<uint32_t>(addResult.ExtendedErrorCode());
|
||||
Logger::error(L"Per-user installation failed: 0x{:08X}", errorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Logger::error(L"PackageIdentity MSIX installation failed - Exception: {}",
|
||||
winrt::to_hstring(ex.what()).c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::error(L"PackageIdentity MSIX not found: " + msixPath);
|
||||
}
|
||||
|
||||
LExit:
|
||||
ReleaseStr(customActionData);
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall UninstallPackageIdentityMSIXCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
|
||||
LPWSTR installScope = nullptr;
|
||||
bool isMachineLevel = false;
|
||||
|
||||
PackageManager pm;
|
||||
|
||||
hr = WcaInitialize(hInstall, "UninstallPackageIdentityMSIXCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
// Check if this was a machine-level installation
|
||||
hr = WcaGetProperty(L"InstallScope", &installScope);
|
||||
if (SUCCEEDED(hr) && installScope && wcscmp(installScope, L"perMachine") == 0)
|
||||
{
|
||||
isMachineLevel = true;
|
||||
}
|
||||
|
||||
Logger::info(L"Uninstalling PackageIdentity MSIX - perUser: {}", !isMachineLevel);
|
||||
|
||||
try
|
||||
{
|
||||
std::wstring packageFamilyName = L"Microsoft.PowerToys.SparseApp_8wekyb3d8bbwe";
|
||||
|
||||
if (isMachineLevel)
|
||||
{
|
||||
// Machine-level uninstallation: deprovision + remove for all users
|
||||
|
||||
// First deprovision the package
|
||||
try
|
||||
{
|
||||
auto deprovisionResult = pm.DeprovisionPackageForAllUsersAsync(packageFamilyName).get();
|
||||
if (deprovisionResult.IsRegistered())
|
||||
{
|
||||
Logger::warn(L"Machine-level deprovisioning completed with warnings");
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& ex)
|
||||
{
|
||||
Logger::warn(L"Machine-level deprovisioning failed: HRESULT 0x{:08X}", static_cast<uint32_t>(ex.code()));
|
||||
}
|
||||
|
||||
// Then remove packages for all users
|
||||
auto packages = pm.FindPackagesForUserWithPackageTypes({}, packageFamilyName, PackageTypes::Main);
|
||||
for (const auto& package : packages)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto machineResult = pm.RemovePackageAsync(package.Id().FullName(), RemovalOptions::RemoveForAllUsers).get();
|
||||
if (machineResult.IsRegistered())
|
||||
{
|
||||
uint32_t errorCode = static_cast<uint32_t>(machineResult.ExtendedErrorCode());
|
||||
Logger::error(L"Machine-level removal failed: 0x{:08X} - {}", errorCode, machineResult.ErrorText());
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& ex)
|
||||
{
|
||||
Logger::error(L"Machine-level removal exception: HRESULT 0x{:08X}", static_cast<uint32_t>(ex.code()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Per-user uninstallation: standard removal
|
||||
|
||||
auto packages = pm.FindPackagesForUserWithPackageTypes({}, packageFamilyName, PackageTypes::Main);
|
||||
for (const auto& package : packages)
|
||||
{
|
||||
auto userResult = pm.RemovePackageAsync(package.Id().FullName()).get();
|
||||
if (userResult.IsRegistered())
|
||||
{
|
||||
uint32_t errorCode = static_cast<uint32_t>(userResult.ExtendedErrorCode());
|
||||
Logger::error(L"Per-user removal failed: 0x{:08X} - {}", errorCode, userResult.ErrorText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
std::string errorMsg = "Failed to uninstall PackageIdentity MSIX: " + std::string(ex.what());
|
||||
Logger::error(errorMsg);
|
||||
// Don't fail the entire uninstallation if PackageIdentity fails
|
||||
Logger::warn(L"Continuing uninstallation despite PackageIdentity MSIX error");
|
||||
}
|
||||
|
||||
LExit:
|
||||
ReleaseStr(installScope);
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall RemoveWindowsServiceByName(std::wstring serviceName)
|
||||
{
|
||||
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
||||
|
||||
@@ -33,5 +33,3 @@ EXPORTS
|
||||
CleanPowerRenameRuntimeRegistryCA
|
||||
CleanNewPlusRuntimeRegistryCA
|
||||
SetBundleInstallLocationCA
|
||||
InstallPackageIdentityMSIXCA
|
||||
UninstallPackageIdentityMSIXCA
|
||||
|
||||
@@ -34,8 +34,13 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>$(Platform)\$(Configuration)\SetupShared\</OutDir>
|
||||
<IntDir>$(SolutionDir)$(ProjectName)\$(Platform)\$(Configuration)\SetupShared\obj\</IntDir>
|
||||
<OutDir Condition=" '$(PerUser)' != 'true' ">$(Platform)\$(Configuration)\MachineSetup\</OutDir>
|
||||
<OutDir Condition=" '$(PerUser)' == 'true' ">$(Platform)\$(Configuration)\UserSetup\</OutDir>
|
||||
<IntDir Condition=" '$(PerUser)' != 'true' ">$(SolutionDir)$(ProjectName)\$(Platform)\$(Configuration)\MachineSetup\obj\</IntDir>
|
||||
<IntDir Condition=" '$(PerUser)' == 'true' ">$(SolutionDir)$(ProjectName)\$(Platform)\$(Configuration)\UserSetup\obj\</IntDir>
|
||||
<!-- The CMD script below checks this value, and it is **CASE SENSITIVE** -->
|
||||
<NormalizedPerUserValue>false</NormalizedPerUserValue>
|
||||
<NormalizedPerUserValue Condition=" '$(PerUser)' == 'true' ">true</NormalizedPerUserValue>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
@@ -54,7 +59,6 @@
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\CmdPal.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\CmdPal.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\ColorPicker.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\ColorPicker.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\Core.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\Core.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\DscResources.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\DscResources.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\EnvironmentVariables.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\EnvironmentVariables.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\FileExplorerPreview.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\FileExplorerPreview.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\FileLocksmith.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\FileLocksmith.wxs.bk""""
|
||||
@@ -76,7 +80,8 @@
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\WinAppSDK.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\WinAppSDK.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\WinUI3Applications.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\WinUI3Applications.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\Workspaces.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\Workspaces.wxs.bk""""
|
||||
call powershell.exe -NonInteractive -executionpolicy Unrestricted -File ..\PowerToysSetupVNext\generateAllFileComponents.ps1 -platform $(Platform)
|
||||
if not "$(NormalizedPerUserValue)" == "true" call powershell.exe -NonInteractive -executionpolicy Unrestricted -File ..\PowerToysSetupVNext\generateAllFileComponents.ps1 -platform $(Platform)
|
||||
if "$(NormalizedPerUserValue)" == "true" call powershell.exe -NonInteractive -executionpolicy Unrestricted -File ..\PowerToysSetupVNext\generateAllFileComponents.ps1 -platform $(Platform) -installscopeperuser $(NormalizedPerUserValue)
|
||||
</Command>
|
||||
<Message>Backing up original files and populating .NET and WPF Runtime dependencies for WiX3 based installer</Message>
|
||||
</PreBuildEvent>
|
||||
@@ -110,6 +115,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -122,6 +128,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -174,4 +181,4 @@
|
||||
<Error Condition="!Exists('..\packages\WixToolset.DUtil.5.0.2\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\WixToolset.DUtil.5.0.2\build\WixToolset.DUtil.props'))" />
|
||||
<Error Condition="!Exists('..\packages\WixToolset.WcaUtil.5.0.2\build\WixToolset.WcaUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\WixToolset.WcaUtil.5.0.2\build\WixToolset.WcaUtil.props'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -4,13 +4,6 @@
|
||||
<Fragment>
|
||||
<DirectoryRef Id="WinUI3AppsInstallFolder">
|
||||
<Directory Id="CmdPalInstallFolder" Name="CmdPal">
|
||||
<Directory Id="CmdPalDepsInstallFolder" Name="Dependencies">
|
||||
<?if $(sys.BUILDARCH) = x64 ?>
|
||||
<Directory Id="CmdPalDepsX64InstallFolder" Name="x64" />
|
||||
<?else?>
|
||||
<Directory Id="CmdPalDepsArm64InstallFolder" Name="arm64" />
|
||||
<?endif?>
|
||||
</Directory>
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="CmdPalInstallFolder" FileSource="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion)_Test">
|
||||
@@ -25,40 +18,14 @@
|
||||
<?endif?>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<?if $(sys.BUILDARCH) = x64 ?>
|
||||
<DirectoryRef Id="CmdPalDepsX64InstallFolder" FileSource="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion)_Test\Dependencies\x64">
|
||||
<Component Id="Module_CmdPal_Deps" Guid="C2790FC4-0665-4462-947A-D942A2AABFF0" Bitness="always64">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="Module_CmdPal_Deps" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<File Id="Microsoft.VCLibs.x64.14.00.Desktop.appx" Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion)_Test\Dependencies\x64\Microsoft.VCLibs.x64.14.00.Desktop.appx" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<?else?>
|
||||
<DirectoryRef Id="CmdPalDepsArm64InstallFolder" FileSource="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion)_Test\Dependencies\arm64">
|
||||
<Component Id="Module_CmdPal_Deps" Guid="C2790FC4-0665-4462-947A-D942A2AABFF0" Bitness="always64">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="Module_CmdPal_Deps" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<File Id="Microsoft.VCLibs.ARM64.14.00.Desktop.appx" Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion)_Test\Dependencies\arm64\Microsoft.VCLibs.ARM64.14.00.Desktop.appx" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<?endif?>
|
||||
<ComponentGroup Id="CmdPalComponentGroup">
|
||||
<Component Id="RemoveCmdPalFolder" Guid="2DF90C08-CC75-4245-A14E-B82904636C53" Directory="INSTALLFOLDER">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="RemoveCmdPalFolder" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveCmdPalInstallDirFolder" Directory="CmdPalInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveCmdPalDepsInstallDirFolder" Directory="CmdPalDepsInstallFolder" On="uninstall" />
|
||||
<?if $(sys.BUILDARCH) = x64 ?>
|
||||
<RemoveFolder Id="RemoveCmdPalDepsX64InstallDirFolder" Directory="CmdPalDepsX64InstallFolder" On="uninstall" />
|
||||
<?else?>
|
||||
<RemoveFolder Id="RemoveCmdPalDepsArm64InstallDirFolder" Directory="CmdPalDepsArm64InstallFolder" On="uninstall" />
|
||||
<?endif?>
|
||||
</Component>
|
||||
<ComponentRef Id="Module_CmdPal" />
|
||||
<ComponentRef Id="Module_CmdPal_Deps" />
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
|
||||
@@ -9,25 +9,6 @@
|
||||
<RegistryValue Type="string" Name="InstallScope" Value="$(var.InstallScope)" />
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
<?if $(var.PerUser) = "true" ?>
|
||||
<Component Id="powertoys_env_path_user" Bitness="always64">
|
||||
<!-- Anchor registry for component key path -->
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="powertoys_env_path_user" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<!-- Append DSCModules folder to current user's PATH for DSC v3 usage -->
|
||||
<Environment Id="AddPowerToysToUserPath" Name="PATH" Action="set" Part="last" System="no" Value="[DSCModulesReferenceFolder]" />
|
||||
</Component>
|
||||
<?else?>
|
||||
<Component Id="powertoys_env_path_machine" Bitness="always64">
|
||||
<!-- Anchor registry for component key path -->
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="powertoys_env_path_machine" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<!-- Append DSCModules folder to machine PATH for DSC v3 usage -->
|
||||
<Environment Id="AddPowerToysToMachinePath" Name="PATH" Action="set" Part="last" System="yes" Value="[DSCModulesReferenceFolder]" />
|
||||
</Component>
|
||||
<?endif?>
|
||||
<Component Id="powertoys_toast_clsid" Bitness="always64">
|
||||
<RemoveFolder Id="Remove_powertoys_toast_clsid" On="uninstall" />
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\CLSID\{DD5CACDA-7C2E-4997-A62A-04A597B58F76}">
|
||||
@@ -63,6 +44,16 @@
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="DSCModulesReferenceFolder">
|
||||
<Component Id="PowerToysDSCReference" Guid="40869ACB-0BEB-4911-AE41-5E73BC1586A9" Bitness="always64">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="DSCModulesReference" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<File Source="$(var.RepoDir)\src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(var.Version).0\Microsoft.PowerToys.Configure.psd1" Id="PTConfReference.psd1" />
|
||||
<File Source="$(var.RepoDir)\src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(var.Version).0\Microsoft.PowerToys.Configure.psm1" Id="PTConfReference.psm1" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<?if $(var.PerUser) = "true" ?>
|
||||
<!-- DSC module files for PerUser handled in InstallDSCModule custom action. -->
|
||||
<?else?>
|
||||
@@ -110,6 +101,7 @@
|
||||
<RegistryValue Type="string" Name="RemoveCoreFolder" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveBaseApplicationsAssetsFolder" Directory="BaseApplicationsAssetsFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveDSCModulesReferenceFolder" Directory="DSCModulesReferenceFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveWinUI3AppsInstallFolder" Directory="WinUI3AppsInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveWinUI3AppsAssetsFolder" Directory="WinUI3AppsAssetsFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveINSTALLFOLDER" Directory="INSTALLFOLDER" On="uninstall" />
|
||||
@@ -121,11 +113,7 @@
|
||||
<ComponentRef Id="License_rtf" />
|
||||
<ComponentRef Id="Notice_md" />
|
||||
<ComponentRef Id="DesktopShortcut" />
|
||||
<?if $(var.PerUser) = "true" ?>
|
||||
<ComponentRef Id="powertoys_env_path_user" />
|
||||
<?else?>
|
||||
<ComponentRef Id="powertoys_env_path_machine" />
|
||||
<?endif?>
|
||||
<ComponentRef Id="PowerToysDSCReference" />
|
||||
<?if $(var.PerUser) = "false" ?>
|
||||
<ComponentRef Id="PowerToysDSC" />
|
||||
<?endif?>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<Project>
|
||||
<Import Project="..\..\Directory.Build.props" Condition="Exists('..\..\Directory.Build.props')" />
|
||||
<Import Project="..\..\src\Version.props" Condition="Exists('..\..\src\Version.props')" />
|
||||
<PropertyGroup>
|
||||
<!-- Set BaseIntermediateOutputPath for each project to avoid conflicts -->
|
||||
@@ -9,4 +8,4 @@
|
||||
<!-- Set MSBuildProjectExtensionsPath to use the BaseIntermediateOutputPath -->
|
||||
<MSBuildProjectExtensionsPath Condition="'$(BaseIntermediateOutputPath)' != ''">$(BaseIntermediateOutputPath)</MSBuildProjectExtensionsPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<?define DscJsonFiles=?>
|
||||
<?define DscJsonFilesPath=$(var.BinDir)\DSCModules?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="DSCModulesReferenceFolder" FileSource="$(var.DscJsonFilesPath)">
|
||||
<!-- DSC v2 PowerShell module files -->
|
||||
<Component Id="PowerToysDSCReference" Guid="40869ACB-0BEB-4911-AE41-5E73BC1586A9" Bitness="always64">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="DSCModulesReference" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<File Source="$(var.RepoDir)\src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(var.Version).0\Microsoft.PowerToys.Configure.psd1" Id="PTConfReference.psd1" />
|
||||
<File Source="$(var.RepoDir)\src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(var.Version).0\Microsoft.PowerToys.Configure.psm1" Id="PTConfReference.psm1" />
|
||||
</Component>
|
||||
|
||||
<!-- DSC v3 JSON manifest files - Generated by generateAllFileComponents.ps1 -->
|
||||
<!--DscJsonFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
<ComponentGroup Id="DscResourcesComponentGroup">
|
||||
<ComponentRef Id="PowerToysDSCReference" />
|
||||
<Component Id="RemoveDSCModulesFolder" Guid="A3C77D92-4E97-4C1A-9F2E-8B3C5D6E7F80" Directory="DSCModulesReferenceFolder">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="RemoveDSCModulesFolder" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveDSCModulesReferenceFolder" Directory="DSCModulesReferenceFolder" On="uninstall" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
@@ -14,6 +14,7 @@ SET PTRoot=$(SolutionDir)\..
|
||||
call "..\..\..\publish.cmd" x64
|
||||
)
|
||||
call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuildThisFileDirectory)\generateMonacoWxs.ps1 -monacoWxsFile "$(MSBuildThisFileDirectory)\MonacoSRC.wxs" -Platform "$(Platform)" -nugetHeatPath "$(NUGET_PACKAGES)\wixtoolset.heat\5.0.2"
|
||||
call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuildThisFileDirectory)\generateDscResourcesWxs.ps1 -dscWxsFile "$(MSBuildThisFileDirectory)\DscResources.wxs" -Platform "$(Platform)" -Configuration "$(Configuration)"
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)' != 'x64'">
|
||||
@@ -24,6 +25,7 @@ SET PTRoot=$(SolutionDir)\..
|
||||
call "..\..\..\publish.cmd" arm64
|
||||
)
|
||||
call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuildThisFileDirectory)\generateMonacoWxs.ps1 -monacoWxsFile "$(MSBuildThisFileDirectory)\MonacoSRC.wxs" -Platform "$(Platform)" -nugetHeatPath "$(NUGET_PACKAGES)\wixtoolset.heat\5.0.2"
|
||||
call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuildThisFileDirectory)\generateDscResourcesWxs.ps1 -dscWxsFile "$(MSBuildThisFileDirectory)\DscResources.wxs" -Platform "$(Platform)" -Configuration "$(Configuration)"
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
@@ -35,7 +37,6 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
call move /Y ..\..\..\CmdPal.wxs.bk ..\..\..\CmdPal.wxs
|
||||
call move /Y ..\..\..\ColorPicker.wxs.bk ..\..\..\ColorPicker.wxs
|
||||
call move /Y ..\..\..\Core.wxs.bk ..\..\..\Core.wxs
|
||||
call move /Y ..\..\..\DscResources.wxs.bk ..\..\..\DscResources.wxs
|
||||
call move /Y ..\..\..\EnvironmentVariables.wxs.bk ..\..\..\EnvironmentVariables.wxs
|
||||
call move /Y ..\..\..\FileExplorerPreview.wxs.bk ..\..\..\FileExplorerPreview.wxs
|
||||
call move /Y ..\..\..\FileLocksmith.wxs.bk ..\..\..\FileLocksmith.wxs
|
||||
@@ -59,12 +60,6 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
call move /Y ..\..\..\Workspaces.wxs.bk ..\..\..\Workspaces.wxs
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(RunBuildEvents)'=='false'">
|
||||
<PostBuildEvent></PostBuildEvent>
|
||||
<RunPostBuildEvent></RunPostBuildEvent>
|
||||
<PreBuildEventUseInBuild>false</PreBuildEventUseInBuild>
|
||||
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="UserMacros" Condition=" '$(PerUser)' == 'true' ">
|
||||
<DefineConstants>$(DefineConstants);PerUser=true</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -112,7 +112,6 @@
|
||||
<Custom Action="SetUninstallCommandNotFoundParam" Before="UninstallCommandNotFound" />
|
||||
<Custom Action="SetUpgradeCommandNotFoundParam" Before="UpgradeCommandNotFound" />
|
||||
<Custom Action="SetApplyModulesRegistryChangeSetsParam" Before="ApplyModulesRegistryChangeSets" />
|
||||
<Custom Action="SetInstallPackageIdentityMSIXParam" Before="InstallPackageIdentityMSIX" />
|
||||
|
||||
<?if $(var.PerUser) = "true" ?>
|
||||
<Custom Action="SetInstallDSCModuleParam" Before="InstallDSCModule" />
|
||||
@@ -124,7 +123,6 @@
|
||||
<Custom Action="SetBundleInstallLocation" After="InstallFiles" Condition="NOT Installed" />
|
||||
<Custom Action="ApplyModulesRegistryChangeSets" After="InstallFiles" Condition="NOT Installed" />
|
||||
<Custom Action="InstallCmdPalPackage" After="InstallFiles" Condition="NOT Installed" />
|
||||
<Custom Action="InstallPackageIdentityMSIX" After="InstallFiles" Condition="NOT Installed" />
|
||||
<Custom Action="override Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Before="RemoveFiles" />
|
||||
<Custom Action="RemovePowerToysSchTasks" After="RemoveFiles" />
|
||||
<!-- TODO: Use to activate embedded MSIX -->
|
||||
@@ -146,7 +144,6 @@
|
||||
<Custom Action="UnRegisterCmdPalPackage" Before="RemoveFiles" Condition="Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")" />
|
||||
<Custom Action="UninstallCommandNotFound" Before="RemoveFiles" Condition="Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")" />
|
||||
<Custom Action="UpgradeCommandNotFound" After="InstallFiles" Condition="WIX_UPGRADE_DETECTED" />
|
||||
<Custom Action="UninstallPackageIdentityMSIX" Before="RemoveFiles" Condition="Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")" />
|
||||
<Custom Action="UninstallServicesTask" After="InstallFinalize" Condition="Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")" />
|
||||
<!-- TODO: Use to activate embedded MSIX -->
|
||||
<!--<Custom Action="UninstallEmbeddedMSIXTask" After="InstallFinalize">
|
||||
@@ -202,12 +199,6 @@
|
||||
|
||||
<CustomAction Id="UninstallEmbeddedMSIXTask" Return="ignore" Impersonate="yes" DllEntry="UninstallEmbeddedMSIXCA" BinaryRef="PTCustomActions" />
|
||||
|
||||
<CustomAction Id="SetInstallPackageIdentityMSIXParam" Property="InstallPackageIdentityMSIX" Value="[INSTALLFOLDER];[InstallScope]" />
|
||||
|
||||
<CustomAction Id="InstallPackageIdentityMSIX" Return="ignore" Impersonate="yes" Execute="deferred" DllEntry="InstallPackageIdentityMSIXCA" BinaryRef="PTCustomActions" />
|
||||
|
||||
<CustomAction Id="UninstallPackageIdentityMSIX" Return="ignore" Impersonate="yes" DllEntry="UninstallPackageIdentityMSIXCA" BinaryRef="PTCustomActions" />
|
||||
|
||||
<CustomAction Id="InstallDSCModule" Return="ignore" Impersonate="yes" Execute="deferred" DllEntry="InstallDSCModuleCA" BinaryRef="PTCustomActions" />
|
||||
|
||||
<CustomAction Id="UninstallDSCModule" Return="ignore" Impersonate="yes" DllEntry="UninstallDSCModuleCA" BinaryRef="PTCustomActions" />
|
||||
|
||||
@@ -14,16 +14,11 @@
|
||||
<?define SettingsV2OOBEAssetsFluentIconsFiles=?>
|
||||
<?define SettingsV2OOBEAssetsFluentIconsFilesPath=$(var.BinDir)WinUI3Apps\Assets\Settings\Icons\?>
|
||||
|
||||
<?define SettingsV2IconsModelsFiles=?>
|
||||
<?define SettingsV2IconsModelsFilesPath=$(var.BinDir)WinUI3Apps\Assets\Settings\Icons\Models\?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="WinUI3AppsAssetsFolder">
|
||||
<Directory Id="SettingsV2AssetsInstallFolder" Name="Settings">
|
||||
<Directory Id="SettingsAppAssetsScriptsFolder" Name="Scripts" />
|
||||
<Directory Id="SettingsV2OOBEAssetsFluentIconsInstallFolder" Name="Icons">
|
||||
<Directory Id="SettingsV2IconsModelsInstallFolder" Name="Models" />
|
||||
</Directory>
|
||||
<Directory Id="SettingsV2OOBEAssetsFluentIconsInstallFolder" Name="Icons" />
|
||||
<Directory Id="SettingsV2AssetsModulesInstallFolder" Name="Modules">
|
||||
<Directory Id="SettingsV2OOBEAssetsModulesInstallFolder" Name="OOBE" />
|
||||
</Directory>
|
||||
@@ -50,11 +45,6 @@
|
||||
<!--SettingsV2OOBEAssetsFluentIconsFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="SettingsV2IconsModelsInstallFolder" FileSource="$(var.SettingsV2IconsModelsFilesPath)">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--SettingsV2IconsModelsFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="SettingsAppAssetsScriptsFolder" FileSource="$(var.SettingsV2AssetsFilesPath)\Scripts\">
|
||||
<Component Id="CommandNotFound_Scripts" Guid="898EFA1E-EDD3-4F4B-8C7F-4A14B0D05B02" Bitness="always64">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
@@ -77,7 +67,6 @@
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2AssetsInstallFolder" Directory="SettingsV2AssetsInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2OOBEAssetsFluentIconsInstallFolder" Directory="SettingsV2OOBEAssetsFluentIconsInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2IconsModelsInstallFolder" Directory="SettingsV2IconsModelsInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2AssetsModulesInstallFolder" Directory="SettingsV2AssetsModulesInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2OOBEAssetsModulesInstallFolder" Directory="SettingsV2OOBEAssetsModulesInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderSettingsAppAssetsScriptsFolder" Directory="SettingsAppAssetsScriptsFolder" On="uninstall" />
|
||||
|
||||
@@ -1,7 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
|
||||
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}</ProjectGuid>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<TargetName>SilentFilesInUseBAFunction</TargetName>
|
||||
<ProjectName>PowerToysSetupCustomActionsVNext</ProjectName>
|
||||
<ProjectModuleDefinitionFile>bafunctions.def</ProjectModuleDefinitionFile>
|
||||
@@ -10,6 +33,7 @@
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
|
||||
<!-- Configuration-specific property groups -->
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
@@ -41,10 +65,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SilentFilesInUseBAFunctions.cpp">
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SilentFilesInUseBAFunctions.cpp" />
|
||||
<ClCompile Include="bafunctions.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
|
||||
@@ -71,5 +92,31 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- C++ source compile-specific things for Debug/Release configurations -->
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -18,6 +18,7 @@ public: // IBootstrapperApplication
|
||||
|
||||
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "*** CUSTOM BA FUNCTION SYSTEM ACTIVE *** Running detect begin BA function. fCached=%d, registrationType=%d, cPackages=%u, fCancel=%d", fCached, registrationType, cPackages, *pfCancel);
|
||||
|
||||
LExit:
|
||||
return hr;
|
||||
}
|
||||
|
||||
@@ -31,6 +32,12 @@ public: // IBAFunctions
|
||||
|
||||
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "*** CUSTOM BA FUNCTION SYSTEM ACTIVE *** Running plan begin BA function. cPackages=%u, fCancel=%d", cPackages, *pfCancel);
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// YOUR CODE GOES HERE
|
||||
// BalExitOnFailure(hr, "Change this message to represent real error handling.");
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
LExit:
|
||||
return hr;
|
||||
}
|
||||
|
||||
@@ -56,7 +63,6 @@ public: // IBAFunctions
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UNREFERENCED_PARAMETER(source);
|
||||
|
||||
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "*** CUSTOM BA FUNCTION CALLED *** Running OnExecuteFilesInUse BA function. packageId=%ls, cFiles=%u, recommendation=%d", wzPackageId, cFiles, nRecommendation);
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $True, Position = 1)]
|
||||
[string]$platform
|
||||
[string]$platform,
|
||||
[Parameter(Mandatory = $False, Position = 2)]
|
||||
[string]$installscopeperuser = "false"
|
||||
)
|
||||
|
||||
Function Generate-FileList() {
|
||||
@@ -75,7 +77,9 @@ Function Generate-FileComponents() {
|
||||
[Parameter(Mandatory = $True, Position = 1)]
|
||||
[string]$fileListName,
|
||||
[Parameter(Mandatory = $True, Position = 2)]
|
||||
[string]$wxsFilePath
|
||||
[string]$wxsFilePath,
|
||||
[Parameter(Mandatory = $True, Position = 3)]
|
||||
[string]$regroot
|
||||
)
|
||||
|
||||
$wxsFile = Get-Content $wxsFilePath;
|
||||
@@ -96,7 +100,7 @@ Function Generate-FileComponents() {
|
||||
$componentDefs +=
|
||||
@"
|
||||
<Component Id="$($componentId)" Guid="$((New-Guid).ToString().ToUpper())">
|
||||
<RegistryKey Root="`$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryKey Root="$($regroot)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="$($componentId)" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>`r`n
|
||||
"@
|
||||
@@ -130,194 +134,194 @@ if ($platform -ceq "arm64") {
|
||||
$platform = "ARM64"
|
||||
}
|
||||
|
||||
if ($installscopeperuser -eq "true") {
|
||||
$registryroot = "HKCU"
|
||||
} else {
|
||||
$registryroot = "HKLM"
|
||||
}
|
||||
|
||||
#BaseApplications
|
||||
Generate-FileList -fileDepsJson "" -fileListName BaseApplicationsFiles -wxsFilePath $PSScriptRoot\BaseApplications.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release"
|
||||
Generate-FileComponents -fileListName "BaseApplicationsFiles" -wxsFilePath $PSScriptRoot\BaseApplications.wxs
|
||||
Generate-FileComponents -fileListName "BaseApplicationsFiles" -wxsFilePath $PSScriptRoot\BaseApplications.wxs -regroot $registryroot
|
||||
|
||||
#WinUI3Applications
|
||||
Generate-FileList -fileDepsJson "" -fileListName WinUI3ApplicationsFiles -wxsFilePath $PSScriptRoot\WinUI3Applications.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps"
|
||||
Generate-FileComponents -fileListName "WinUI3ApplicationsFiles" -wxsFilePath $PSScriptRoot\WinUI3Applications.wxs
|
||||
Generate-FileComponents -fileListName "WinUI3ApplicationsFiles" -wxsFilePath $PSScriptRoot\WinUI3Applications.wxs -regroot $registryroot
|
||||
|
||||
#AdvancedPaste
|
||||
Generate-FileList -fileDepsJson "" -fileListName AdvancedPasteAssetsFiles -wxsFilePath $PSScriptRoot\AdvancedPaste.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\AdvancedPaste"
|
||||
Generate-FileComponents -fileListName "AdvancedPasteAssetsFiles" -wxsFilePath $PSScriptRoot\AdvancedPaste.wxs
|
||||
Generate-FileComponents -fileListName "AdvancedPasteAssetsFiles" -wxsFilePath $PSScriptRoot\AdvancedPaste.wxs -regroot $registryroot
|
||||
|
||||
#AwakeFiles
|
||||
Generate-FileList -fileDepsJson "" -fileListName AwakeImagesFiles -wxsFilePath $PSScriptRoot\Awake.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Awake"
|
||||
Generate-FileComponents -fileListName "AwakeImagesFiles" -wxsFilePath $PSScriptRoot\Awake.wxs
|
||||
Generate-FileComponents -fileListName "AwakeImagesFiles" -wxsFilePath $PSScriptRoot\Awake.wxs -regroot $registryroot
|
||||
|
||||
#ColorPicker
|
||||
Generate-FileList -fileDepsJson "" -fileListName ColorPickerAssetsFiles -wxsFilePath $PSScriptRoot\ColorPicker.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\ColorPicker"
|
||||
Generate-FileComponents -fileListName "ColorPickerAssetsFiles" -wxsFilePath $PSScriptRoot\ColorPicker.wxs
|
||||
Generate-FileComponents -fileListName "ColorPickerAssetsFiles" -wxsFilePath $PSScriptRoot\ColorPicker.wxs -regroot $registryroot
|
||||
|
||||
#Environment Variables
|
||||
Generate-FileList -fileDepsJson "" -fileListName EnvironmentVariablesAssetsFiles -wxsFilePath $PSScriptRoot\EnvironmentVariables.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\EnvironmentVariables"
|
||||
Generate-FileComponents -fileListName "EnvironmentVariablesAssetsFiles" -wxsFilePath $PSScriptRoot\EnvironmentVariables.wxs
|
||||
Generate-FileComponents -fileListName "EnvironmentVariablesAssetsFiles" -wxsFilePath $PSScriptRoot\EnvironmentVariables.wxs -regroot $registryroot
|
||||
|
||||
#FileExplorerAdd-ons
|
||||
Generate-FileList -fileDepsJson "" -fileListName MonacoPreviewHandlerMonacoAssetsFiles -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Monaco"
|
||||
Generate-FileList -fileDepsJson "" -fileListName MonacoPreviewHandlerCustomLanguagesFiles -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Monaco\customLanguages"
|
||||
Generate-FileComponents -fileListName "MonacoPreviewHandlerMonacoAssetsFiles" -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs
|
||||
Generate-FileComponents -fileListName "MonacoPreviewHandlerCustomLanguagesFiles" -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs
|
||||
Generate-FileComponents -fileListName "MonacoPreviewHandlerMonacoAssetsFiles" -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "MonacoPreviewHandlerCustomLanguagesFiles" -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -regroot $registryroot
|
||||
|
||||
#FileLocksmith
|
||||
Generate-FileList -fileDepsJson "" -fileListName FileLocksmithAssetsFiles -wxsFilePath $PSScriptRoot\FileLocksmith.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\FileLocksmith"
|
||||
Generate-FileComponents -fileListName "FileLocksmithAssetsFiles" -wxsFilePath $PSScriptRoot\FileLocksmith.wxs
|
||||
Generate-FileComponents -fileListName "FileLocksmithAssetsFiles" -wxsFilePath $PSScriptRoot\FileLocksmith.wxs -regroot $registryroot
|
||||
|
||||
#Hosts
|
||||
Generate-FileList -fileDepsJson "" -fileListName HostsAssetsFiles -wxsFilePath $PSScriptRoot\Hosts.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Hosts"
|
||||
Generate-FileComponents -fileListName "HostsAssetsFiles" -wxsFilePath $PSScriptRoot\Hosts.wxs
|
||||
Generate-FileComponents -fileListName "HostsAssetsFiles" -wxsFilePath $PSScriptRoot\Hosts.wxs -regroot $registryroot
|
||||
|
||||
#ImageResizer
|
||||
Generate-FileList -fileDepsJson "" -fileListName ImageResizerAssetsFiles -wxsFilePath $PSScriptRoot\ImageResizer.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ImageResizer"
|
||||
Generate-FileComponents -fileListName "ImageResizerAssetsFiles" -wxsFilePath $PSScriptRoot\ImageResizer.wxs
|
||||
Generate-FileComponents -fileListName "ImageResizerAssetsFiles" -wxsFilePath $PSScriptRoot\ImageResizer.wxs -regroot $registryroot
|
||||
|
||||
# Light Switch Service
|
||||
Generate-FileList -fileDepsJson "" -fileListName LightSwitchFiles -wxsFilePath $PSScriptRoot\LightSwitch.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\LightSwitchService"
|
||||
Generate-FileComponents -fileListName "LightSwitchFiles" -wxsFilePath $PSScriptRoot\LightSwitch.wxs
|
||||
Generate-FileComponents -fileListName "LightSwitchFiles" -wxsFilePath $PSScriptRoot\LightSwitch.wxs -regroot $registryroot
|
||||
|
||||
#New+
|
||||
Generate-FileList -fileDepsJson "" -fileListName NewPlusAssetsFiles -wxsFilePath $PSScriptRoot\NewPlus.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\NewPlus"
|
||||
Generate-FileComponents -fileListName "NewPlusAssetsFiles" -wxsFilePath $PSScriptRoot\NewPlus.wxs
|
||||
Generate-FileComponents -fileListName "NewPlusAssetsFiles" -wxsFilePath $PSScriptRoot\NewPlus.wxs -regroot $registryroot
|
||||
|
||||
#Peek
|
||||
Generate-FileList -fileDepsJson "" -fileListName PeekAssetsFiles -wxsFilePath $PSScriptRoot\Peek.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Peek\"
|
||||
Generate-FileComponents -fileListName "PeekAssetsFiles" -wxsFilePath $PSScriptRoot\Peek.wxs
|
||||
Generate-FileComponents -fileListName "PeekAssetsFiles" -wxsFilePath $PSScriptRoot\Peek.wxs -regroot $registryroot
|
||||
|
||||
#PowerRename
|
||||
Generate-FileList -fileDepsJson "" -fileListName PowerRenameAssetsFiles -wxsFilePath $PSScriptRoot\PowerRename.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\PowerRename\"
|
||||
Generate-FileComponents -fileListName "PowerRenameAssetsFiles" -wxsFilePath $PSScriptRoot\PowerRename.wxs
|
||||
Generate-FileComponents -fileListName "PowerRenameAssetsFiles" -wxsFilePath $PSScriptRoot\PowerRename.wxs -regroot $registryroot
|
||||
|
||||
#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
|
||||
Generate-FileComponents -fileListName "RegistryPreviewAssetsFiles" -wxsFilePath $PSScriptRoot\RegistryPreview.wxs -regroot $registryroot
|
||||
|
||||
#Run
|
||||
Generate-FileList -fileDepsJson "" -fileListName launcherImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\PowerLauncher"
|
||||
Generate-FileComponents -fileListName "launcherImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "launcherImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
## Plugins
|
||||
###Calculator
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Calculator\Microsoft.PowerToys.Run.Plugin.Calculator.deps.json" -fileListName calcComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName calcImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Calculator\Images"
|
||||
Generate-FileComponents -fileListName "calcComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "calcImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "calcComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "calcImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###Folder
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Folder\Microsoft.Plugin.Folder.deps.json" -fileListName FolderComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName FolderImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Folder\Images"
|
||||
Generate-FileComponents -fileListName "FolderComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "FolderImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "FolderComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "FolderImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###Program
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Program\Microsoft.Plugin.Program.deps.json" -fileListName ProgramComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName ProgramImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Program\Images"
|
||||
Generate-FileComponents -fileListName "ProgramComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "ProgramImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "ProgramComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "ProgramImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###Shell
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Shell\Microsoft.Plugin.Shell.deps.json" -fileListName ShellComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName ShellImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Shell\Images"
|
||||
Generate-FileComponents -fileListName "ShellComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "ShellImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "ShellComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "ShellImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###Indexer
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Indexer\Microsoft.Plugin.Indexer.deps.json" -fileListName IndexerComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName IndexerImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Indexer\Images"
|
||||
Generate-FileComponents -fileListName "IndexerComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "IndexerImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "IndexerComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "IndexerImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###UnitConverter
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\UnitConverter\Community.PowerToys.Run.Plugin.UnitConverter.deps.json" -fileListName UnitConvCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName UnitConvImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\UnitConverter\Images"
|
||||
Generate-FileComponents -fileListName "UnitConvCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "UnitConvImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "UnitConvCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "UnitConvImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###WebSearch
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WebSearch\Community.PowerToys.Run.Plugin.WebSearch.deps.json" -fileListName WebSrchCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName WebSrchImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WebSearch\Images"
|
||||
Generate-FileComponents -fileListName "WebSrchCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "WebSrchImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "WebSrchCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "WebSrchImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###History
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\History\Microsoft.PowerToys.Run.Plugin.History.deps.json" -fileListName HistoryPluginComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName HistoryPluginImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\History\Images"
|
||||
Generate-FileComponents -fileListName "HistoryPluginComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "HistoryPluginImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "HistoryPluginComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "HistoryPluginImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###Uri
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Uri\Microsoft.Plugin.Uri.deps.json" -fileListName UriComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName UriImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Uri\Images"
|
||||
Generate-FileComponents -fileListName "UriComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "UriImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "UriComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "UriImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###VSCodeWorkspaces
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\VSCodeWorkspaces\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.deps.json" -fileListName VSCWrkCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName VSCWrkImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\VSCodeWorkspaces\Images"
|
||||
Generate-FileComponents -fileListName "VSCWrkCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "VSCWrkImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "VSCWrkCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "VSCWrkImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###WindowWalker
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowWalker\Microsoft.Plugin.WindowWalker.deps.json" -fileListName WindowWlkrCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName WindowWlkrImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowWalker\Images"
|
||||
Generate-FileComponents -fileListName "WindowWlkrCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "WindowWlkrImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "WindowWlkrCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "WindowWlkrImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###OneNote
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\OneNote\Microsoft.PowerToys.Run.Plugin.OneNote.deps.json" -fileListName OneNoteComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName OneNoteImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\OneNote\Images"
|
||||
Generate-FileComponents -fileListName "OneNoteComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "OneNoteImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "OneNoteComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "OneNoteImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###Registry
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Registry\Microsoft.PowerToys.Run.Plugin.Registry.deps.json" -fileListName RegistryComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName RegistryImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Registry\Images"
|
||||
Generate-FileComponents -fileListName "RegistryComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "RegistryImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "RegistryComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "RegistryImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###Service
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Service\Microsoft.PowerToys.Run.Plugin.Service.deps.json" -fileListName ServiceComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName ServiceImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Service\Images"
|
||||
Generate-FileComponents -fileListName "ServiceComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "ServiceImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "ServiceComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "ServiceImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###System
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\System\Microsoft.PowerToys.Run.Plugin.System.deps.json" -fileListName SystemComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName SystemImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\System\Images"
|
||||
Generate-FileComponents -fileListName "SystemComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "SystemImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "SystemComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "SystemImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###TimeDate
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\TimeDate\Microsoft.PowerToys.Run.Plugin.TimeDate.deps.json" -fileListName TimeDateComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName TimeDateImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\TimeDate\Images"
|
||||
Generate-FileComponents -fileListName "TimeDateComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "TimeDateImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "TimeDateComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "TimeDateImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###WindowsSettings
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.deps.json" -fileListName WinSetCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName WinSetImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowsSettings\Images"
|
||||
Generate-FileComponents -fileListName "WinSetCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "WinSetImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "WinSetCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "WinSetImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###WindowsTerminal
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowsTerminal\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.deps.json" -fileListName WinTermCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName WinTermImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowsTerminal\Images"
|
||||
Generate-FileComponents -fileListName "WinTermCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "WinTermImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "WinTermCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "WinTermImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###PowerToys
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\PowerToys\Microsoft.PowerToys.Run.Plugin.PowerToys.deps.json" -fileListName PowerToysCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName PowerToysImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\PowerToys\Images"
|
||||
Generate-FileComponents -fileListName "PowerToysCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "PowerToysImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "PowerToysCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "PowerToysImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
###ValueGenerator
|
||||
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\ValueGenerator\Community.PowerToys.Run.Plugin.ValueGenerator.deps.json" -fileListName ValueGeneratorCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
|
||||
Generate-FileList -fileDepsJson "" -fileListName ValueGeneratorImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\ValueGenerator\Images"
|
||||
Generate-FileComponents -fileListName "ValueGeneratorCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "ValueGeneratorImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
|
||||
Generate-FileComponents -fileListName "ValueGeneratorCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "ValueGeneratorImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
|
||||
## Plugins
|
||||
|
||||
#ShortcutGuide
|
||||
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideSvgFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\ShortcutGuide\"
|
||||
Generate-FileComponents -fileListName "ShortcutGuideSvgFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
|
||||
Generate-FileComponents -fileListName "ShortcutGuideSvgFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -regroot $registryroot
|
||||
|
||||
#Settings
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\"
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsModulesFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Modules\"
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2OOBEAssetsModulesFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Modules\OOBE\"
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2OOBEAssetsFluentIconsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Icons\"
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2IconsModelsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Icons\Models\"
|
||||
Generate-FileComponents -fileListName "SettingsV2AssetsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
Generate-FileComponents -fileListName "SettingsV2AssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsFluentIconsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
Generate-FileComponents -fileListName "SettingsV2IconsModelsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
Generate-FileComponents -fileListName "SettingsV2AssetsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "SettingsV2AssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
|
||||
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsFluentIconsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
|
||||
|
||||
#Workspaces
|
||||
Generate-FileList -fileDepsJson "" -fileListName WorkspacesImagesComponentFiles -wxsFilePath $PSScriptRoot\Workspaces.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Workspaces\"
|
||||
Generate-FileComponents -fileListName "WorkspacesImagesComponentFiles" -wxsFilePath $PSScriptRoot\Workspaces.wxs
|
||||
|
||||
#DSC Resources - JSON manifest files in DSCModules subfolder
|
||||
Generate-FileList -fileDepsJson "" -fileListName DscJsonFiles -wxsFilePath $PSScriptRoot\DscResources.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\DSCModules\"
|
||||
Generate-FileComponents -fileListName "DscJsonFiles" -wxsFilePath $PSScriptRoot\DscResources.wxs
|
||||
Generate-FileComponents -fileListName "WorkspacesImagesComponentFiles" -wxsFilePath $PSScriptRoot\Workspaces.wxs -regroot $registryroot
|
||||
|
||||
102
installer/PowerToysSetupVNext/generateDscResourcesWxs.ps1
Normal file
102
installer/PowerToysSetupVNext/generateDscResourcesWxs.ps1
Normal file
@@ -0,0 +1,102 @@
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string]$dscWxsFile,
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string]$Platform,
|
||||
[Parameter(Mandatory = $True)]
|
||||
[string]$Configuration
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
|
||||
# Find build output directory
|
||||
$buildOutputDir = Join-Path $scriptDir "..\..\$Platform\$Configuration"
|
||||
|
||||
if (-not (Test-Path $buildOutputDir)) {
|
||||
Write-Error "Build output directory not found: '$buildOutputDir'"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Find all DSC manifest JSON files
|
||||
$dscFiles = Get-ChildItem -Path $buildOutputDir -Filter "microsoft.powertoys.*.settings.dsc.resource.json" -File
|
||||
|
||||
if (-not $dscFiles) {
|
||||
Write-Warning "No DSC manifest files found in '$buildOutputDir'"
|
||||
# Create empty component group
|
||||
$wxsContent = @"
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||
|
||||
<?include `$(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<Fragment>
|
||||
<ComponentGroup Id="DscResourcesComponentGroup">
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
"@
|
||||
Set-Content -Path $dscWxsFile -Value $wxsContent
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host "Found $($dscFiles.Count) DSC manifest file(s)"
|
||||
|
||||
# Generate WiX fragment
|
||||
$wxsContent = @"
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||
|
||||
<?include `$(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="DSCModulesReferenceFolder">
|
||||
"@
|
||||
|
||||
$componentRefs = @()
|
||||
|
||||
foreach ($file in $dscFiles) {
|
||||
$componentId = "DscResource_" + ($file.BaseName -replace '[^A-Za-z0-9_]', '_')
|
||||
$fileId = $componentId + "_File"
|
||||
$guid = [System.Guid]::NewGuid().ToString().ToUpper()
|
||||
|
||||
$componentRefs += $componentId
|
||||
|
||||
$wxsContent += @"
|
||||
|
||||
<Component Id="$componentId" Guid="{$guid}" Directory="DSCModulesReferenceFolder">
|
||||
<RegistryKey Root="`$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="$componentId" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Id="$fileId" Source="`$(var.BinDir)$($file.Name)" Vital="no"/>
|
||||
</Component>
|
||||
"@
|
||||
}
|
||||
|
||||
$wxsContent += @"
|
||||
|
||||
</DirectoryRef>
|
||||
</Fragment>
|
||||
|
||||
<Fragment>
|
||||
<ComponentGroup Id="DscResourcesComponentGroup">
|
||||
"@
|
||||
|
||||
foreach ($componentId in $componentRefs) {
|
||||
$wxsContent += @"
|
||||
|
||||
<ComponentRef Id="$componentId"/>
|
||||
"@
|
||||
}
|
||||
|
||||
$wxsContent += @"
|
||||
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
"@
|
||||
|
||||
# Write the WiX file
|
||||
Set-Content -Path $dscWxsFile -Value $wxsContent
|
||||
|
||||
Write-Host "Generated DSC resources WiX fragment: '$dscWxsFile'"
|
||||
@@ -1,67 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Sparse package manifest (moved to PackageIdentity folder for cleaner organization).
|
||||
Based on Windows AI Foundry WPF sparse sample with PowerOCR customizations. -->
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
|
||||
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
|
||||
xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
|
||||
xmlns:systemai="http://schemas.microsoft.com/appx/manifest/systemai/windows10"
|
||||
IgnorableNamespaces="uap uap2 uap3 rescap desktop uap10 systemai">
|
||||
<Identity
|
||||
Name="Microsoft.PowerToys.SparseApp"
|
||||
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
|
||||
Version="0.0.1.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>PowerToys.SparseApp</DisplayName>
|
||||
<PublisherDisplayName>PowerToys</PublisherDisplayName>
|
||||
<Logo>Images\StoreLogo.png</Logo>
|
||||
<uap10:AllowExternalContent>true</uap10:AllowExternalContent>
|
||||
</Properties>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="en-us" />
|
||||
</Resources>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19000.0" MaxVersionTested="10.0.26226.0" />
|
||||
</Dependencies>
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
<systemai:Capability Name="systemAIModels"/>
|
||||
<rescap:Capability Name="unvirtualizedResources"/>
|
||||
</Capabilities>
|
||||
|
||||
<Applications>
|
||||
<Application Id="PowerToys.OCR" Executable="PowerToys.PowerOCR.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<uap:VisualElements
|
||||
DisplayName="PowerToys.OCR"
|
||||
Description="PowerToys OCR Module"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Images\Square150x150Logo.png"
|
||||
Square44x44Logo="Images\Square44x44Logo.png">
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
<Application Id="PowerToys.SettingsUI" Executable="WinUI3Apps\PowerToys.Settings.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<uap:VisualElements
|
||||
DisplayName="PowerToys.SettingsUI"
|
||||
Description="PowerToys Settings UI"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Images\Square150x150Logo.png"
|
||||
Square44x44Logo="Images\Square44x44Logo.png">
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
<Application Id="PowerToys.ImageResizerUI" Executable="WinUI3Apps\PowerToys.ImageResizer.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<uap:VisualElements
|
||||
DisplayName="PowerToys.ImageResizer"
|
||||
Description="PowerToys Image Resizer UI"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Images\Square150x150Logo.png"
|
||||
Square44x44Logo="Images\Square44x44Logo.png">
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
</Package>
|
||||
@@ -1,6 +0,0 @@
|
||||
@echo off
|
||||
REM Wrapper to invoke PowerToys sparse package build script.
|
||||
REM Pass through all arguments (e.g. Platform=arm64 Configuration=Debug -Clean)
|
||||
|
||||
powershell -ExecutionPolicy Bypass -NoLogo -NoProfile -File "%~dp0\BuildSparsePackage.ps1" %*
|
||||
exit /b %ERRORLEVEL%
|
||||
@@ -1,422 +0,0 @@
|
||||
#Requires -Version 5.1
|
||||
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[ValidateSet("arm64", "x64")]
|
||||
[string]$Platform = "x64",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[ValidateSet("Debug", "Release")]
|
||||
[string]$Configuration = "Release",
|
||||
|
||||
[switch]$Clean,
|
||||
[switch]$ForceCert,
|
||||
[switch]$NoSign,
|
||||
[switch]$CIBuild
|
||||
)
|
||||
|
||||
# PowerToys sparse packaging helper.
|
||||
# Generates a sparse MSIX (no payload) that grants package identity to selected Win32 components.
|
||||
# Multiple applications (PowerOCR, Settings UI, etc.) can share this single sparse identity.
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$isCIBuild = $false
|
||||
if ($CIBuild.IsPresent) {
|
||||
$isCIBuild = $true
|
||||
} elseif ($env:CIBuild) {
|
||||
$isCIBuild = $env:CIBuild -ieq 'true'
|
||||
}
|
||||
|
||||
$currentPublisherHint = $script:Config.CertSubject
|
||||
|
||||
# Configuration constants - centralized management
|
||||
$script:Config = @{
|
||||
IdentityName = "Microsoft.PowerToys.SparseApp"
|
||||
SparseMsixName = "PowerToysSparse.msix"
|
||||
CertPrefix = "PowerToysSparse"
|
||||
CertSubject = 'CN=PowerToys Dev, O=PowerToys, L=Redmond, S=Washington, C=US'
|
||||
CertValidMonths = 12
|
||||
}
|
||||
|
||||
#region Helper Functions
|
||||
|
||||
function Find-WindowsSDKTool {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$ToolName,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$Architecture = "x64"
|
||||
)
|
||||
|
||||
# Simple fallback: check common Windows SDK locations
|
||||
$commonPaths = @(
|
||||
"${env:ProgramFiles}\Windows Kits\10\bin\*\$Architecture\$ToolName",
|
||||
"${env:ProgramFiles(x86)}\Windows Kits\10\bin\*\$Architecture\$ToolName",
|
||||
"${env:ProgramFiles(x86)}\Windows Kits\10\bin\*\x86\$ToolName" # SignTool fallback
|
||||
)
|
||||
|
||||
foreach ($pattern in $commonPaths) {
|
||||
$found = Get-ChildItem $pattern -ErrorAction SilentlyContinue |
|
||||
Sort-Object Name -Descending |
|
||||
Select-Object -First 1
|
||||
if ($found) {
|
||||
Write-BuildLog "Found $ToolName at: $($found.FullName)" -Level Info
|
||||
return $found.FullName
|
||||
}
|
||||
}
|
||||
|
||||
throw "$ToolName not found. Please ensure Windows SDK is installed."
|
||||
}
|
||||
|
||||
function Test-CertificateValidity {
|
||||
param([string]$ThumbprintFile)
|
||||
|
||||
if (-not (Test-Path $ThumbprintFile)) { return $false }
|
||||
|
||||
try {
|
||||
$thumb = (Get-Content $ThumbprintFile -Raw).Trim()
|
||||
if (-not $thumb) { return $false }
|
||||
$cert = Get-Item "cert:\CurrentUser\My\$thumb" -ErrorAction Stop
|
||||
return $cert.HasPrivateKey -and $cert.NotAfter -gt (Get-Date)
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Write-BuildLog {
|
||||
param([string]$Message, [string]$Level = "Info")
|
||||
|
||||
$colors = @{ Error = "Red"; Warning = "Yellow"; Success = "Green"; Info = "Cyan" }
|
||||
$color = if ($colors.ContainsKey($Level)) { $colors[$Level] } else { "White" }
|
||||
|
||||
Write-Host "[$(Get-Date -f 'HH:mm:ss')] $Message" -ForegroundColor $color
|
||||
}
|
||||
|
||||
function Stop-FileProcesses {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$FilePath
|
||||
)
|
||||
|
||||
# This function is kept for compatibility but simplified since
|
||||
# the staging directory approach resolves the file lock issues
|
||||
Write-Verbose "File process check for: $FilePath"
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
# Environment diagnostics for troubleshooting
|
||||
Write-BuildLog "Starting PackageIdentity build process..." -Level Info
|
||||
Write-BuildLog "PowerShell Version: $($PSVersionTable.PSVersion)" -Level Info
|
||||
try {
|
||||
$execPolicy = Get-ExecutionPolicy
|
||||
Write-BuildLog "Execution Policy: $execPolicy" -Level Info
|
||||
} catch {
|
||||
Write-BuildLog "Execution Policy: Unable to determine (MSBuild environment)" -Level Info
|
||||
}
|
||||
Write-BuildLog "Current User: $env:USERNAME" -Level Info
|
||||
Write-BuildLog "Build Platform: $Platform, Configuration: $Configuration" -Level Info
|
||||
|
||||
# Check for Visual Studio environment
|
||||
if ($env:VSINSTALLDIR) {
|
||||
Write-BuildLog "Running in Visual Studio environment: $env:VSINSTALLDIR" -Level Info
|
||||
}
|
||||
|
||||
# Ensure certificate provider is available
|
||||
try {
|
||||
# Force load certificate provider for MSBuild environment
|
||||
if (-not (Get-PSProvider -PSProvider Certificate -ErrorAction SilentlyContinue)) {
|
||||
Write-BuildLog "Loading certificate provider..." -Level Warning
|
||||
Import-Module Microsoft.PowerShell.Security -Force
|
||||
}
|
||||
if (-not (Test-Path 'Cert:\CurrentUser')) {
|
||||
Write-BuildLog "Certificate drive not available, attempting to initialize..." -Level Warning
|
||||
Import-Module PKI -ErrorAction SilentlyContinue
|
||||
# Try to access the certificate store to force initialization
|
||||
Get-ChildItem "Cert:\CurrentUser\My" -ErrorAction SilentlyContinue | Out-Null
|
||||
}
|
||||
} catch {
|
||||
Write-BuildLog ("Note: Certificate provider setup may need manual configuration: {0}" -f $_) -Level Warning
|
||||
}
|
||||
|
||||
# Project root folder (now set to current script folder for local builds)
|
||||
$ProjectRoot = $PSScriptRoot
|
||||
$UserFolder = Join-Path $ProjectRoot '.user'
|
||||
if (-not (Test-Path $UserFolder)) { New-Item -ItemType Directory -Path $UserFolder | Out-Null }
|
||||
|
||||
# Certificate file paths using configuration
|
||||
$prefix = $script:Config.CertPrefix
|
||||
$CertThumbFile, $CertCerFile = @('.thumbprint', '.cer') |
|
||||
ForEach-Object { Join-Path $UserFolder "$prefix.certificate.sample$_" }
|
||||
|
||||
# Clean option: remove bin/obj and uninstall existing sparse package if present
|
||||
if ($Clean) {
|
||||
Write-BuildLog "Cleaning build artifacts..." -Level Info
|
||||
'bin','obj' | ForEach-Object {
|
||||
$target = Join-Path $ProjectRoot $_
|
||||
if (Test-Path $target) { Remove-Item $target -Recurse -Force }
|
||||
}
|
||||
Write-BuildLog "Attempting to remove existing sparse package (best effort)" -Level Info
|
||||
try { Get-AppxPackage -Name $script:Config.IdentityName | Remove-AppxPackage } catch {}
|
||||
}
|
||||
|
||||
# Force certificate regeneration if requested
|
||||
if ($ForceCert -and (Test-Path $UserFolder)) {
|
||||
Write-BuildLog "ForceCert specified: removing existing certificate artifacts..." -Level Warning
|
||||
Remove-Item $UserFolder -Recurse -Force
|
||||
New-Item -ItemType Directory -Path $UserFolder | Out-Null
|
||||
}
|
||||
|
||||
# Ensure dev cert (development only; not for production use) - skip if NoSign specified
|
||||
$needNewCert = -not $NoSign -and (-not (Test-Path $CertThumbFile) -or $ForceCert -or -not (Test-CertificateValidity -ThumbprintFile $CertThumbFile))
|
||||
|
||||
if ($needNewCert) {
|
||||
Write-BuildLog "Generating development certificate (prefix=$($script:Config.CertPrefix))..." -Level Info
|
||||
|
||||
# Clear stale files in the certificate cache
|
||||
if (Test-Path $UserFolder) {
|
||||
Get-ChildItem -Path $UserFolder | ForEach-Object {
|
||||
if ($_.PSIsContainer) {
|
||||
Remove-Item $_.FullName -Recurse -Force
|
||||
} else {
|
||||
Remove-Item $_.FullName -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-not (Test-Path $UserFolder)) {
|
||||
New-Item -ItemType Directory -Path $UserFolder | Out-Null
|
||||
}
|
||||
|
||||
$now = Get-Date
|
||||
$expiration = $now.AddMonths($script:Config.CertValidMonths)
|
||||
# Subject MUST match <Identity Publisher="..."> inside AppxManifest.xml
|
||||
$friendlyName = "PowerToys Dev Sparse Cert Create=$now"
|
||||
$keyFriendly = "PowerToys Dev Sparse Key Create=$now"
|
||||
|
||||
$certStore = 'cert:\CurrentUser\My'
|
||||
$ekuOid = '2.5.29.37'
|
||||
$ekuValue = '1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13'
|
||||
$eku = "$ekuOid={text}$ekuValue"
|
||||
|
||||
$cert = New-SelfSignedCertificate -CertStoreLocation $certStore `
|
||||
-NotAfter $expiration `
|
||||
-Subject $script:Config.CertSubject `
|
||||
-FriendlyName $friendlyName `
|
||||
-KeyFriendlyName $keyFriendly `
|
||||
-KeyDescription $keyFriendly `
|
||||
-TextExtension $eku
|
||||
|
||||
# Export certificate files
|
||||
Set-Content -Path $CertThumbFile -Value $cert.Thumbprint -Force
|
||||
Export-Certificate -Cert $cert -FilePath $CertCerFile -Force | Out-Null
|
||||
}
|
||||
|
||||
# Determine output directory - using PowerToys standard structure
|
||||
# Navigate to PowerToys root (two levels up from src/PackageIdentity)
|
||||
$PowerToysRoot = Split-Path (Split-Path $ProjectRoot -Parent) -Parent
|
||||
$outDir = Join-Path $PowerToysRoot "$Platform\$Configuration"
|
||||
|
||||
if (-not (Test-Path $outDir)) {
|
||||
Write-BuildLog "Creating output directory: $outDir" -Level Info
|
||||
New-Item -ItemType Directory -Path $outDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# PackageIdentity folder (this script location) containing the sparse manifest and assets
|
||||
$sparseDir = $PSScriptRoot
|
||||
$manifestPath = Join-Path $sparseDir 'AppxManifest.xml'
|
||||
if (-not (Test-Path $manifestPath)) { throw "Missing AppxManifest.xml in PackageIdentity folder: $manifestPath" }
|
||||
|
||||
$versionPropsPath = Join-Path $PowerToysRoot 'src\Version.props'
|
||||
$targetManifestVersion = $null
|
||||
$versionCandidate = $null
|
||||
if (Test-Path $versionPropsPath) {
|
||||
try {
|
||||
[xml]$propsXml = Get-Content -Path $versionPropsPath -Raw
|
||||
$versionCandidate = $propsXml.Project.PropertyGroup.Version
|
||||
} catch {
|
||||
Write-BuildLog ("Unable to read version from {0}: {1}" -f $versionPropsPath, $_) -Level Warning
|
||||
}
|
||||
} else {
|
||||
Write-BuildLog "Version.props not found at $versionPropsPath; manifest version will remain unchanged." -Level Warning
|
||||
}
|
||||
|
||||
if ($versionCandidate) {
|
||||
$targetManifestVersion = $versionCandidate.Trim()
|
||||
if (($targetManifestVersion -split '\.').Count -lt 4) {
|
||||
$targetManifestVersion = "$targetManifestVersion.0"
|
||||
}
|
||||
Write-BuildLog "Using sparse package version from Version.props: $targetManifestVersion" -Level Info
|
||||
} else {
|
||||
Write-BuildLog "No version value provided; manifest version will remain unchanged." -Level Info
|
||||
}
|
||||
|
||||
# Find MakeAppx.exe from Windows SDK
|
||||
try {
|
||||
$hostSdkArchitecture = if ([System.Environment]::Is64BitProcess) { 'x64' } else { 'x86' }
|
||||
$makeAppxPath = Find-WindowsSDKTool -ToolName "makeappx.exe" -Architecture $hostSdkArchitecture
|
||||
} catch {
|
||||
Write-Error "MakeAppx.exe not found. Please ensure Windows SDK is installed."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Pack sparse MSIX from PackageIdentity folder
|
||||
$msixPath = Join-Path $outDir $script:Config.SparseMsixName
|
||||
|
||||
# Clean up existing MSIX file
|
||||
if (Test-Path $msixPath) {
|
||||
Write-BuildLog "Removing existing MSIX file..." -Level Info
|
||||
try {
|
||||
Remove-Item $msixPath -Force -ErrorAction Stop
|
||||
Write-BuildLog "Successfully removed existing MSIX file" -Level Success
|
||||
} catch {
|
||||
Write-BuildLog ("Warning: Could not remove existing MSIX file: {0}" -f $_) -Level Warning
|
||||
}
|
||||
}
|
||||
|
||||
# Create a clean staging directory to avoid file lock issues
|
||||
$stagingDir = Join-Path $outDir "staging"
|
||||
if (Test-Path $stagingDir) {
|
||||
Remove-Item $stagingDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
New-Item -ItemType Directory -Path $stagingDir -Force | Out-Null
|
||||
|
||||
try {
|
||||
Write-BuildLog "Creating clean staging directory for packaging..." -Level Info
|
||||
|
||||
# Copy only essential files to staging directory to avoid file locks
|
||||
$essentialFiles = @(
|
||||
"AppxManifest.xml"
|
||||
"Images\*"
|
||||
)
|
||||
|
||||
foreach ($filePattern in $essentialFiles) {
|
||||
$sourcePath = Join-Path $sparseDir $filePattern
|
||||
$relativePath = $filePattern
|
||||
|
||||
if ($filePattern.Contains('\')) {
|
||||
$targetDir = Join-Path $stagingDir (Split-Path $relativePath -Parent)
|
||||
if (-not (Test-Path $targetDir)) {
|
||||
New-Item -ItemType Directory -Path $targetDir -Force | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
if ($filePattern.EndsWith('\*')) {
|
||||
# Copy directory contents
|
||||
$sourceDir = $sourcePath.TrimEnd('\*')
|
||||
$targetDir = Join-Path $stagingDir (Split-Path $relativePath.TrimEnd('\*') -Parent)
|
||||
if (Test-Path $sourceDir) {
|
||||
Copy-Item -Path "$sourceDir\*" -Destination $targetDir -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
} else {
|
||||
# Copy single file
|
||||
$targetPath = Join-Path $stagingDir $relativePath
|
||||
if (Test-Path $sourcePath) {
|
||||
Copy-Item -Path $sourcePath -Destination $targetPath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Ensure publisher matches the dev certificate for local builds
|
||||
$manifestStagingPath = Join-Path $stagingDir 'AppxManifest.xml'
|
||||
$shouldUseDevPublisher = -not $isCIBuild
|
||||
if (Test-Path $manifestStagingPath) {
|
||||
try {
|
||||
[xml]$manifestXml = Get-Content -Path $manifestStagingPath -Raw
|
||||
$identityNode = $manifestXml.Package.Identity
|
||||
$manifestChanged = $false
|
||||
if ($identityNode) {
|
||||
$currentPublisherHint = $identityNode.Publisher
|
||||
}
|
||||
|
||||
if ($identityNode) {
|
||||
if ($targetManifestVersion -and $identityNode.Version -ne $targetManifestVersion) {
|
||||
Write-BuildLog "Updating manifest version to $targetManifestVersion" -Level Info
|
||||
$identityNode.SetAttribute('Version', $targetManifestVersion)
|
||||
$manifestChanged = $true
|
||||
}
|
||||
|
||||
if ($shouldUseDevPublisher -and $identityNode.Publisher -ne $script:Config.CertSubject) {
|
||||
Write-BuildLog "Updating manifest publisher for local build" -Level Warning
|
||||
$identityNode.SetAttribute('Publisher', $script:Config.CertSubject)
|
||||
$manifestChanged = $true
|
||||
}
|
||||
$currentPublisherHint = $identityNode.Publisher
|
||||
}
|
||||
|
||||
if ($manifestChanged) {
|
||||
$manifestXml.Save($manifestStagingPath)
|
||||
}
|
||||
} catch {
|
||||
Write-BuildLog ("Unable to adjust manifest metadata: {0}" -f $_) -Level Warning
|
||||
}
|
||||
}
|
||||
|
||||
Write-BuildLog "Staging directory prepared with essential files only" -Level Success
|
||||
|
||||
# Pack MSIX using staging directory
|
||||
Write-BuildLog "Packing sparse MSIX ($($script:Config.SparseMsixName)) from staging -> $msixPath" -Level Info
|
||||
|
||||
& $makeAppxPath pack /d $stagingDir /p $msixPath /nv /o
|
||||
|
||||
if ($LASTEXITCODE -eq 0 -and (Test-Path $msixPath)) {
|
||||
Write-BuildLog "MSIX packaging completed successfully" -Level Success
|
||||
} else {
|
||||
Write-BuildLog "MakeAppx failed with exit code $LASTEXITCODE" -Level Error
|
||||
exit 1
|
||||
}
|
||||
} finally {
|
||||
# Clean up staging directory
|
||||
if (Test-Path $stagingDir) {
|
||||
try {
|
||||
Remove-Item $stagingDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Write-BuildLog "Cleaned up staging directory" -Level Info
|
||||
} catch {
|
||||
Write-BuildLog ("Warning: Could not clean up staging directory: {0}" -f $_) -Level Warning
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Sign package (skip if NoSign specified for CI scenarios)
|
||||
if ($NoSign) {
|
||||
Write-BuildLog "Skipping signing (NoSign specified for CI build)" -Level Warning
|
||||
} else {
|
||||
# Use certificate thumbprint for signing (safer, no password)
|
||||
$certThumbprint = (Get-Content -Path $CertThumbFile -Raw).Trim()
|
||||
try {
|
||||
$signToolPath = Find-WindowsSDKTool -ToolName "signtool.exe"
|
||||
} catch {
|
||||
Write-Error "SignTool.exe not found. Please ensure Windows SDK is installed."
|
||||
exit 1
|
||||
}
|
||||
Write-BuildLog "Signing sparse MSIX using cert thumbprint $certThumbprint..." -Level Info
|
||||
& $signToolPath sign /fd SHA256 /sha1 $certThumbprint $msixPath
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Warning "SignTool failed (exit $LASTEXITCODE). Ensure the certificate is in CurrentUser\\My and try -ForceCert if needed."
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
}
|
||||
|
||||
$publisherHintFile = Join-Path $UserFolder "$($script:Config.CertPrefix).publisher.txt"
|
||||
try {
|
||||
Set-Content -Path $publisherHintFile -Value $currentPublisherHint -Force -NoNewline
|
||||
} catch {
|
||||
Write-BuildLog ("Unable to write publisher hint: {0}" -f $_) -Level Warning
|
||||
}
|
||||
|
||||
Write-BuildLog "`nPackage created: $msixPath" -Level Success
|
||||
|
||||
if ($NoSign) {
|
||||
Write-BuildLog "UNSIGNED package created for CI build. Sign before deployment." -Level Warning
|
||||
} else {
|
||||
Write-BuildLog "Install the dev certificate (once): $CertCerFile" -Level Info
|
||||
Write-BuildLog "Identity Name: $($script:Config.IdentityName)" -Level Info
|
||||
}
|
||||
|
||||
Write-BuildLog "Register sparse package:" -Level Info
|
||||
Write-BuildLog " Add-AppxPackage -Path `"$msixPath`" -ExternalLocation `"$outDir`"" -Level Warning
|
||||
Write-BuildLog "(If already installed and you changed manifest only): Add-AppxPackage -Register `"$manifestPath`" -ExternalLocation `"$outDir`" -ForceApplicationShutdown" -Level Warning
|
||||
@@ -1,43 +0,0 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Determine whether a given process (by PID) runs with an MSIX/UWP package identity.
|
||||
.DESCRIPTION
|
||||
Calls the Windows API GetPackageFullName to check if the target process executes under an MSIX/Sparse App/UWP package identity.
|
||||
Returns the package full name when identity is present, or "No package identity" otherwise.
|
||||
.PARAMETER ProcessId
|
||||
The process ID to inspect.
|
||||
.EXAMPLE
|
||||
.\Check-ProcessIdentity.ps1 -pid 12345
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[int]$ProcessId
|
||||
)
|
||||
|
||||
Add-Type -TypeDefinition @'
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
public class P {
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern IntPtr OpenProcess(uint a, bool b, int p);
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern bool CloseHandle(IntPtr h);
|
||||
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
|
||||
public static extern int GetPackageFullName(IntPtr h, ref int l, StringBuilder b);
|
||||
public static string G(int pid) {
|
||||
IntPtr h = OpenProcess(0x1000, false, pid);
|
||||
if (h == IntPtr.Zero) return "Failed to open process";
|
||||
int len = 0;
|
||||
GetPackageFullName(h, ref len, null);
|
||||
if (len == 0) { CloseHandle(h); return "No package identity"; }
|
||||
var sb = new StringBuilder(len);
|
||||
int r = GetPackageFullName(h, ref len, sb);
|
||||
CloseHandle(h);
|
||||
return r == 0 ? sb.ToString() : "Error:" + r;
|
||||
}
|
||||
}
|
||||
'@
|
||||
|
||||
$result = [P]::G($ProcessId)
|
||||
Write-Output $result
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 68 B |
Binary file not shown.
|
Before Width: | Height: | Size: 68 B |
Binary file not shown.
|
Before Width: | Height: | Size: 68 B |
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!-- CI Build Configuration -->
|
||||
<PropertyGroup Condition="'$(CIBuild)'=='true'">
|
||||
<ForceCIPackaging>true</ForceCIPackaging>
|
||||
<NoSignCI>true</NoSignCI>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Target to generate sparse MSIX package -->
|
||||
<Target Name="GenerateSparsePackage" BeforeTargets="PrepareForBuild">
|
||||
<!-- Use NoSign only for CI builds to avoid certificate issues on hosted agents -->
|
||||
<PropertyGroup>
|
||||
<NoSignParam Condition="'$(NoSignCI)' == 'true'">-NoSign</NoSignParam>
|
||||
<NoSignParam Condition="'$(NoSignCI)' != 'true'"></NoSignParam>
|
||||
<CIBuildParam Condition="'$(CIBuild)' == 'true'">-CIBuild</CIBuildParam>
|
||||
<CIBuildParam Condition="'$(CIBuild)' != 'true'"></CIBuildParam>
|
||||
</PropertyGroup>
|
||||
|
||||
<Exec Command="pwsh -NonInteractive -ExecutionPolicy Bypass -File "$(MSBuildThisFileDirectory)BuildSparsePackage.ps1" -Platform $(Platform) -Configuration $(Configuration) $(NoSignParam) $(CIBuildParam)"
|
||||
ContinueOnError="false"
|
||||
WorkingDirectory="$(MSBuildThisFileDirectory)" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}</ProjectGuid>
|
||||
<RootNamespace>PackageIdentity</RootNamespace>
|
||||
<ProjectName>PackageIdentity</ProjectName>
|
||||
<UseFastUpToDateCheck>false</UseFastUpToDateCheck>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Utility</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Utility</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Utility</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Utility</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</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" />
|
||||
<Import Project="..\Solution.props" />
|
||||
</ImportGroup>
|
||||
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="AppxManifest.xml" />
|
||||
<None Include="BuildSparsePackage.ps1" />
|
||||
<None Include="BuildSparsePackage.cmd" />
|
||||
<None Include="Check-ProcessIdentity.ps1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Image Include="Images\Square150x150Logo.png">
|
||||
<Filter>Images</Filter>
|
||||
</Image>
|
||||
<Image Include="Images\Square44x44Logo.png">
|
||||
<Filter>Images</Filter>
|
||||
</Image>
|
||||
<Image Include="Images\StoreLogo.png">
|
||||
<Filter>Images</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Images">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>png;jpg;jpeg;gif;bmp;ico</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="AppxManifest.xml" />
|
||||
<None Include="BuildSparsePackage.ps1" />
|
||||
<None Include="BuildSparsePackage.cmd" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Images\Square150x150Logo.png">
|
||||
<Filter>Images</Filter>
|
||||
</Image>
|
||||
<Image Include="Images\Square44x44Logo.png">
|
||||
<Filter>Images</Filter>
|
||||
</Image>
|
||||
<Image Include="Images\StoreLogo.png">
|
||||
<Filter>Images</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,90 +0,0 @@
|
||||
# PowerToys sparse package identity
|
||||
|
||||
This document describes how to build, sign, register, and consume the shared sparse MSIX package that grants package identity to select Win32 components of PowerToys.
|
||||
|
||||
## Package overview
|
||||
|
||||
The sparse package lives under `src/PackageIdentity`. It produces a payload-free MSIX whose `Identity` matches `Microsoft.PowerToys.SparseApp`. The manifest contains one entry per Win32 surface that should run with identity (for example Settings, PowerOCR, Image Resizer).
|
||||
|
||||
> The MSIX contains only metadata. When the package is registered you must point `-ExternalLocation` to the output folder that hosts the Win32 binaries (for example `x64\Release`).
|
||||
|
||||
## Building the sparse package locally
|
||||
|
||||
Two options are available:
|
||||
|
||||
- Build the utility project from Visual Studio: `PackageIdentity.vcxproj` defines a `GenerateSparsePackage` target that runs before `PrepareForBuild` and invokes the helper script automatically.
|
||||
- Invoke the helper script directly from PowerShell:
|
||||
|
||||
```powershell
|
||||
$repoRoot = "C:/git/PowerToys"
|
||||
pwsh "$repoRoot/src/PackageIdentity/BuildSparsePackage.ps1" -Platform x64 -Configuration Release
|
||||
```
|
||||
|
||||
Supported switches:
|
||||
|
||||
- `-Clean` removes previous `bin`/`obj` outputs and uninstalls existing installation.
|
||||
- `-ForceCert` regenerates the local dev certificate (.pfx/.cer/.pwd/.thumbprint) under `src/PackageIdentity/.user`.
|
||||
- `-NoSign` skips signing. The MSIX still builds but must be signed before deployment.
|
||||
- `-CIBuild` (or setting `$env:CIBuild = 'true'`) keeps the manifest publisher intact and skips the local cert substitution.
|
||||
|
||||
The script determines the proper `makeappx.exe` for the host build machine (x64 on typical developer boxes) and creates `PowerToysSparse.msix` in `{repo}\<Platform>\<Configuration>`.
|
||||
|
||||
> After packaging finishes, the helper also emits `src/PackageIdentity/.user/PowerToysSparse.publisher.txt`. This file mirrors the publisher string Windows will see once the sparse package is registered, which downstream projects can read to stay in sync when generating their own manifests.
|
||||
|
||||
## Local signing basics
|
||||
|
||||
When `-NoSign` is not used the script generates (or reuses) a development certificate and signs the package via `signtool.exe`:
|
||||
|
||||
1. Artifacts are stored in `src/PackageIdentity/.user/PowerToysSparse.certificate.sample.*` (`.cer` and `.thumbprint`).
|
||||
2. Install the `.cer` into `CurrentUser` → `TrustedPeople` (and `TrustedRoot`, if necessary) so Windows trusts the signature:
|
||||
|
||||
```powershell
|
||||
$repoRoot = "C:/git/PowerToys"
|
||||
Import-Certificate -FilePath "$repoRoot/src/PackageIdentity/.user/PowerToysSparse.certificate.sample.cer" -CertStoreLocation Cert:\CurrentUser\TrustedPeople
|
||||
```
|
||||
|
||||
3. The private key stays in the current user's personal certificate store.
|
||||
|
||||
## Registering or unregistering the package
|
||||
|
||||
After `PowerToysSparse.msix` is generated:
|
||||
|
||||
```powershell
|
||||
# First time registration
|
||||
$repoRoot = "C:/git/PowerToys"
|
||||
$outputRoot = Join-Path $repoRoot "x64/Release"
|
||||
Add-AppxPackage -Path (Join-Path $outputRoot "PowerToysSparse.msix") -ExternalLocation $outputRoot
|
||||
|
||||
# Re-register after manifest tweaks only
|
||||
Add-AppxPackage -Register (Join-Path $repoRoot "src/PackageIdentity/AppxManifest.xml") -ExternalLocation $outputRoot -ForceApplicationShutdown
|
||||
|
||||
# Remove the sparse identity
|
||||
Get-AppxPackage -Name Microsoft.PowerToys.SparseApp | Remove-AppxPackage
|
||||
```
|
||||
|
||||
`-ExternalLocation` should match the output folder that contains the Win32 executables declared in the manifest. Re-run registration whenever the manifest or executable layout changes.
|
||||
|
||||
## CI-specific guidance
|
||||
|
||||
- Pass `-CIBuild` to `BuildSparsePackage.ps1` (or build with `msbuild PackageIdentity.vcxproj /p:CIBuild=true`). This prevents the script from rewriting the manifest publisher to the local dev certificate subject.
|
||||
- The project automatically adds `-NoSign` only when `$(CIBuild)` is `true`. Local Debug and Release builds are signed with the development certificate.
|
||||
- Make sure the agent trusts whichever certificate signs the package. If the package remains unsigned (`-NoSign`) it cannot be installed on test machines until it is signed.
|
||||
|
||||
## Consuming the identity from other components
|
||||
|
||||
1. Add a new `<Application>` entry inside `src/PackageIdentity/AppxManifest.xml`. Use a unique `Id` (for example `PowerToys.MyModuleUI`) and set `Executable` to the Win32 binary relative to the `-ExternalLocation` root.
|
||||
2. Ensure the binary is copied into the platform/configuration output folder (`x64\Release`, `ARM64\Debug`, etc.) so the sparse package can locate it.
|
||||
3. Embed a sparse identity manifest in the Win32 binary so it binds to the MSIX identity at runtime. The manifest must declare an `<msix>` element with `packageName="Microsoft.PowerToys.SparseApp"`, `applicationId` matching the `<Application Id>`, and a `publisher` that matches the sparse package. Keep the manifest’s publisher in sync with `src/PackageIdentity/.user/PowerToysSparse.publisher.txt` (emitted by `BuildSparsePackage.ps1`). See `src/modules/imageresizer/ui/ImageResizerUI.csproj` for an example that points `ApplicationManifest` to `ImageResizerUI.dev.manifest` for local builds and switches to `ImageResizerUI.prod.manifest` when `$(CIBuild)` is `true`.
|
||||
4. Register or re-register the sparse package so Windows learns about the new application Id.
|
||||
5. To launch the Win32 surface with identity, use the `shell:AppsFolder` activation form (for example: `shell:AppsFolder\Microsoft.PowerToys.SparseApp_<PackageFamilyName>!PowerToys.MyModuleUI`) or activate it via `IApplicationActivationManager::ActivateApplication` using the same AppUserModelID.
|
||||
|
||||
- For locally built packages, resolve the `<PackageFamilyName>` with `Get-AppxPackage -Name Microsoft.PowerToys.SparseApp | Select-Object -ExpandProperty PackageFamilyName`.
|
||||
- Store-distributed builds use `Microsoft.PowerToys.SparseApp_8wekyb3d8bbwe`. Local developer builds created by this script typically use a different family name derived from the dev certificate.
|
||||
|
||||
6. Context menu handlers or other launchers should fall back to the unpackaged executable path for environments where the sparse package is not present.
|
||||
|
||||
## Troubleshooting tips
|
||||
|
||||
- `Program 'makeappx.exe' failed to run`: make sure you are running an x64 PowerShell host. The script now chooses the appropriate makeappx automatically; update your repo if the log still points to an ARM64 binary.
|
||||
- `HRESULT 0x800B0109 (trust failure)`: install the development certificate into both `TrustedPeople` and `TrustedRoot` stores for the current user.
|
||||
- Stale registration: remove the package with `Remove-AppxPackage` and re-run the script with `-Clean` to rebuild from scratch.
|
||||
@@ -9,6 +9,12 @@
|
||||
<RootNamespace>CalculatorEngineCommon</RootNamespace>
|
||||
<AppxPackage>false</AppxPackage>
|
||||
</PropertyGroup>
|
||||
<!-- BEGIN common.build.pre.props -->
|
||||
<PropertyGroup Label="Configuration">
|
||||
<EnableHybridCRT>true</EnableHybridCRT>
|
||||
<UseCrtSDKReferenceStaticWarning Condition="'$(EnableHybridCRT)'=='true'">false</UseCrtSDKReferenceStaticWarning>
|
||||
</PropertyGroup>
|
||||
<!-- END common.build.pre.props -->
|
||||
<!-- BEGIN cppwinrt.build.pre.props -->
|
||||
<PropertyGroup Label="Globals">
|
||||
<CppWinRTEnabled>true</CppWinRTEnabled>
|
||||
@@ -19,9 +25,11 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<MinimalCoreWin>true</MinimalCoreWin>
|
||||
<AppContainerApplication>false</AppContainerApplication>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<WindowsStoreApp>true</WindowsStoreApp>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<UseCrtSDKReference Condition="'$(EnableHybridCRT)'=='true'">false</UseCrtSDKReference>
|
||||
<!-- The SDK reference breaks the Hybrid CRT -->
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<!-- We have to use the Desktop platform for Hybrid CRT to work. -->
|
||||
@@ -140,5 +148,43 @@
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target> <!-- END common.build.post.props -->
|
||||
</Target>
|
||||
<!-- BEGIN common.build.post.props -->
|
||||
<!--
|
||||
The Hybrid CRT model statically links the runtime and STL and dynamically
|
||||
links the UCRT instead of the VC++ CRT. The UCRT ships with Windows.
|
||||
WinAppSDK asserts that this is "supported according to the CRT maintainer."
|
||||
|
||||
This must come before Microsoft.Cpp.targets because it manipulates ClCompile.RuntimeLibrary.
|
||||
-->
|
||||
<ItemDefinitionGroup Condition="'$(EnableHybridCRT)'=='true' and '$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<!-- We use MultiThreadedDebug, rather than MultiThreadedDebugDLL, to avoid DLL dependencies on VCRUNTIME140d.dll and MSVCP140d.dll. -->
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<!-- Link statically against the runtime and STL, but link dynamically against the CRT by ignoring the static CRT
|
||||
lib and instead linking against the Universal CRT DLL import library. This "hybrid" linking mechanism is
|
||||
supported according to the CRT maintainer. Dynamic linking against the CRT makes the binaries a bit smaller
|
||||
than they would otherwise be if the CRT, runtime, and STL were all statically linked in. -->
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries);libucrtd.lib</IgnoreSpecificDefaultLibraries>
|
||||
<AdditionalOptions>%(AdditionalOptions) /defaultlib:ucrtd.lib</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(EnableHybridCRT)'=='true' and ('$(Configuration)'=='Release' or '$(Configuration)'=='AuditMode')">
|
||||
<ClCompile>
|
||||
<!-- We use MultiThreaded, rather than MultiThreadedDLL, to avoid DLL dependencies on VCRUNTIME140.dll and MSVCP140.dll. -->
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<!-- Link statically against the runtime and STL, but link dynamically against the CRT by ignoring the static CRT
|
||||
lib and instead linking against the Universal CRT DLL import library. This "hybrid" linking mechanism is
|
||||
supported according to the CRT maintainer. Dynamic linking against the CRT makes the binaries a bit smaller
|
||||
than they would otherwise be if the CRT, runtime, and STL were all statically linked in. -->
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries);libucrt.lib</IgnoreSpecificDefaultLibraries>
|
||||
<AdditionalOptions>%(AdditionalOptions) /defaultlib:ucrt.lib</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<!-- END common.build.post.props -->
|
||||
</Project>
|
||||
@@ -112,10 +112,6 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMousePointerCrosshairsEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredCursorWrapEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredCursorWrapEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredPowerRenameEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredPowerRenameEnabledValue());
|
||||
@@ -196,38 +192,6 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteOnlineAIModelsValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetAllowedAdvancedPasteOpenAIValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteOpenAIValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetAllowedAdvancedPasteAzureOpenAIValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteAzureOpenAIValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetAllowedAdvancedPasteAzureAIInferenceValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteAzureAIInferenceValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetAllowedAdvancedPasteMistralValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteMistralValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetAllowedAdvancedPasteGoogleValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteGoogleValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetAllowedAdvancedPasteAnthropicValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteAnthropicValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetAllowedAdvancedPasteOllamaValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteOllamaValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetAllowedAdvancedPasteFoundryLocalValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteFoundryLocalValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredNewPlusEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredNewPlusEnabledValue());
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetConfiguredMouseHighlighterEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMouseJumpEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMousePointerCrosshairsEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCursorWrapEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredPowerRenameEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredPowerLauncherEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQuickAccentEnabledValue();
|
||||
@@ -55,14 +54,6 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetConfiguredQoiPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQoiThumbnailsEnabledValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteOnlineAIModelsValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteOpenAIValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteAzureOpenAIValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteAzureAIInferenceValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteMistralValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteGoogleValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteAnthropicValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteOllamaValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteFoundryLocalValue();
|
||||
static GpoRuleConfigured GetConfiguredNewPlusEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredWorkspacesEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbClipboardSharingEnabledValue();
|
||||
|
||||
@@ -38,7 +38,6 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetConfiguredMouseHighlighterEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMouseJumpEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMousePointerCrosshairsEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCursorWrapEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMouseWithoutBordersEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredPowerRenameEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredPowerLauncherEnabledValue();
|
||||
@@ -59,14 +58,6 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetConfiguredQoiPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQoiThumbnailsEnabledValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteOnlineAIModelsValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteOpenAIValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteAzureOpenAIValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteAzureAIInferenceValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteMistralValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteGoogleValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteAnthropicValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteOllamaValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteFoundryLocalValue();
|
||||
static GpoRuleConfigured GetConfiguredNewPlusEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredWorkspacesEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbClipboardSharingEnabledValue();
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
// 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.
|
||||
|
||||
namespace LanguageModelProvider.FoundryLocal;
|
||||
|
||||
internal sealed record FoundryCachedModel(string Name, string? Id);
|
||||
@@ -1,61 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LanguageModelProvider.FoundryLocal;
|
||||
|
||||
internal sealed record FoundryCatalogModel
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("displayName")]
|
||||
public string DisplayName { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("providerType")]
|
||||
public string ProviderType { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("uri")]
|
||||
public string Uri { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("version")]
|
||||
public string Version { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("modelType")]
|
||||
public string ModelType { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("promptTemplate")]
|
||||
public PromptTemplate PromptTemplate { get; init; } = default!;
|
||||
|
||||
[JsonPropertyName("publisher")]
|
||||
public string Publisher { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("task")]
|
||||
public string Task { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("runtime")]
|
||||
public Runtime Runtime { get; init; } = default!;
|
||||
|
||||
[JsonPropertyName("fileSizeMb")]
|
||||
public long FileSizeMb { get; init; }
|
||||
|
||||
[JsonPropertyName("modelSettings")]
|
||||
public ModelSettings ModelSettings { get; init; } = default!;
|
||||
|
||||
[JsonPropertyName("alias")]
|
||||
public string Alias { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("supportsToolCalling")]
|
||||
public bool SupportsToolCalling { get; init; }
|
||||
|
||||
[JsonPropertyName("license")]
|
||||
public string License { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("licenseDescription")]
|
||||
public string LicenseDescription { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("parentModelUri")]
|
||||
public string ParentModelUri { get; init; } = string.Empty;
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
// 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 ManagedCommon;
|
||||
using Microsoft.AI.Foundry.Local;
|
||||
|
||||
namespace LanguageModelProvider.FoundryLocal;
|
||||
|
||||
internal sealed class FoundryClient
|
||||
{
|
||||
public static async Task<FoundryClient?> CreateAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogInfo("[FoundryClient] Creating Foundry Local client");
|
||||
|
||||
var manager = new FoundryLocalManager();
|
||||
|
||||
// Check if service is already running
|
||||
if (manager.IsServiceRunning)
|
||||
{
|
||||
Logger.LogInfo("[FoundryClient] Foundry service is already running");
|
||||
return new FoundryClient(manager);
|
||||
}
|
||||
|
||||
// Start the service using SDK's method
|
||||
Logger.LogInfo("[FoundryClient] Starting Foundry service using manager.StartServiceAsync()");
|
||||
await manager.StartServiceAsync().ConfigureAwait(false);
|
||||
|
||||
Logger.LogInfo("[FoundryClient] Foundry service started successfully");
|
||||
return new FoundryClient(manager);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"[FoundryClient] Error creating client: {ex.Message}");
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
Logger.LogError($"[FoundryClient] Inner exception: {ex.InnerException.Message}");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly FoundryLocalManager _foundryManager;
|
||||
private readonly List<FoundryCatalogModel> _catalogModels = [];
|
||||
|
||||
private FoundryClient(FoundryLocalManager foundryManager)
|
||||
{
|
||||
_foundryManager = foundryManager;
|
||||
}
|
||||
|
||||
public Task<string?> GetServiceUrl()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Task.FromResult(_foundryManager.Endpoint?.ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Task.FromResult<string?>(null);
|
||||
}
|
||||
}
|
||||
|
||||
public Uri? GetServiceUri()
|
||||
{
|
||||
try
|
||||
{
|
||||
return _foundryManager.ServiceUri;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<FoundryCatalogModel>> ListCatalogModels()
|
||||
{
|
||||
if (_catalogModels.Count > 0)
|
||||
{
|
||||
return _catalogModels;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Logger.LogInfo("[FoundryClient] Listing catalog models");
|
||||
var models = await _foundryManager.ListCatalogModelsAsync().ConfigureAwait(false);
|
||||
|
||||
if (models != null)
|
||||
{
|
||||
foreach (var model in models)
|
||||
{
|
||||
_catalogModels.Add(new FoundryCatalogModel
|
||||
{
|
||||
Name = model.ModelId ?? string.Empty,
|
||||
DisplayName = model.DisplayName ?? string.Empty,
|
||||
ProviderType = model.ProviderType ?? string.Empty,
|
||||
Uri = model.Uri ?? string.Empty,
|
||||
Version = model.Version ?? string.Empty,
|
||||
ModelType = model.ModelType ?? string.Empty,
|
||||
Publisher = model.Publisher ?? string.Empty,
|
||||
Task = model.Task ?? string.Empty,
|
||||
FileSizeMb = model.FileSizeMb,
|
||||
Alias = model.Alias ?? string.Empty,
|
||||
License = model.License ?? string.Empty,
|
||||
LicenseDescription = model.LicenseDescription ?? string.Empty,
|
||||
ParentModelUri = model.ParentModelUri ?? string.Empty,
|
||||
SupportsToolCalling = model.SupportsToolCalling,
|
||||
});
|
||||
}
|
||||
|
||||
Logger.LogInfo($"[FoundryClient] Found {_catalogModels.Count} catalog models");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"[FoundryClient] Error listing catalog models: {ex.Message}");
|
||||
|
||||
// Surfacing errors here prevents listing other providers; swallow and return cached list instead.
|
||||
}
|
||||
|
||||
return _catalogModels;
|
||||
}
|
||||
|
||||
public async Task<List<FoundryCachedModel>> ListCachedModels()
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogInfo("[FoundryClient] Listing cached models");
|
||||
var cachedModels = await _foundryManager.ListCachedModelsAsync().ConfigureAwait(false);
|
||||
var catalogModels = await ListCatalogModels().ConfigureAwait(false);
|
||||
|
||||
List<FoundryCachedModel> models = [];
|
||||
|
||||
foreach (var model in cachedModels)
|
||||
{
|
||||
var catalogModel = catalogModels.FirstOrDefault(m => m.Name == model.ModelId);
|
||||
var alias = catalogModel?.Alias ?? model.Alias;
|
||||
models.Add(new FoundryCachedModel(model.ModelId ?? string.Empty, alias));
|
||||
}
|
||||
|
||||
Logger.LogInfo($"[FoundryClient] Found {models.Count} cached models");
|
||||
return models;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"[FoundryClient] Error listing cached models: {ex.Message}");
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> IsModelLoaded(string modelId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var loadedModels = await _foundryManager.ListLoadedModelsAsync().ConfigureAwait(false);
|
||||
var isLoaded = loadedModels.Any(m => m.ModelId == modelId);
|
||||
Logger.LogInfo($"[FoundryClient] IsModelLoaded({modelId}): {isLoaded}");
|
||||
Logger.LogInfo($"[FoundryClient] Loaded models: {string.Join(", ", loadedModels.Select(m => m.ModelId))}");
|
||||
return isLoaded;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"[FoundryClient] IsModelLoaded exception: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> EnsureModelLoaded(string modelId)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogInfo($"[FoundryClient] EnsureModelLoaded called with: {modelId}");
|
||||
|
||||
// Check if already loaded
|
||||
if (await IsModelLoaded(modelId).ConfigureAwait(false))
|
||||
{
|
||||
Logger.LogInfo($"[FoundryClient] Model already loaded: {modelId}");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if model exists in cache
|
||||
var cachedModels = await ListCachedModels().ConfigureAwait(false);
|
||||
Logger.LogInfo($"[FoundryClient] Cached models: {string.Join(", ", cachedModels.Select(m => m.Name))}");
|
||||
|
||||
if (!cachedModels.Any(m => m.Name == modelId))
|
||||
{
|
||||
Logger.LogWarning($"[FoundryClient] Model not found in cache: {modelId}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the model
|
||||
Logger.LogInfo($"[FoundryClient] Loading model: {modelId}");
|
||||
await _foundryManager.LoadModelAsync(modelId).ConfigureAwait(false);
|
||||
|
||||
// Verify it's loaded
|
||||
var loaded = await IsModelLoaded(modelId).ConfigureAwait(false);
|
||||
Logger.LogInfo($"[FoundryClient] Model load result: {loaded}");
|
||||
return loaded;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"[FoundryClient] EnsureModelLoaded exception: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// 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.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LanguageModelProvider.FoundryLocal;
|
||||
|
||||
[JsonSourceGenerationOptions(
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
WriteIndented = false)]
|
||||
[JsonSerializable(typeof(FoundryCatalogModel))]
|
||||
[JsonSerializable(typeof(List<FoundryCatalogModel>))]
|
||||
internal sealed partial class FoundryJsonContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// 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.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LanguageModelProvider.FoundryLocal;
|
||||
|
||||
internal sealed record ModelSettings
|
||||
{
|
||||
// The sample shows an empty array; keep it open-ended.
|
||||
[JsonPropertyName("parameters")]
|
||||
public List<JsonElement> Parameters { get; init; } = [];
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LanguageModelProvider.FoundryLocal;
|
||||
|
||||
internal sealed record PromptTemplate
|
||||
{
|
||||
[JsonPropertyName("assistant")]
|
||||
public string Assistant { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("prompt")]
|
||||
public string Prompt { get; init; } = string.Empty;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LanguageModelProvider.FoundryLocal;
|
||||
|
||||
internal sealed record Runtime
|
||||
{
|
||||
[JsonPropertyName("deviceType")]
|
||||
public string DeviceType { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("executionProvider")]
|
||||
public string ExecutionProvider { get; init; } = string.Empty;
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
// 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.ClientModel;
|
||||
using LanguageModelProvider.FoundryLocal;
|
||||
using ManagedCommon;
|
||||
using Microsoft.Extensions.AI;
|
||||
using OpenAI;
|
||||
|
||||
namespace LanguageModelProvider;
|
||||
|
||||
public sealed class FoundryLocalModelProvider : ILanguageModelProvider
|
||||
{
|
||||
private IEnumerable<ModelDetails>? _downloadedModels;
|
||||
private FoundryClient? _foundryManager;
|
||||
private string? _serviceUrl;
|
||||
|
||||
public static FoundryLocalModelProvider Instance { get; } = new();
|
||||
|
||||
public string Name => "FoundryLocal";
|
||||
|
||||
public string ProviderDescription => "The model will run locally via Foundry Local";
|
||||
|
||||
public string UrlPrefix => "fl://";
|
||||
|
||||
public IChatClient? GetIChatClient(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogInfo($"[FoundryLocal] GetIChatClient called with url: {url}");
|
||||
InitializeAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"[FoundryLocal] Failed to initialize: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_serviceUrl) || _foundryManager == null)
|
||||
{
|
||||
Logger.LogError("[FoundryLocal] Service URL or manager is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract model ID from URL (format: fl://modelname)
|
||||
var modelId = url.Replace(UrlPrefix, string.Empty).Trim('/');
|
||||
if (string.IsNullOrWhiteSpace(modelId))
|
||||
{
|
||||
Logger.LogError("[FoundryLocal] Model ID is empty after extraction");
|
||||
return null;
|
||||
}
|
||||
|
||||
Logger.LogInfo($"[FoundryLocal] Extracted model ID: {modelId}");
|
||||
|
||||
// Ensure the model is loaded before returning chat client
|
||||
try
|
||||
{
|
||||
var isLoaded = _foundryManager.EnsureModelLoaded(modelId).GetAwaiter().GetResult();
|
||||
if (!isLoaded)
|
||||
{
|
||||
Logger.LogError($"[FoundryLocal] Failed to load model: {modelId}");
|
||||
return null;
|
||||
}
|
||||
|
||||
Logger.LogInfo($"[FoundryLocal] Model is loaded: {modelId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"[FoundryLocal] Exception ensuring model loaded: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Use ServiceUri instead of Endpoint since Endpoint already includes /v1
|
||||
var baseUri = _foundryManager.GetServiceUri();
|
||||
if (baseUri == null)
|
||||
{
|
||||
Logger.LogError("[FoundryLocal] Service URI is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
var endpointUri = new Uri($"{baseUri.ToString().TrimEnd('/')}/v1");
|
||||
Logger.LogInfo($"[FoundryLocal] Creating OpenAI client with endpoint: {endpointUri}");
|
||||
Logger.LogInfo($"[FoundryLocal] Model ID for chat client: {modelId}");
|
||||
|
||||
return new OpenAIClient(
|
||||
new ApiKeyCredential("none"),
|
||||
new OpenAIClientOptions { Endpoint = endpointUri })
|
||||
.GetChatClient(modelId)
|
||||
.AsIChatClient();
|
||||
}
|
||||
|
||||
public string GetIChatClientString(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
InitializeAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var modelId = url.Split('/').LastOrDefault();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_serviceUrl) || string.IsNullOrWhiteSpace(modelId))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return $"new OpenAIClient(new ApiKeyCredential(\"none\"), new OpenAIClientOptions{{ Endpoint = new Uri(\"{_serviceUrl}/v1\") }}).GetChatClient(\"{modelId}\").AsIChatClient()";
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ModelDetails>> GetModelsAsync(bool ignoreCached = false, CancellationToken cancelationToken = default)
|
||||
{
|
||||
if (ignoreCached)
|
||||
{
|
||||
Logger.LogInfo("[FoundryLocal] Ignoring cached models, resetting");
|
||||
Reset();
|
||||
}
|
||||
|
||||
await InitializeAsync(cancelationToken);
|
||||
|
||||
Logger.LogInfo($"[FoundryLocal] Returning {_downloadedModels?.Count() ?? 0} downloaded models");
|
||||
return _downloadedModels ?? [];
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
_downloadedModels = null;
|
||||
_ = InitializeAsync();
|
||||
}
|
||||
|
||||
private async Task InitializeAsync(CancellationToken cancelationToken = default)
|
||||
{
|
||||
if (_foundryManager != null && _downloadedModels != null && _downloadedModels.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInfo("[FoundryLocal] Initializing provider");
|
||||
_foundryManager ??= await FoundryClient.CreateAsync();
|
||||
|
||||
if (_foundryManager == null)
|
||||
{
|
||||
Logger.LogError("[FoundryLocal] Failed to create Foundry client");
|
||||
return;
|
||||
}
|
||||
|
||||
_serviceUrl ??= await _foundryManager.GetServiceUrl();
|
||||
Logger.LogInfo($"[FoundryLocal] Service URL: {_serviceUrl}");
|
||||
|
||||
var cachedModels = await _foundryManager.ListCachedModels();
|
||||
Logger.LogInfo($"[FoundryLocal] Found {cachedModels.Count} cached models");
|
||||
|
||||
List<ModelDetails> downloadedModels = [];
|
||||
|
||||
foreach (var model in cachedModels)
|
||||
{
|
||||
Logger.LogInfo($"[FoundryLocal] Adding unmatched cached model: {model.Name}");
|
||||
downloadedModels.Add(new ModelDetails
|
||||
{
|
||||
Id = $"fl-{model.Name}",
|
||||
Name = model.Name,
|
||||
Url = $"{UrlPrefix}{model.Name}",
|
||||
Description = $"{model.Name} running locally with Foundry Local",
|
||||
HardwareAccelerators = [HardwareAccelerator.FOUNDRYLOCAL],
|
||||
SupportedOnQualcomm = true,
|
||||
ProviderModelDetails = model,
|
||||
});
|
||||
}
|
||||
|
||||
_downloadedModels = downloadedModels;
|
||||
Logger.LogInfo($"[FoundryLocal] Initialization complete. Total downloaded models: {downloadedModels.Count}");
|
||||
}
|
||||
|
||||
public async Task<bool> IsAvailable()
|
||||
{
|
||||
Logger.LogInfo("[FoundryLocal] Checking availability");
|
||||
await InitializeAsync();
|
||||
var available = _foundryManager != null;
|
||||
Logger.LogInfo($"[FoundryLocal] Available: {available}");
|
||||
return available;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// 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.
|
||||
|
||||
namespace LanguageModelProvider;
|
||||
|
||||
public enum HardwareAccelerator
|
||||
{
|
||||
CPU,
|
||||
DML,
|
||||
QNN,
|
||||
WCRAPI,
|
||||
OLLAMA,
|
||||
OPENAI,
|
||||
FOUNDRYLOCAL,
|
||||
LEMONADE,
|
||||
NPU,
|
||||
GPU,
|
||||
VitisAI,
|
||||
OpenVINO,
|
||||
NvTensorRT,
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// 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.AI;
|
||||
|
||||
namespace LanguageModelProvider;
|
||||
|
||||
public interface ILanguageModelProvider
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
string UrlPrefix { get; }
|
||||
|
||||
string ProviderDescription { get; }
|
||||
|
||||
Task<IEnumerable<ModelDetails>> GetModelsAsync(bool ignoreCached = false, CancellationToken cancelationToken = default);
|
||||
|
||||
IChatClient? GetIChatClient(string url);
|
||||
|
||||
string GetIChatClientString(string url);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="..\..\Common.Dotnet.CsWinRT.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.AI" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.AI.Foundry.Local" />
|
||||
<PackageReference Include="OpenAI" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ManagedCommon\ManagedCommon.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,106 +0,0 @@
|
||||
// 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 Microsoft.Extensions.AI;
|
||||
|
||||
namespace LanguageModelProvider;
|
||||
|
||||
public sealed class LanguageModelService
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, ILanguageModelProvider> _providersByPrefix;
|
||||
|
||||
public LanguageModelService(IEnumerable<ILanguageModelProvider> providers)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(providers);
|
||||
|
||||
_providersByPrefix = new ConcurrentDictionary<string, ILanguageModelProvider>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var provider in providers)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(provider.UrlPrefix))
|
||||
{
|
||||
_providersByPrefix[provider.UrlPrefix] = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static LanguageModelService CreateDefault()
|
||||
{
|
||||
return new LanguageModelService(new[]
|
||||
{
|
||||
FoundryLocalModelProvider.Instance,
|
||||
});
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<ILanguageModelProvider> Providers => _providersByPrefix.Values.ToArray();
|
||||
|
||||
public bool RegisterProvider(ILanguageModelProvider provider)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(provider);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(provider.UrlPrefix))
|
||||
{
|
||||
throw new ArgumentException("Provider must supply a URL prefix.", nameof(provider));
|
||||
}
|
||||
|
||||
_providersByPrefix[provider.UrlPrefix] = provider;
|
||||
return true;
|
||||
}
|
||||
|
||||
public ILanguageModelProvider? GetProviderFor(string? modelReference)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(modelReference))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var provider in _providersByPrefix.Values)
|
||||
{
|
||||
if (modelReference.StartsWith(provider.UrlPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<ModelDetails>> GetModelsAsync(bool refresh = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
List<ModelDetails> models = [];
|
||||
|
||||
foreach (var provider in _providersByPrefix.Values)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var providerModels = await provider.GetModelsAsync(refresh, cancellationToken).ConfigureAwait(false);
|
||||
models.AddRange(providerModels);
|
||||
}
|
||||
|
||||
return models;
|
||||
}
|
||||
|
||||
public IChatClient? GetClient(ModelDetails model)
|
||||
{
|
||||
if (model is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var reference = !string.IsNullOrWhiteSpace(model.Url) ? model.Url : model.Id;
|
||||
return GetClient(reference);
|
||||
}
|
||||
|
||||
public IChatClient? GetClient(string? modelReference)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(modelReference))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var provider = GetProviderFor(modelReference);
|
||||
|
||||
return provider?.GetIChatClient(modelReference);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// 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.Generic;
|
||||
|
||||
namespace LanguageModelProvider;
|
||||
|
||||
public class ModelDetails
|
||||
{
|
||||
public string Id { get; set; } = string.Empty;
|
||||
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
public string Url { get; set; } = string.Empty;
|
||||
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
public long Size { get; set; }
|
||||
|
||||
public bool IsUserAdded { get; set; }
|
||||
|
||||
public string Icon { get; set; } = string.Empty;
|
||||
|
||||
public List<HardwareAccelerator> HardwareAccelerators { get; set; } = [];
|
||||
|
||||
public bool SupportedOnQualcomm { get; set; }
|
||||
|
||||
public string License { get; set; } = string.Empty;
|
||||
|
||||
public object? ProviderModelDetails { get; set; }
|
||||
}
|
||||
@@ -26,16 +26,6 @@ namespace ManagedCommon
|
||||
|
||||
private static readonly string Version = Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>()?.Version ?? "Unknown";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the log directory for the current version of the app.
|
||||
/// </summary>
|
||||
public static string CurrentVersionLogDirectoryPath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the log directory for the app.
|
||||
/// </summary>
|
||||
public static string AppLogDirectoryPath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the logger and sets the path for logging.
|
||||
/// </summary>
|
||||
@@ -52,9 +42,6 @@ namespace ManagedCommon
|
||||
Directory.CreateDirectory(versionedPath);
|
||||
}
|
||||
|
||||
AppLogDirectoryPath = basePath;
|
||||
CurrentVersionLogDirectoryPath = versionedPath;
|
||||
|
||||
var logFilePath = Path.Combine(versionedPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log");
|
||||
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
|
||||
@@ -143,7 +130,7 @@ namespace ManagedCommon
|
||||
{
|
||||
exMessage +=
|
||||
"Inner exception: " + Environment.NewLine +
|
||||
ex.InnerException.GetType() + " (" + ex.InnerException.HResult + "): " + ex.InnerException.Message + Environment.NewLine;
|
||||
ex.InnerException.GetType() + " (" + ex.HResult + "): " + ex.InnerException.Message + Environment.NewLine;
|
||||
}
|
||||
|
||||
exMessage +=
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace ManagedCommon
|
||||
ColorPicker,
|
||||
CmdPal,
|
||||
CropAndLock,
|
||||
CursorWrap,
|
||||
EnvironmentVariables,
|
||||
FancyZones,
|
||||
FileLocksmith,
|
||||
|
||||
@@ -63,12 +63,14 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
|
||||
@@ -59,7 +59,6 @@ struct LogSettings
|
||||
inline const static std::string mouseHighlighterLoggerName = "mouse-highlighter";
|
||||
inline const static std::string mouseJumpLoggerName = "mouse-jump";
|
||||
inline const static std::string mousePointerCrosshairsLoggerName = "mouse-pointer-crosshairs";
|
||||
inline const static std::string cursorWrapLoggerName = "cursor-wrap";
|
||||
inline const static std::string imageResizerLoggerName = "imageresizer";
|
||||
inline const static std::string powerRenameLoggerName = "powerrename";
|
||||
inline const static std::string alwaysOnTopLoggerName = "always-on-top";
|
||||
|
||||
@@ -46,6 +46,16 @@
|
||||
<PropertyGroup>
|
||||
<TargetName>notifications</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <Windows.h>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace powertoys_gpo
|
||||
{
|
||||
@@ -52,7 +51,6 @@ namespace powertoys_gpo
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_HIGHLIGHTER = L"ConfigureEnabledUtilityMouseHighlighter";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_JUMP = L"ConfigureEnabledUtilityMouseJump";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_POINTER_CROSSHAIRS = L"ConfigureEnabledUtilityMousePointerCrosshairs";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_CURSOR_WRAP = L"ConfigureEnabledUtilityCursorWrap";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_RENAME = L"ConfigureEnabledUtilityPowerRename";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER = L"ConfigureEnabledUtilityPowerLauncher";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_QUICK_ACCENT = L"ConfigureEnabledUtilityQuickAccent";
|
||||
@@ -84,14 +82,6 @@ namespace powertoys_gpo
|
||||
const std::wstring POLICY_CONFIGURE_RUN_AT_STARTUP = L"ConfigureRunAtStartup";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER_ALL_PLUGINS = L"PowerLauncherAllPluginsEnabledState";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_ONLINE_AI_MODELS = L"AllowPowerToysAdvancedPasteOnlineAIModels";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_OPENAI = L"AllowAdvancedPasteOpenAI";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_AZURE_OPENAI = L"AllowAdvancedPasteAzureOpenAI";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_AZURE_AI_INFERENCE = L"AllowAdvancedPasteAzureAIInference";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_MISTRAL = L"AllowAdvancedPasteMistral";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_GOOGLE = L"AllowAdvancedPasteGoogle";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_ANTHROPIC = L"AllowAdvancedPasteAnthropic";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_OLLAMA = L"AllowAdvancedPasteOllama";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_FOUNDRY_LOCAL = L"AllowAdvancedPasteFoundryLocal";
|
||||
const std::wstring POLICY_MWB_CLIPBOARD_SHARING_ENABLED = L"MwbClipboardSharingEnabled";
|
||||
const std::wstring POLICY_MWB_FILE_TRANSFER_ENABLED = L"MwbFileTransferEnabled";
|
||||
const std::wstring POLICY_MWB_USE_ORIGINAL_USER_INTERFACE = L"MwbUseOriginalUserInterface";
|
||||
@@ -411,11 +401,6 @@ namespace powertoys_gpo
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_MOUSE_POINTER_CROSSHAIRS);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredCursorWrapEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_CURSOR_WRAP);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredPowerRenameEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_POWER_RENAME);
|
||||
@@ -590,46 +575,6 @@ namespace powertoys_gpo
|
||||
return getConfiguredValue(POLICY_ALLOW_ADVANCED_PASTE_ONLINE_AI_MODELS);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getAllowedAdvancedPasteOpenAIValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_ALLOW_ADVANCED_PASTE_OPENAI);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getAllowedAdvancedPasteAzureOpenAIValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_ALLOW_ADVANCED_PASTE_AZURE_OPENAI);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getAllowedAdvancedPasteAzureAIInferenceValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_ALLOW_ADVANCED_PASTE_AZURE_AI_INFERENCE);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getAllowedAdvancedPasteMistralValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_ALLOW_ADVANCED_PASTE_MISTRAL);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getAllowedAdvancedPasteGoogleValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_ALLOW_ADVANCED_PASTE_GOOGLE);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getAllowedAdvancedPasteAnthropicValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_ALLOW_ADVANCED_PASTE_ANTHROPIC);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getAllowedAdvancedPasteOllamaValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_ALLOW_ADVANCED_PASTE_OLLAMA);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getAllowedAdvancedPasteFoundryLocalValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_ALLOW_ADVANCED_PASTE_FOUNDRY_LOCAL);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredMwbClipboardSharingEnabledValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_MWB_CLIPBOARD_SHARING_ENABLED);
|
||||
|
||||
@@ -33,4 +33,9 @@
|
||||
<Target Name="PostBuildAction" AfterTargets="Build" Outputs="$(GeneratedDSCModule)" Condition="'$(Platform)'!='ARM64'">
|
||||
<Exec Command=""$(OutDir)$(AssemblyName).exe" "..\..\..\x64\$(Configuration)\WinUI3Apps\PowerToys.Settings.UI.Lib.dll" $(GeneratedDSCModule) $(GeneratedDSCManifest)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Condition="'$(Platform)'=='ARM64'">
|
||||
<Exec Command=""$(MSBuildToolsPath)\msbuild.exe" PowerToys.sln -p:Configuration="$(Configuration)" -p:Platform="x64" -verbosity:m -t:DSC\PowerToys_Settings_DSC_Schema_Generator" WorkingDirectory="..\..\..\" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -23,8 +23,7 @@ public sealed class SettingsResourceAdvancedPasteModuleTest : SettingsResourceMo
|
||||
{
|
||||
s.Properties.ShowCustomPreview = !s.Properties.ShowCustomPreview;
|
||||
s.Properties.CloseAfterLosingFocus = !s.Properties.CloseAfterLosingFocus;
|
||||
|
||||
// s.Properties.IsAdvancedAIEnabled = !s.Properties.IsAdvancedAIEnabled;
|
||||
s.Properties.IsAdvancedAIEnabled = !s.Properties.IsAdvancedAIEnabled;
|
||||
s.Properties.AdvancedPasteUIShortcut = new HotkeySettings
|
||||
{
|
||||
Key = "mock",
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace PowerToys.DSC.Models;
|
||||
public sealed class DscManifest
|
||||
{
|
||||
private const string Schema = "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.vscode.json";
|
||||
private const string Executable = @"..\PowerToys.DSC.exe";
|
||||
private const string Executable = @"PowerToys.DSC.exe";
|
||||
|
||||
private readonly string _type;
|
||||
private readonly string _version;
|
||||
|
||||
@@ -40,11 +40,9 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Generate the DSC resource JSON files to DSCModules subfolder -->
|
||||
<!-- Skip generation in CI/CD builds (CIBuild=true) to avoid unnecessary work during pipeline -->
|
||||
<Target Name="GenerateDscResourceJsonFiles" AfterTargets="Build" Condition="'$(CIBuild)' != 'true'">
|
||||
<Message Text="Generating DSC resource JSON files to DSCModules subfolder..." Importance="high" />
|
||||
<MakeDir Directories="$(TargetDir)DSCModules" />
|
||||
<Exec Command="dotnet "$(TargetPath)" manifest --resource settings --outputDir "$(TargetDir)DSCModules"" />
|
||||
<!-- In debug mode, generate the DSC resource JSON files -->
|
||||
<Target Name="GenerateDscResourceJsonFiles" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
|
||||
<Message Text="Generating DSC resource JSON files inside ..." Importance="high" />
|
||||
<Exec Command="dotnet "$(TargetPath)" manifest --resource settings --outputDir "$(TargetDir)\"" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.18" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.17" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyNamespaces>
|
||||
<target prefix="powertoys" namespace="Microsoft.Policies.PowerToys" />
|
||||
</policyNamespaces>
|
||||
<resources minRequiredRevision="1.18"/><!-- Last changed with PowerToys v0.96.0 -->
|
||||
<resources minRequiredRevision="1.17"/><!-- Last changed with PowerToys v0.90.0 -->
|
||||
<supportedOn>
|
||||
<definitions>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_64_0" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0)"/>
|
||||
@@ -26,7 +26,6 @@
|
||||
<definition name="SUPPORTED_POWERTOYS_0_88_0" displayName="$(string.SUPPORTED_POWERTOYS_0_88_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_89_0" displayName="$(string.SUPPORTED_POWERTOYS_0_89_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_90_0" displayName="$(string.SUPPORTED_POWERTOYS_0_90_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_96_0" displayName="$(string.SUPPORTED_POWERTOYS_0_96_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1)"/>
|
||||
</definitions>
|
||||
</supportedOn>
|
||||
@@ -615,86 +614,6 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="AllowAdvancedPasteOpenAI" class="Both" displayName="$(string.AllowAdvancedPasteOpenAI)" explainText="$(string.AllowAdvancedPasteOpenAIDescription)" key="Software\Policies\PowerToys" valueName="AllowAdvancedPasteOpenAI">
|
||||
<parentCategory ref="AdvancedPaste" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_96_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="AllowAdvancedPasteAzureOpenAI" class="Both" displayName="$(string.AllowAdvancedPasteAzureOpenAI)" explainText="$(string.AllowAdvancedPasteAzureOpenAIDescription)" key="Software\Policies\PowerToys" valueName="AllowAdvancedPasteAzureOpenAI">
|
||||
<parentCategory ref="AdvancedPaste" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_96_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="AllowAdvancedPasteAzureAIInference" class="Both" displayName="$(string.AllowAdvancedPasteAzureAIInference)" explainText="$(string.AllowAdvancedPasteAzureAIInferenceDescription)" key="Software\Policies\PowerToys" valueName="AllowAdvancedPasteAzureAIInference">
|
||||
<parentCategory ref="AdvancedPaste" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_96_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="AllowAdvancedPasteMistral" class="Both" displayName="$(string.AllowAdvancedPasteMistral)" explainText="$(string.AllowAdvancedPasteMistralDescription)" key="Software\Policies\PowerToys" valueName="AllowAdvancedPasteMistral">
|
||||
<parentCategory ref="AdvancedPaste" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_96_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="AllowAdvancedPasteGoogle" class="Both" displayName="$(string.AllowAdvancedPasteGoogle)" explainText="$(string.AllowAdvancedPasteGoogleDescription)" key="Software\Policies\PowerToys" valueName="AllowAdvancedPasteGoogle">
|
||||
<parentCategory ref="AdvancedPaste" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_96_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="AllowAdvancedPasteAnthropic" class="Both" displayName="$(string.AllowAdvancedPasteAnthropic)" explainText="$(string.AllowAdvancedPasteAnthropicDescription)" key="Software\Policies\PowerToys" valueName="AllowAdvancedPasteAnthropic">
|
||||
<parentCategory ref="AdvancedPaste" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_96_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="AllowAdvancedPasteOllama" class="Both" displayName="$(string.AllowAdvancedPasteOllama)" explainText="$(string.AllowAdvancedPasteOllamaDescription)" key="Software\Policies\PowerToys" valueName="AllowAdvancedPasteOllama">
|
||||
<parentCategory ref="AdvancedPaste" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_96_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="AllowAdvancedPasteFoundryLocal" class="Both" displayName="$(string.AllowAdvancedPasteFoundryLocal)" explainText="$(string.AllowAdvancedPasteFoundryLocalDescription)" key="Software\Policies\PowerToys" valueName="AllowAdvancedPasteFoundryLocal">
|
||||
<parentCategory ref="AdvancedPaste" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_96_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbClipboardSharingEnabled" class="Both" displayName="$(string.MwbClipboardSharingEnabled)" explainText="$(string.MwbClipboardSharingEnabledDescription)" key="Software\Policies\PowerToys" valueName="MwbClipboardSharingEnabled">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_83_0" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.18" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.17" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<displayName>PowerToys</displayName>
|
||||
<description>PowerToys</description>
|
||||
<resources>
|
||||
@@ -33,7 +33,6 @@
|
||||
<string id="SUPPORTED_POWERTOYS_0_88_0">PowerToys version 0.88.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_89_0">PowerToys version 0.89.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_90_0">PowerToys version 0.90.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_96_0">PowerToys version 0.96.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1">From PowerToys version 0.64.0 until PowerToys version 0.87.1</string>
|
||||
|
||||
<string id="ConfigureAllUtilityGlobalEnabledStateDescription">This policy configures the enabled state for all PowerToys utilities.
|
||||
@@ -292,54 +291,6 @@ If you don't configure this policy, the user will be able to control the setting
|
||||
<string id="ConfigureEnabledUtilityFileExplorerQOIPreview">QOI file preview: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileExplorerQOIThumbnails">QOI file thumbnail: Configure enabled state</string>
|
||||
<string id="AllowPowerToysAdvancedPasteOnlineAIModels">Allow using online AI models</string>
|
||||
<string id="AllowAdvancedPasteOpenAI">Advanced Paste: Allow OpenAI endpoint</string>
|
||||
<string id="AllowAdvancedPasteOpenAIDescription">This policy controls whether users can use the OpenAI endpoint in Advanced Paste.
|
||||
|
||||
If you enable or don't configure this policy, users can configure and use OpenAI as their AI provider.
|
||||
|
||||
If you disable this policy, users will not be able to select or use OpenAI endpoint in Advanced Paste settings.</string>
|
||||
<string id="AllowAdvancedPasteAzureOpenAI">Advanced Paste: Allow Azure OpenAI endpoint</string>
|
||||
<string id="AllowAdvancedPasteAzureOpenAIDescription">This policy controls whether users can use the Azure OpenAI endpoint in Advanced Paste.
|
||||
|
||||
If you enable or don't configure this policy, users can configure and use Azure OpenAI as their AI provider.
|
||||
|
||||
If you disable this policy, users will not be able to select or use Azure OpenAI endpoint in Advanced Paste settings.</string>
|
||||
<string id="AllowAdvancedPasteAzureAIInference">Advanced Paste: Allow Azure AI Inference endpoint</string>
|
||||
<string id="AllowAdvancedPasteAzureAIInferenceDescription">This policy controls whether users can use the Azure AI Inference endpoint in Advanced Paste.
|
||||
|
||||
If you enable or don't configure this policy, users can configure and use Azure AI Inference as their AI provider.
|
||||
|
||||
If you disable this policy, users will not be able to select or use Azure AI Inference endpoint in Advanced Paste settings.</string>
|
||||
<string id="AllowAdvancedPasteMistral">Advanced Paste: Allow Mistral endpoint</string>
|
||||
<string id="AllowAdvancedPasteMistralDescription">This policy controls whether users can use the Mistral AI endpoint in Advanced Paste.
|
||||
|
||||
If you enable or don't configure this policy, users can configure and use Mistral as their AI provider.
|
||||
|
||||
If you disable this policy, users will not be able to select or use Mistral endpoint in Advanced Paste settings.</string>
|
||||
<string id="AllowAdvancedPasteGoogle">Advanced Paste: Allow Google endpoint</string>
|
||||
<string id="AllowAdvancedPasteGoogleDescription">This policy controls whether users can use the Google (Gemini) endpoint in Advanced Paste.
|
||||
|
||||
If you enable or don't configure this policy, users can configure and use Google as their AI provider.
|
||||
|
||||
If you disable this policy, users will not be able to select or use Google endpoint in Advanced Paste settings.</string>
|
||||
<string id="AllowAdvancedPasteAnthropic">Advanced Paste: Allow Anthropic endpoint</string>
|
||||
<string id="AllowAdvancedPasteAnthropicDescription">This policy controls whether users can use the Anthropic (Claude) endpoint in Advanced Paste.
|
||||
|
||||
If you enable or don't configure this policy, users can configure and use Anthropic as their AI provider.
|
||||
|
||||
If you disable this policy, users will not be able to select or use Anthropic endpoint in Advanced Paste settings.</string>
|
||||
<string id="AllowAdvancedPasteOllama">Advanced Paste: Allow Ollama endpoint</string>
|
||||
<string id="AllowAdvancedPasteOllamaDescription">This policy controls whether users can use the Ollama local model endpoint in Advanced Paste.
|
||||
|
||||
If you enable or don't configure this policy, users can configure and use Ollama as their AI provider.
|
||||
|
||||
If you disable this policy, users will not be able to select or use Ollama endpoint in Advanced Paste settings.</string>
|
||||
<string id="AllowAdvancedPasteFoundryLocal">Advanced Paste: Allow Foundry Local endpoint</string>
|
||||
<string id="AllowAdvancedPasteFoundryLocalDescription">This policy controls whether users can use the Foundry Local model endpoint in Advanced Paste.
|
||||
|
||||
If you enable or don't configure this policy, users can configure and use Foundry Local as their AI provider.
|
||||
|
||||
If you disable this policy, users will not be able to select or use Foundry Local endpoint in Advanced Paste settings.</string>
|
||||
<string id="MwbClipboardSharingEnabled">Clipboard sharing enabled</string>
|
||||
<string id="MwbFileTransferEnabled">File transfer enabled</string>
|
||||
<string id="MwbUseOriginalUserInterface">Original user interface is available</string>
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using AdvancedPaste.Models;
|
||||
using AdvancedPaste.Settings;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
namespace AdvancedPaste.UnitTests.Mocks;
|
||||
|
||||
/// <summary>
|
||||
/// Minimal <see cref="IUserSettings"/> implementation used by integration tests that
|
||||
/// need to construct the runtime Advanced Paste services.
|
||||
/// </summary>
|
||||
internal sealed class IntegrationTestUserSettings : IUserSettings
|
||||
{
|
||||
private readonly PasteAIConfiguration _configuration;
|
||||
private readonly IReadOnlyList<AdvancedPasteCustomAction> _customActions;
|
||||
private readonly IReadOnlyList<PasteFormats> _additionalActions;
|
||||
|
||||
public IntegrationTestUserSettings()
|
||||
{
|
||||
var provider = new PasteAIProviderDefinition
|
||||
{
|
||||
Id = "integration-openai",
|
||||
EnableAdvancedAI = true,
|
||||
ServiceTypeKind = AIServiceType.OpenAI,
|
||||
ModelName = "gpt-4o",
|
||||
ModerationEnabled = true,
|
||||
};
|
||||
|
||||
_configuration = new PasteAIConfiguration
|
||||
{
|
||||
ActiveProviderId = provider.Id,
|
||||
Providers = new ObservableCollection<PasteAIProviderDefinition> { provider },
|
||||
};
|
||||
|
||||
_customActions = Array.Empty<AdvancedPasteCustomAction>();
|
||||
_additionalActions = Array.Empty<PasteFormats>();
|
||||
}
|
||||
|
||||
public bool IsAIEnabled => true;
|
||||
|
||||
public bool ShowCustomPreview => false;
|
||||
|
||||
public bool CloseAfterLosingFocus => false;
|
||||
|
||||
public IReadOnlyList<AdvancedPasteCustomAction> CustomActions => _customActions;
|
||||
|
||||
public IReadOnlyList<PasteFormats> AdditionalActions => _additionalActions;
|
||||
|
||||
public PasteAIConfiguration PasteAIConfiguration => _configuration;
|
||||
|
||||
public event EventHandler Changed;
|
||||
|
||||
public Task SetActiveAIProviderAsync(string providerId)
|
||||
{
|
||||
_configuration.ActiveProviderId = providerId ?? string.Empty;
|
||||
Changed?.Invoke(this, EventArgs.Empty);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,6 @@ using System.Threading.Tasks;
|
||||
|
||||
using AdvancedPaste.Helpers;
|
||||
using AdvancedPaste.Models;
|
||||
using AdvancedPaste.Services;
|
||||
using AdvancedPaste.Services.CustomActions;
|
||||
using AdvancedPaste.Services.OpenAI;
|
||||
using AdvancedPaste.UnitTests.Mocks;
|
||||
using ManagedCommon;
|
||||
@@ -81,9 +79,7 @@ public sealed class AIServiceBatchIntegrationTests
|
||||
Assert.IsTrue(results.Count <= inputs.Count);
|
||||
CollectionAssert.AreEqual(results.Select(result => result.ToInput()).ToList(), inputs.Take(results.Count).ToList());
|
||||
|
||||
#pragma warning disable IL2026, IL3050 // The tests rely on runtime JSON serialization for ad-hoc data files.
|
||||
async Task WriteResultsAsync() => await File.WriteAllTextAsync(resultsFile, JsonSerializer.Serialize(results, SerializerOptions));
|
||||
#pragma warning restore IL2026, IL3050
|
||||
|
||||
Logger.LogInfo($"Starting {nameof(TestGenerateBatchResults)}; Count={inputs.Count}, InCache={results.Count}");
|
||||
|
||||
@@ -105,12 +101,8 @@ public sealed class AIServiceBatchIntegrationTests
|
||||
await WriteResultsAsync();
|
||||
}
|
||||
|
||||
private static async Task<List<T>> GetDataListAsync<T>(string filePath)
|
||||
{
|
||||
#pragma warning disable IL2026, IL3050 // Tests only run locally and can depend on runtime JSON serialization.
|
||||
return File.Exists(filePath) ? JsonSerializer.Deserialize<List<T>>(await File.ReadAllTextAsync(filePath)) : [];
|
||||
#pragma warning restore IL2026, IL3050
|
||||
}
|
||||
private static async Task<List<T>> GetDataListAsync<T>(string filePath) =>
|
||||
File.Exists(filePath) ? JsonSerializer.Deserialize<List<T>>(await File.ReadAllTextAsync(filePath)) : [];
|
||||
|
||||
private static async Task<string> GetTextOutputAsync(BatchTestInput input, PasteFormats format)
|
||||
{
|
||||
@@ -138,35 +130,23 @@ public sealed class AIServiceBatchIntegrationTests
|
||||
|
||||
private static async Task<DataPackage> GetOutputDataPackageAsync(BatchTestInput batchTestInput, PasteFormats format)
|
||||
{
|
||||
var services = CreateServices();
|
||||
VaultCredentialsProvider credentialsProvider = new();
|
||||
PromptModerationService promptModerationService = new(credentialsProvider);
|
||||
NoOpProgress progress = new();
|
||||
CustomTextTransformService customTextTransformService = new(credentialsProvider, promptModerationService);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case PasteFormats.CustomTextTransformation:
|
||||
var transformResult = await services.CustomActionTransformService.TransformTextAsync(batchTestInput.Prompt, batchTestInput.Clipboard, CancellationToken.None, progress);
|
||||
return DataPackageHelpers.CreateFromText(transformResult.Content ?? string.Empty);
|
||||
return DataPackageHelpers.CreateFromText(await customTextTransformService.TransformTextAsync(batchTestInput.Prompt, batchTestInput.Clipboard, CancellationToken.None, progress));
|
||||
|
||||
case PasteFormats.KernelQuery:
|
||||
var clipboardData = DataPackageHelpers.CreateFromText(batchTestInput.Clipboard).GetView();
|
||||
return await services.KernelService.TransformClipboardAsync(batchTestInput.Prompt, clipboardData, isSavedQuery: false, CancellationToken.None, progress);
|
||||
KernelService kernelService = new(new NoOpKernelQueryCacheService(), credentialsProvider, promptModerationService, customTextTransformService);
|
||||
return await kernelService.TransformClipboardAsync(batchTestInput.Prompt, clipboardData, isSavedQuery: false, CancellationToken.None, progress);
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException($"Unexpected format {format}");
|
||||
}
|
||||
}
|
||||
|
||||
private static IntegrationTestServices CreateServices()
|
||||
{
|
||||
IntegrationTestUserSettings userSettings = new();
|
||||
EnhancedVaultCredentialsProvider credentialsProvider = new(userSettings);
|
||||
PromptModerationService promptModerationService = new(credentialsProvider);
|
||||
PasteAIProviderFactory providerFactory = new();
|
||||
ICustomActionTransformService customActionTransformService = new CustomActionTransformService(promptModerationService, providerFactory, credentialsProvider, userSettings);
|
||||
IKernelService kernelService = new AdvancedAIKernelService(credentialsProvider, new NoOpKernelQueryCacheService(), promptModerationService, userSettings, customActionTransformService);
|
||||
|
||||
return new IntegrationTestServices(customActionTransformService, kernelService);
|
||||
}
|
||||
|
||||
private readonly record struct IntegrationTestServices(ICustomActionTransformService CustomActionTransformService, IKernelService KernelService);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ using System.Threading.Tasks;
|
||||
|
||||
using AdvancedPaste.Helpers;
|
||||
using AdvancedPaste.Models;
|
||||
using AdvancedPaste.Services;
|
||||
using AdvancedPaste.Services.CustomActions;
|
||||
using AdvancedPaste.Services.OpenAI;
|
||||
using AdvancedPaste.Telemetry;
|
||||
using AdvancedPaste.UnitTests.Mocks;
|
||||
@@ -29,19 +27,16 @@ namespace AdvancedPaste.UnitTests.ServicesTests;
|
||||
public sealed class KernelServiceIntegrationTests : IDisposable
|
||||
{
|
||||
private const string StandardImageFile = "image_with_text_example.png";
|
||||
private IKernelService _kernelService;
|
||||
private KernelService _kernelService;
|
||||
private AdvancedPasteEventListener _eventListener;
|
||||
|
||||
[TestInitialize]
|
||||
public void TestInitialize()
|
||||
{
|
||||
IntegrationTestUserSettings userSettings = new();
|
||||
EnhancedVaultCredentialsProvider credentialsProvider = new(userSettings);
|
||||
VaultCredentialsProvider credentialsProvider = new();
|
||||
PromptModerationService promptModerationService = new(credentialsProvider);
|
||||
PasteAIProviderFactory providerFactory = new();
|
||||
CustomActionTransformService customActionTransformService = new(promptModerationService, providerFactory, credentialsProvider, userSettings);
|
||||
|
||||
_kernelService = new AdvancedAIKernelService(credentialsProvider, new NoOpKernelQueryCacheService(), promptModerationService, userSettings, customActionTransformService);
|
||||
_kernelService = new KernelService(new NoOpKernelQueryCacheService(), credentialsProvider, promptModerationService, new CustomTextTransformService(credentialsProvider, promptModerationService));
|
||||
_eventListener = new();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,14 +33,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="AdvancedPasteXAML\Controls\ClipboardHistoryItemPreviewControl.xaml" />
|
||||
<None Remove="AdvancedPasteXAML\Controls\PromptBox.xaml" />
|
||||
<None Remove="AdvancedPasteXAML\Styles\Button.xaml" />
|
||||
<None Remove="Assets\AdvancedPaste\AIIcon.png" />
|
||||
<None Remove="Assets\AdvancedPaste\Gradient.png" />
|
||||
<None Remove="AdvancedPasteXAML\Controls\AnimatedContentControl\AnimatedBorderBrush.xaml" />
|
||||
<None Remove="AdvancedPasteXAML\Views\MainPage.xaml" />
|
||||
<None Remove="Assets\AdvancedPaste\SemanticKernel.svg" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -52,6 +49,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenAI" />
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Animations" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
||||
@@ -59,17 +57,10 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" />
|
||||
<!-- Including MessagePack to force version, since it's used by StreamJsonRpc but contains vulnerabilities. After StreamJsonRpc updates the version of MessagePack, we can upgrade StreamJsonRpc instead. -->
|
||||
<PackageReference Include="MessagePack" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Amazon" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.AzureAIInference" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Google" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.HuggingFace" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.MistralAI" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Ollama" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
|
||||
<PackageReference Include="System.ClientModel" />
|
||||
<PackageReference Include="Microsoft.Windows.Compatibility" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
@@ -111,7 +102,6 @@
|
||||
<!-- HACK: Common.UI is referenced, even if it is not used, to force dll versions to be the same as in other projects that use it. It's still unclear why this is the case, but this is need for flattening the install directory. -->
|
||||
<ProjectReference Include="..\..\..\common\Common.UI\Common.UI.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\LanguageModelProvider\LanguageModelProvider.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
|
||||
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
</ItemGroup>
|
||||
@@ -124,38 +114,9 @@
|
||||
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
|
||||
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="AdvancedPasteXAML\Controls\ClipboardHistoryItemPreviewControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="AdvancedPasteXAML\Controls\PromptBox.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="AdvancedPasteXAML\Styles\Button.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- Share AI Model Provider Icons from Settings.UI to avoid duplication -->
|
||||
<!-- These icons are included from Settings.UI project -->
|
||||
<Content Include="..\..\..\settings-ui\Settings.UI\Assets\Settings\Icons\Models\*.svg">
|
||||
<Link>Assets\Settings\Icons\Models\%(Filename)%(Extension)</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<!-- AdvancedPaste specific assets -->
|
||||
<Content Include="Assets\AdvancedPaste\*.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\AdvancedPaste\*.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<!-- Keep SemanticKernel.svg as it's specific to AdvancedPaste -->
|
||||
<Content Include="Assets\AdvancedPaste\SemanticKernel.svg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<ResourceDictionary Source="ms-appx:///AdvancedPasteXAML/Controls/AnimatedContentControl/AnimatedContentControl.xaml" />
|
||||
<ResourceDictionary Source="ms-appx:///AdvancedPasteXAML/Styles/Button.xaml" />
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<!-- Other app resources here -->
|
||||
|
||||
@@ -10,10 +10,10 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using AdvancedPaste.Helpers;
|
||||
using AdvancedPaste.Models;
|
||||
using AdvancedPaste.Services;
|
||||
using AdvancedPaste.Services.CustomActions;
|
||||
using AdvancedPaste.Settings;
|
||||
using AdvancedPaste.ViewModels;
|
||||
using ManagedCommon;
|
||||
@@ -77,12 +77,11 @@ namespace AdvancedPaste
|
||||
{
|
||||
services.AddSingleton<IFileSystem, FileSystem>();
|
||||
services.AddSingleton<IUserSettings, UserSettings>();
|
||||
services.AddSingleton<IAICredentialsProvider, EnhancedVaultCredentialsProvider>();
|
||||
services.AddSingleton<IAICredentialsProvider, Services.OpenAI.VaultCredentialsProvider>();
|
||||
services.AddSingleton<IPromptModerationService, Services.OpenAI.PromptModerationService>();
|
||||
services.AddSingleton<ICustomTextTransformService, Services.OpenAI.CustomTextTransformService>();
|
||||
services.AddSingleton<IKernelQueryCacheService, CustomActionKernelQueryCacheService>();
|
||||
services.AddSingleton<IPasteAIProviderFactory, PasteAIProviderFactory>();
|
||||
services.AddSingleton<ICustomActionTransformService, CustomActionTransformService>();
|
||||
services.AddSingleton<IKernelService, AdvancedAIKernelService>();
|
||||
services.AddSingleton<IKernelService, Services.OpenAI.KernelService>();
|
||||
services.AddSingleton<IPasteFormatExecutor, PasteFormatExecutor>();
|
||||
services.AddSingleton<OptionsViewModel>();
|
||||
}).Build();
|
||||
@@ -112,11 +111,7 @@ namespace AdvancedPaste
|
||||
/// Invoked when the application is launched.
|
||||
/// </summary>
|
||||
/// <param name="args">Details about the launch request and process.</param>
|
||||
#if DEBUG
|
||||
protected async override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
#else
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
#endif
|
||||
{
|
||||
var cmdArgs = Environment.GetCommandLineArgs();
|
||||
if (cmdArgs?.Length > 1)
|
||||
@@ -138,10 +133,6 @@ namespace AdvancedPaste
|
||||
{
|
||||
ProcessNamedPipe(cmdArgs[2]);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
await ShowWindow(); // This allows for direct access without using PowerToys Runner, not all functionality might work
|
||||
#endif
|
||||
}
|
||||
|
||||
private void ProcessNamedPipe(string pipeName)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="16" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:AnimatedContentControl">
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="AdvancedPaste.Controls.ClipboardHistoryItemPreviewControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="using:AdvancedPaste.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:AdvancedPaste.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<converters:DateTimeToFriendlyStringConverter x:Key="DateTimeToFriendlyStringConverter" />
|
||||
<tkconverters:BoolToVisibilityConverter x:Name="BoolToVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border Background="{ThemeResource SubtleFillColorSecondaryBrush}" CornerRadius="16,0,0,16">
|
||||
<Grid>
|
||||
<!-- Image preview -->
|
||||
<Image
|
||||
Source="{x:Bind ClipboardItem.Image, Mode=OneWay}"
|
||||
Stretch="UniformToFill"
|
||||
Visibility="{x:Bind HasImage, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<!-- Text preview -->
|
||||
<TextBlock
|
||||
Margin="8,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="10"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{x:Bind ClipboardItem.Content, Mode=OneWay}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{x:Bind HasText, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<!-- Icon glyph fallback -->
|
||||
<FontIcon
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="48"
|
||||
Glyph="{x:Bind IconGlyph, Mode=OneWay}"
|
||||
Visibility="{x:Bind HasGlyph, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="2">
|
||||
<TextBlock
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{x:Bind Header, Mode=OneWay}"
|
||||
TextWrapping="NoWrap" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Timestamp, Converter={StaticResource DateTimeToFriendlyStringConverter}, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -1,127 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using AdvancedPaste.Helpers;
|
||||
using AdvancedPaste.Models;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace AdvancedPaste.Controls
|
||||
{
|
||||
public sealed partial class ClipboardHistoryItemPreviewControl : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty ClipboardItemProperty = DependencyProperty.Register(
|
||||
nameof(ClipboardItem),
|
||||
typeof(ClipboardItem),
|
||||
typeof(ClipboardHistoryItemPreviewControl),
|
||||
new PropertyMetadata(defaultValue: null, OnClipboardItemChanged));
|
||||
|
||||
public ClipboardItem ClipboardItem
|
||||
{
|
||||
get => (ClipboardItem)GetValue(ClipboardItemProperty);
|
||||
set => SetValue(ClipboardItemProperty, value);
|
||||
}
|
||||
|
||||
// Computed properties for display
|
||||
public string Header => ClipboardItem != null ? GetHeaderFromFormat(ClipboardItem.Format) : string.Empty;
|
||||
|
||||
public string IconGlyph => ClipboardItem != null ? GetGlyphFromFormat(ClipboardItem.Format) : string.Empty;
|
||||
|
||||
public string ContentText => ClipboardItem?.Content ?? string.Empty;
|
||||
|
||||
public ImageSource ContentImage => ClipboardItem?.Image;
|
||||
|
||||
public DateTimeOffset? Timestamp => ClipboardItem?.Timestamp ?? ClipboardItem?.Item?.Timestamp;
|
||||
|
||||
public bool HasImage => ContentImage is not null;
|
||||
|
||||
public bool HasText => !string.IsNullOrEmpty(ContentText) && !HasImage;
|
||||
|
||||
public bool HasGlyph => !HasImage && !HasText && !string.IsNullOrEmpty(IconGlyph);
|
||||
|
||||
public ClipboardHistoryItemPreviewControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private static void OnClipboardItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is ClipboardHistoryItemPreviewControl control)
|
||||
{
|
||||
// Notify bindings that all computed properties may have changed
|
||||
control.Bindings.Update();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetHeaderFromFormat(ClipboardFormat format)
|
||||
{
|
||||
// Check flags in priority order (most specific first)
|
||||
if (format.HasFlag(ClipboardFormat.Image))
|
||||
{
|
||||
return GetStringOrFallback("ClipboardPreviewCategoryImage", "Image");
|
||||
}
|
||||
|
||||
if (format.HasFlag(ClipboardFormat.Video))
|
||||
{
|
||||
return GetStringOrFallback("ClipboardPreviewCategoryVideo", "Video");
|
||||
}
|
||||
|
||||
if (format.HasFlag(ClipboardFormat.Audio))
|
||||
{
|
||||
return GetStringOrFallback("ClipboardPreviewCategoryAudio", "Audio");
|
||||
}
|
||||
|
||||
if (format.HasFlag(ClipboardFormat.File))
|
||||
{
|
||||
return GetStringOrFallback("ClipboardPreviewCategoryFile", "File");
|
||||
}
|
||||
|
||||
if (format.HasFlag(ClipboardFormat.Text) || format.HasFlag(ClipboardFormat.Html))
|
||||
{
|
||||
return GetStringOrFallback("ClipboardPreviewCategoryText", "Text");
|
||||
}
|
||||
|
||||
return GetStringOrFallback("ClipboardPreviewCategoryUnknown", "Clipboard");
|
||||
}
|
||||
|
||||
private static string GetGlyphFromFormat(ClipboardFormat format)
|
||||
{
|
||||
// Check flags in priority order (most specific first)
|
||||
if (format.HasFlag(ClipboardFormat.Image))
|
||||
{
|
||||
return "\uEB9F"; // Image icon
|
||||
}
|
||||
|
||||
if (format.HasFlag(ClipboardFormat.Video))
|
||||
{
|
||||
return "\uE714"; // Video icon
|
||||
}
|
||||
|
||||
if (format.HasFlag(ClipboardFormat.Audio))
|
||||
{
|
||||
return "\uE189"; // Audio icon
|
||||
}
|
||||
|
||||
if (format.HasFlag(ClipboardFormat.File))
|
||||
{
|
||||
return "\uE8A5"; // File icon
|
||||
}
|
||||
|
||||
if (format.HasFlag(ClipboardFormat.Text) || format.HasFlag(ClipboardFormat.Html))
|
||||
{
|
||||
return "\uE8D2"; // Text icon
|
||||
}
|
||||
|
||||
return "\uE77B"; // Generic clipboard icon
|
||||
}
|
||||
|
||||
private static string GetStringOrFallback(string resourceKey, string fallback)
|
||||
{
|
||||
var value = ResourceLoaderInstance.ResourceLoader.GetString(resourceKey);
|
||||
return string.IsNullOrEmpty(value) ? fallback : value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,21 +7,34 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:AdvancedPaste.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:settings="using:Microsoft.PowerToys.Settings.UI.Library"
|
||||
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
x:Name="PromptBoxControl"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<Color x:Key="AccentGradientColor">#65C8F2</Color>
|
||||
<LinearGradientBrush x:Key="AccentGradientBrush" StartPoint="0,0" EndPoint="1,1">
|
||||
<GradientStop Offset="0.0" Color="#98EFFE" />
|
||||
<GradientStop Offset="0.25" Color="#48B1E9" />
|
||||
<GradientStop Offset="1.0" Color="{StaticResource AccentGradientColor}" />
|
||||
</LinearGradientBrush>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<Color x:Key="AccentGradientColor">#005FB8</Color>
|
||||
<LinearGradientBrush x:Key="AccentGradientBrush" StartPoint="0,0" EndPoint="1,1">
|
||||
<GradientStop Offset="0.0" Color="#4992C7" />
|
||||
<GradientStop Offset="0.25" Color="#1353A0" />
|
||||
<GradientStop Offset="1.0" Color="{StaticResource AccentGradientColor}" />
|
||||
</LinearGradientBrush>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<Color x:Key="AccentGradientColor">#48B1E9</Color>
|
||||
<SolidColorBrush x:Key="AccentGradientBrush" Color="{StaticResource AccentGradientColor}" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<LinearGradientBrush x:Name="IntelligentUnderlineGradient" StartPoint="0,0.5" EndPoint="1,0.5">
|
||||
<GradientStop Offset="0.0" Color="#FF0078D4" />
|
||||
<GradientStop Offset="0.42" Color="#FF464FEB" />
|
||||
<GradientStop Offset="0.87" Color="#FFD660FF" />
|
||||
<GradientStop Offset="1.0" Color="#FFFEA874" />
|
||||
</LinearGradientBrush>
|
||||
<x:Double x:Key="ModelSelectorButtonWidth">44</x:Double>
|
||||
<Style x:Key="CustomTextBoxStyle" TargetType="TextBox">
|
||||
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}" />
|
||||
<Setter Property="Background" Value="{ThemeResource TextControlBackground}" />
|
||||
@@ -142,7 +155,6 @@
|
||||
Foreground="{ThemeResource TextControlHeaderForeground}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
<Border
|
||||
x:Name="BorderElement"
|
||||
Grid.Row="1"
|
||||
@@ -156,32 +168,48 @@
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Control.IsTemplateFocusTarget="True"
|
||||
CornerRadius="{TemplateBinding CornerRadius}" />
|
||||
<Rectangle
|
||||
x:Name="FocusHighlighter"
|
||||
<Viewbox
|
||||
Grid.Row="1"
|
||||
Grid.RowSpan="1"
|
||||
Grid.ColumnSpan="4"
|
||||
Height="2"
|
||||
Margin="12,0,12,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Bottom"
|
||||
Fill="{StaticResource IntelligentUnderlineGradient}"
|
||||
RadiusX="1"
|
||||
RadiusY="1"
|
||||
Visibility="Collapsed" />
|
||||
<Grid Grid.Row="1" Width="{StaticResource ModelSelectorButtonWidth}">
|
||||
<ProgressRing
|
||||
Width="20"
|
||||
Height="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsActive="{Binding DataContext.IsBusy, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
IsIndeterminate="{Binding DataContext.HasIndeterminateTransformProgress, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Visibility="{Binding DataContext.IsBusy, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BoolToVisibilityConverter}}"
|
||||
Value="{Binding DataContext.TransformProgress, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
|
||||
</Grid>
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="8,0,0,0">
|
||||
<StackPanel
|
||||
Margin="0"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<ProgressRing
|
||||
Width="30"
|
||||
Height="30"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
IsActive="{Binding DataContext.IsBusy, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
IsIndeterminate="{Binding DataContext.HasIndeterminateTransformProgress, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Visibility="{Binding DataContext.IsBusy, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BoolToVisibilityConverter}}"
|
||||
Value="{Binding DataContext.TransformProgress, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
|
||||
|
||||
<StackPanel
|
||||
Margin="0"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Visibility="{Binding DataContext.IsBusy, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BoolToInvertedVisibilityConverter}}">
|
||||
<Image
|
||||
x:Name="AIGlyphImage"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Source="/Assets/AdvancedPaste/SemanticKernel.svg"
|
||||
Visibility="{Binding DataContext.IsAdvancedAIEnabled, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<PathIcon
|
||||
x:Name="AIGlyph"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Data="M128 766q0-42 24-77t65-48l178-57q32-11 61-30t52-42q50-50 71-114l58-179q13-40 48-65t78-26q42 0 77 24t50 65l58 177q21 66 72 117 49 50 117 72l176 58q43 14 69 48t26 80q0 41-25 76t-64 49l-178 58q-66 21-117 72-32 32-51 73t-33 84-26 83-30 73-45 51-71 20q-42 0-77-24t-49-65l-58-178q-8-25-19-47t-28-43q-34-43-77-68t-89-41-89-27-78-29-55-45-21-75zm1149 7q-76-29-145-53t-129-60-104-88-73-138l-57-176-67 176q-18 48-42 89t-60 78q-34 34-76 61t-89 43l-177 57q75 29 144 53t127 60 103 89 73 137l57 176 67-176q37-97 103-168t168-103l177-57zm-125 759q0-31 20-57t49-36l99-32q34-11 53-34t30-51 20-59 20-54 33-41 58-16q32 0 59 19t38 50q6 20 11 40t13 40 17 38 25 34q16 17 39 26t48 18 49 16 44 20 31 32 12 50q0 33-18 60t-51 38q-19 6-39 11t-41 13-39 17-34 25q-24 25-35 62t-24 73-35 61-68 25q-32 0-59-19t-38-50q-6-18-11-39t-13-41-17-40-24-33q-18-17-41-27t-47-17-49-15-43-20-30-33-12-54zm583 4q-43-13-74-30t-55-41-40-55-32-74q-12 41-29 72t-42 55-55 42-71 31q81 23 128 71t71 129q15-43 31-74t40-54 53-40 75-32z"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Visibility="{Binding DataContext.IsAdvancedAIEnabled, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BoolToInvertedVisibilityConverter}}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Viewbox>
|
||||
<ScrollViewer
|
||||
x:Name="ContentElement"
|
||||
Grid.Row="1"
|
||||
@@ -251,6 +279,12 @@
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="AIGlyph" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="AIGlyphImage" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="0.4" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundDisabled}}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
@@ -280,10 +314,7 @@
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundFocused}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusHighlighter" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<LinearGradientBrush MappingMode="Absolute" StartPoint="0,0" EndPoint="0,2">
|
||||
@@ -300,7 +331,7 @@
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderThickness">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderThemeThicknessFocused}" />
|
||||
</ObjectAnimationUsingKeyFrames>-->
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundFocused}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
@@ -333,8 +364,6 @@
|
||||
FalseValue="Visible"
|
||||
TrueValue="Collapsed" />
|
||||
<converters:CountToVisibilityConverter x:Key="CountToVisibilityConverter" />
|
||||
<converters:CountToInvertedVisibilityConverter x:Key="CountToInvertedVisibilityConverter" />
|
||||
<converters:ServiceTypeToIconConverter x:Key="ServiceTypeToIconConverter" />
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid x:Name="PromptBoxGrid" Loaded="Grid_Loaded">
|
||||
@@ -345,19 +374,18 @@
|
||||
<local:AnimatedContentControl
|
||||
x:Name="Loader"
|
||||
MinHeight="48"
|
||||
CornerRadius="16">
|
||||
CornerRadius="8">
|
||||
<Grid>
|
||||
<TextBox
|
||||
x:Name="InputTxtBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
x:FieldModifier="public"
|
||||
CornerRadius="16"
|
||||
DataContext="{x:Bind ViewModel}"
|
||||
IsEnabled="{x:Bind ViewModel.ClipboardHasData, Mode=OneWay}"
|
||||
KeyDown="InputTxtBox_KeyDown"
|
||||
PlaceholderText="{x:Bind ViewModel.InputTxtBoxPlaceholderText, Mode=OneWay}"
|
||||
Style="{StaticResource CustomTextBoxStyle}"
|
||||
TabIndex="1"
|
||||
TabIndex="0"
|
||||
Text="{x:Bind ViewModel.Query, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="InputTxtBoxTooltip" />
|
||||
@@ -517,139 +545,6 @@
|
||||
</Flyout>
|
||||
</FlyoutBase.AttachedFlyout>
|
||||
</TextBox>
|
||||
<DropDownButton
|
||||
x:Name="AIProviderButton"
|
||||
x:Uid="AIProviderButton"
|
||||
MinWidth="{StaticResource ModelSelectorButtonWidth}"
|
||||
Margin="1,1,0,2"
|
||||
Padding="0,0,4,0"
|
||||
VerticalAlignment="Stretch"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,1,0"
|
||||
CornerRadius="16,0,0,16"
|
||||
Style="{StaticResource SubtleDropDownButtonStyle}"
|
||||
TabIndex="0"
|
||||
Visibility="{x:Bind ViewModel.IsBusy, Mode=OneWay, Converter={StaticResource BoolToInvertedVisibilityConverter}}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock Text="{x:Bind ViewModel.ActiveAIProviderTooltip, Mode=OneWay}" TextWrapping="WrapWholeWords" />
|
||||
</ToolTipService.ToolTip>
|
||||
<DropDownButton.Content>
|
||||
<Image
|
||||
x:Name="AIProviderIcon"
|
||||
Width="16"
|
||||
Height="16"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Source="{x:Bind ViewModel.ActiveAIProvider?.ServiceType, Mode=OneWay, Converter={StaticResource ServiceTypeToIconConverter}}" />
|
||||
</DropDownButton.Content>
|
||||
<DropDownButton.Flyout>
|
||||
<Flyout
|
||||
Opened="AIProviderFlyout_Opened"
|
||||
Placement="Bottom"
|
||||
ShouldConstrainToRootBounds="False">
|
||||
<Grid
|
||||
Width="386"
|
||||
Margin="-4"
|
||||
RowSpacing="12">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
x:Uid="AIProvidersFlyoutHeader"
|
||||
Grid.Row="0"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}" />
|
||||
<ListView
|
||||
x:Name="AIProviderListView"
|
||||
Grid.Row="1"
|
||||
MaxHeight="320"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{StaticResource OverlayCornerRadius}"
|
||||
ItemsSource="{x:Bind ViewModel.AIProviders, Mode=OneWay}"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
ScrollViewer.VerticalScrollMode="Auto"
|
||||
SelectedItem="{x:Bind ViewModel.ActiveAIProvider, Mode=OneWay}"
|
||||
SelectionChanged="AIProviderListView_SelectionChanged"
|
||||
SelectionMode="Single"
|
||||
Visibility="{x:Bind ViewModel.AIProviders.Count, Mode=OneWay, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical" Spacing="2" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListView.ItemsPanel>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="settings:PasteAIProviderDefinition">
|
||||
<Grid Padding="0,8,0,8" ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
Width="20"
|
||||
Height="20"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Source="{x:Bind ServiceType, Mode=OneWay, Converter={StaticResource ServiceTypeToIconConverter}}" />
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="2">
|
||||
<TextBlock Text="{x:Bind DisplayName, Mode=OneWay}" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind ServiceType, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
<Border
|
||||
Grid.Column="2"
|
||||
Padding="2,0,2,0"
|
||||
VerticalAlignment="Center"
|
||||
BorderBrush="{ThemeResource ControlStrokeColorSecondary}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}"
|
||||
Visibility="{x:Bind IsLocalModel, Mode=OneWay}">
|
||||
<TextBlock
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontSize="10"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="Local" />
|
||||
</Border>
|
||||
<!--<Border
|
||||
Grid.Column="2"
|
||||
Padding="2,0,2,0"
|
||||
VerticalAlignment="Center"
|
||||
BorderBrush="{ThemeResource TertiaryButtonBorderBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}"
|
||||
Visibility="{x:Bind EnableAdvanceAI}">
|
||||
<TextBlock
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontSize="10"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="ADVANCED" />
|
||||
</Border>-->
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<TextBlock
|
||||
x:Uid="AIProvidersEmptyText"
|
||||
Grid.Row="1"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
TextWrapping="WrapWholeWords"
|
||||
Visibility="{x:Bind ViewModel.AIProviders.Count, Mode=OneWay, Converter={StaticResource CountToInvertedVisibilityConverter}}" />
|
||||
<HyperlinkButton
|
||||
x:Uid="AIProvidersManageButtonContent"
|
||||
Grid.Row="2"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{x:Bind ViewModel.OpenSettingsCommand, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</Flyout>
|
||||
</DropDownButton.Flyout>
|
||||
</DropDownButton>
|
||||
<Grid
|
||||
Width="32"
|
||||
Height="32"
|
||||
@@ -667,9 +562,10 @@
|
||||
Command="{x:Bind GenerateCustomAICommand}"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=16}"
|
||||
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
IsEnabled="{x:Bind ViewModel.IsCustomAIAvailable, Mode=OneWay}"
|
||||
Style="{StaticResource SubtleButtonStyle}"
|
||||
TabIndex="2"
|
||||
TabIndex="1"
|
||||
Visibility="{x:Bind ViewModel.Query.Length, Mode=OneWay, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="SendBtnToolTip" TextWrapping="WrapWholeWords" />
|
||||
@@ -744,8 +640,8 @@
|
||||
x:Name="LoadingText"
|
||||
x:Uid="LoadingText"
|
||||
Grid.Row="1"
|
||||
Margin="4,4,0,0"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource AccentGradientBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Visibility="Collapsed">
|
||||
<animations:Implicit.ShowAnimations>
|
||||
|
||||
@@ -10,11 +10,9 @@ using AdvancedPaste.Models;
|
||||
using AdvancedPaste.ViewModels;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
|
||||
namespace AdvancedPaste.Controls
|
||||
{
|
||||
@@ -22,8 +20,6 @@ namespace AdvancedPaste.Controls
|
||||
{
|
||||
public OptionsViewModel ViewModel { get; private set; }
|
||||
|
||||
private bool _syncingProviderSelection;
|
||||
|
||||
public static readonly DependencyProperty PlaceholderTextProperty = DependencyProperty.Register(
|
||||
nameof(PlaceholderText),
|
||||
typeof(string),
|
||||
@@ -48,18 +44,6 @@ namespace AdvancedPaste.Controls
|
||||
set => SetValue(FooterProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ModelSelectorProperty = DependencyProperty.Register(
|
||||
nameof(ModelSelector),
|
||||
typeof(object),
|
||||
typeof(PromptBox),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
|
||||
public object ModelSelector
|
||||
{
|
||||
get => GetValue(ModelSelectorProperty);
|
||||
set => SetValue(ModelSelectorProperty, value);
|
||||
}
|
||||
|
||||
public PromptBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -76,11 +60,6 @@ namespace AdvancedPaste.Controls
|
||||
var state = ViewModel.IsBusy ? "LoadingState" : ViewModel.PasteActionError.HasText ? "ErrorState" : "DefaultState";
|
||||
VisualStateManager.GoToState(this, state, true);
|
||||
}
|
||||
|
||||
if (e.PropertyName is nameof(ViewModel.ActiveAIProvider) or nameof(ViewModel.AIProviders))
|
||||
{
|
||||
SyncProviderSelection();
|
||||
}
|
||||
}
|
||||
|
||||
private void ViewModel_PreviewRequested(object sender, EventArgs e)
|
||||
@@ -94,7 +73,6 @@ namespace AdvancedPaste.Controls
|
||||
private void Grid_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
InputTxtBox.Focus(FocusState.Programmatic);
|
||||
SyncProviderSelection();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
@@ -133,57 +111,5 @@ namespace AdvancedPaste.Controls
|
||||
{
|
||||
Loader.IsLoading = loading;
|
||||
}
|
||||
|
||||
private void SyncProviderSelection()
|
||||
{
|
||||
if (AIProviderListView is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_syncingProviderSelection = true;
|
||||
AIProviderListView.SelectedItem = ViewModel.ActiveAIProvider;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_syncingProviderSelection = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void AIProviderFlyout_Opened(object sender, object e)
|
||||
{
|
||||
SyncProviderSelection();
|
||||
}
|
||||
|
||||
private async void AIProviderListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (_syncingProviderSelection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var flyout = FlyoutBase.GetAttachedFlyout(AIProviderButton);
|
||||
|
||||
if (AIProviderListView.SelectedItem is not PasteAIProviderDefinition provider)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.Equals(ViewModel.ActiveAIProvider?.Id, provider.Id, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
flyout?.Hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ViewModel.SetActiveProviderCommand.CanExecute(provider))
|
||||
{
|
||||
await ViewModel.SetActiveProviderCommand.ExecuteAsync(provider);
|
||||
SyncProviderSelection();
|
||||
}
|
||||
|
||||
flyout?.Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace AdvancedPaste.Converters;
|
||||
|
||||
public sealed partial class CountToInvertedVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
bool hasItems = ((value is int intValue) && intValue > 0) || (value is IEnumerable enumerable && enumerable.GetEnumerator().MoveNext());
|
||||
return targetType == typeof(Visibility)
|
||||
? (hasItems ? Visibility.Collapsed : Visibility.Visible)
|
||||
: !hasItems;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
=> throw new NotSupportedException();
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.Windows.ApplicationModel.Resources;
|
||||
|
||||
namespace AdvancedPaste.Converters
|
||||
{
|
||||
public sealed partial class DateTimeToFriendlyStringConverter : IValueConverter
|
||||
{
|
||||
private static readonly ResourceLoader _resources = new ResourceLoader();
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is not DateTimeOffset dto)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Use local times to calculate relative values and formatting
|
||||
var now = DateTimeOffset.Now;
|
||||
var localValue = dto.ToLocalTime();
|
||||
var culture = !string.IsNullOrEmpty(language)
|
||||
? new CultureInfo(language)
|
||||
: CultureInfo.CurrentCulture;
|
||||
|
||||
var delta = now - localValue;
|
||||
|
||||
// Future dates: fall back to date/time formatting
|
||||
if (delta < TimeSpan.Zero)
|
||||
{
|
||||
return FormatDateAndTime(localValue, culture);
|
||||
}
|
||||
|
||||
// < 1 minute
|
||||
if (delta.TotalSeconds < 60)
|
||||
{
|
||||
return _resources.GetString("Relative_JustNow"); // "Just now"
|
||||
}
|
||||
|
||||
// < 60 minutes
|
||||
if (delta.TotalMinutes < 60)
|
||||
{
|
||||
var mins = (int)Math.Round(delta.TotalMinutes);
|
||||
if (mins <= 1)
|
||||
{
|
||||
return _resources.GetString("Relative_MinuteAgo"); // "1 minute ago"
|
||||
}
|
||||
|
||||
var fmt = _resources.GetString("Relative_MinutesAgo_Format"); // "{0} minutes ago"
|
||||
return string.Format(culture, fmt, mins);
|
||||
}
|
||||
|
||||
// Same calendar day → "Today, {time}"
|
||||
var today = now.Date;
|
||||
if (localValue.Date == today)
|
||||
{
|
||||
var time = localValue.ToString("t", culture); // localized short time
|
||||
var fmt = _resources.GetString("Relative_Today_TimeFormat"); // "Today, {0}"
|
||||
return string.Format(culture, fmt, time);
|
||||
}
|
||||
|
||||
// Yesterday → "Yesterday, {time}"
|
||||
if (localValue.Date == today.AddDays(-1))
|
||||
{
|
||||
var time = localValue.ToString("t", culture);
|
||||
var fmt = _resources.GetString("Relative_Yesterday_TimeFormat"); // "Yesterday, {0}"
|
||||
return string.Format(culture, fmt, time);
|
||||
}
|
||||
|
||||
// Within last 7 days → "{Weekday}, {time}"
|
||||
if (delta.TotalDays < 7)
|
||||
{
|
||||
var weekday = localValue.ToString("dddd", culture); // localized weekday
|
||||
var time = localValue.ToString("t", culture);
|
||||
var fmt = _resources.GetString("Relative_Weekday_TimeFormat"); // "{0}, {1}"
|
||||
return string.Format(culture, fmt, weekday, time);
|
||||
}
|
||||
|
||||
// Older → localized date + time
|
||||
return FormatDateAndTime(localValue, culture);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
private static string FormatDateAndTime(DateTimeOffset localValue, CultureInfo culture)
|
||||
{
|
||||
// Use localized short date + short time
|
||||
var date = localValue.ToString("d", culture);
|
||||
var time = localValue.ToString("t", culture);
|
||||
var fmt = _resources.GetString("Relative_Date_TimeFormat"); // "{0}, {1}"
|
||||
return string.Format(culture, fmt, date, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
|
||||
namespace AdvancedPaste.Converters;
|
||||
|
||||
public sealed partial class ServiceTypeToIconConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
string iconPath = value switch
|
||||
{
|
||||
string service when !string.IsNullOrWhiteSpace(service) => AIServiceTypeRegistry.GetIconPath(service),
|
||||
AIServiceType serviceType => AIServiceTypeRegistry.GetIconPath(serviceType),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
if (string.IsNullOrEmpty(iconPath))
|
||||
{
|
||||
iconPath = AIServiceTypeRegistry.GetIconPath(AIServiceType.Unknown);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new SvgImageSource(new Uri(iconPath));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogDebug("Failed to create SvgImageSource for AI service icon", ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
=> throw new NotSupportedException();
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pages="using:AdvancedPaste.Pages"
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
Width="486"
|
||||
Width="420"
|
||||
Height="188"
|
||||
MinWidth="486"
|
||||
MinWidth="420"
|
||||
MinHeight="188"
|
||||
Closed="WindowEx_Closed"
|
||||
IsAlwaysOnTop="True"
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
AutomationProperties.HelpText="{x:Bind Name, Mode=OneWay}"
|
||||
AutomationProperties.Name="{x:Bind AccessibleName, Mode=OneWay}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="48" />
|
||||
<ColumnDefinition Width="26" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
@@ -52,7 +52,6 @@
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
x:Phase="1"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Name, Mode=OneWay}" />
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
@@ -75,7 +74,7 @@
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Opacity="0.5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="48" />
|
||||
<ColumnDefinition Width="26" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
@@ -88,7 +87,6 @@
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
x:Phase="1"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Name, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
@@ -144,160 +142,69 @@
|
||||
</Page.KeyboardAccelerators>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid
|
||||
Margin="8,0,8,16"
|
||||
Padding="4"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="20"
|
||||
Visibility="{x:Bind ViewModel.ClipboardHasData, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:ClipboardHistoryItemPreviewControl Height="48" ClipboardItem="{x:Bind ViewModel.CurrentClipboardItem, Mode=OneWay}" />
|
||||
<Button
|
||||
x:Uid="ClipboardHistoryButton"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,4,0"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="{x:Bind ViewModel.ClipboardHistoryEnabled, Mode=TwoWay}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="ClipboardHistoryButtonToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
<FontIcon
|
||||
Margin="0,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontSize="16"
|
||||
Glyph="" />
|
||||
<Button.Flyout>
|
||||
<Flyout
|
||||
FlyoutPresenterStyle="{StaticResource PaddingLessFlyoutPresenterStyle}"
|
||||
Placement="Right"
|
||||
ShouldConstrainToRootBounds="False">
|
||||
<ItemsView
|
||||
Width="320"
|
||||
Margin="8,8,8,0"
|
||||
IsItemInvokedEnabled="True"
|
||||
ItemInvoked="ClipboardHistory_ItemInvoked"
|
||||
ItemsSource="{x:Bind clipboardHistory, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ItemsView.Layout>
|
||||
<StackLayout Orientation="Vertical" Spacing="8" />
|
||||
</ItemsView.Layout>
|
||||
<ItemsView.Transitions />
|
||||
<ItemsView.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:ClipboardItem">
|
||||
<ItemContainer
|
||||
AutomationProperties.Name="{x:Bind Description, Mode=OneWay}"
|
||||
CornerRadius="16"
|
||||
ToolTipService.ToolTip="{x:Bind Content}">
|
||||
<Grid
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
ColumnSpacing="8"
|
||||
CornerRadius="16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" MaxWidth="240" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:ClipboardHistoryItemPreviewControl
|
||||
Height="64"
|
||||
x:Phase="0"
|
||||
ClipboardItem="{x:Bind}" />
|
||||
<Button
|
||||
x:Name="ClipboardHistoryItemMoreOptionsButton"
|
||||
x:Uid="ClipboardHistoryItemMoreOptionsButton"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="16" Glyph="" />
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="ClipboardHistoryItemDeleteButton"
|
||||
Click="ClipboardHistoryItemDeleteButton_Click"
|
||||
CommandParameter="{x:Bind (local:ClipboardItem)}"
|
||||
Icon="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</Grid>
|
||||
</ItemContainer>
|
||||
</DataTemplate>
|
||||
</ItemsView.ItemTemplate>
|
||||
</ItemsView>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</Grid>
|
||||
<controls:PromptBox
|
||||
x:Name="CustomFormatTextBox"
|
||||
x:Uid="CustomFormatTextBox"
|
||||
Grid.Row="1"
|
||||
Margin="20,0,20,0"
|
||||
Margin="8,4,8,0"
|
||||
x:FieldModifier="public"
|
||||
IsEnabled="{x:Bind ViewModel.IsCustomAIServiceEnabled, Mode=OneWay}"
|
||||
TabIndex="0">
|
||||
<controls:PromptBox.Footer>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
x:Uid="AIMistakeNote"
|
||||
Margin="0,0,2,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="10"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
<Button
|
||||
Padding="0"
|
||||
Style="{StaticResource CaptionTextBlockStyle}">
|
||||
<Run x:Uid="AIMistakeNote" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
Margin="4,0,2,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<FontIcon FontSize="12" Glyph="" />
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
<Run x:Uid="AIMistakeNote" /><LineBreak /><Run
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="You are using a custom endpoint. Verify all answers." />
|
||||
</TextBlock>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<HyperlinkButton
|
||||
x:Name="TermsHyperlink"
|
||||
x:Uid="TermsLink"
|
||||
Padding="0"
|
||||
FontSize="12"
|
||||
NavigateUri="{x:Bind ViewModel.TermsLinkUri, Mode=OneWay}"
|
||||
Visibility="{x:Bind ViewModel.HasTermsLink, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<HyperlinkButton
|
||||
x:Name="PrivacyHyperLink"
|
||||
x:Uid="PrivacyLink"
|
||||
Padding="0"
|
||||
FontSize="12"
|
||||
NavigateUri="{x:Bind ViewModel.PrivacyLinkUri, Mode=OneWay}"
|
||||
Visibility="{x:Bind ViewModel.HasPrivacyLink, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
Style="{StaticResource CaptionTextBlockStyle}">
|
||||
<Hyperlink
|
||||
x:Name="TermsHyperlink"
|
||||
NavigateUri="https://openai.com/policies/terms-of-use"
|
||||
TabIndex="3">
|
||||
<Run x:Uid="TermsLink" />
|
||||
</Hyperlink>
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock Text="https://openai.com/policies/terms-of-use" />
|
||||
</ToolTipService.ToolTip>
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
Margin="0,0,2,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
ToolTipService.ToolTip="">
|
||||
<Run x:Uid="AIFooterSeparator" Foreground="{ThemeResource TextFillColorSecondaryBrush}">|</Run>
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
Margin="0,0,2,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}">
|
||||
<Hyperlink NavigateUri="https://openai.com/policies/privacy-policy" TabIndex="3">
|
||||
<Run x:Uid="PrivacyLink" />
|
||||
</Hyperlink>
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock Text="https://openai.com/policies/privacy-policy" />
|
||||
</ToolTipService.ToolTip>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</controls:PromptBox.Footer>
|
||||
</controls:PromptBox>
|
||||
<Grid Grid.Row="2" RowSpacing="4">
|
||||
<Grid
|
||||
Grid.Row="2"
|
||||
Background="{ThemeResource LayerOnAcrylicFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,1,0,0"
|
||||
RowSpacing="4">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="{x:Bind ViewModel.StandardPasteFormats.Count, Mode=OneWay, Converter={StaticResource standardPasteFormatsToHeightConverter}}" />
|
||||
<RowDefinition Height="Auto" />
|
||||
@@ -318,6 +225,7 @@
|
||||
ScrollViewer.VerticalScrollMode="Auto"
|
||||
SelectionMode="None"
|
||||
TabIndex="1" />
|
||||
|
||||
<Rectangle
|
||||
Grid.Row="1"
|
||||
Height="1"
|
||||
@@ -338,6 +246,117 @@
|
||||
ScrollViewer.VerticalScrollMode="Auto"
|
||||
SelectionMode="None"
|
||||
TabIndex="2" />
|
||||
|
||||
<Rectangle
|
||||
Grid.Row="3"
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||
<Button
|
||||
Grid.Row="4"
|
||||
Height="32"
|
||||
Margin="4,0,4,4"
|
||||
Padding="{StaticResource ButtonPadding}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
AutomationProperties.LabeledBy="{x:Bind ClipboardHistoryButton}"
|
||||
IsEnabled="{x:Bind ViewModel.ClipboardHistoryEnabled, Mode=TwoWay}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Grid
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
ColumnSpacing="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<FontIcon
|
||||
Margin="0,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontSize="16"
|
||||
Glyph="" />
|
||||
<TextBlock
|
||||
x:Name="ClipboardHistoryButton"
|
||||
x:Uid="ClipboardHistoryButton"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center" />
|
||||
<FontIcon
|
||||
Grid.Column="2"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Glyph="" />
|
||||
</Grid>
|
||||
<Button.Flyout>
|
||||
<Flyout
|
||||
FlyoutPresenterStyle="{StaticResource PaddingLessFlyoutPresenterStyle}"
|
||||
Placement="Right"
|
||||
ShouldConstrainToRootBounds="False">
|
||||
|
||||
<ListView
|
||||
Width="320"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="ClipboardHistory_ItemClick"
|
||||
ItemsSource="{x:Bind clipboardHistory, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.Transitions />
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:ClipboardItem">
|
||||
<Grid
|
||||
Height="40"
|
||||
HorizontalAlignment="Stretch"
|
||||
AutomationProperties.Name="{x:Bind Description, Mode=OneWay}"
|
||||
ColumnSpacing="8"
|
||||
ToolTipService.ToolTip="{x:Bind Content}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" MaxWidth="240" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Left"
|
||||
x:Phase="2"
|
||||
Source="{x:Bind Image}"
|
||||
Visibility="Visible" />
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
x:Phase="1"
|
||||
Text="{x:Bind Content}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Visibility="Visible" />
|
||||
<Button
|
||||
x:Name="ClipboardHistoryItemMoreOptionsButton"
|
||||
x:Uid="ClipboardHistoryItemMoreOptionsButton"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="16" Glyph="" />
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="ClipboardHistoryItemDeleteButton"
|
||||
Click="ClipboardHistoryItemDeleteButton_Click"
|
||||
CommandParameter="{x:Bind (local:ClipboardItem)}"
|
||||
Icon="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@@ -68,22 +68,11 @@ namespace AdvancedPaste.Pages
|
||||
if (item.Content.Contains(StandardDataFormats.Text))
|
||||
{
|
||||
string text = await item.Content.GetTextAsync();
|
||||
items.Add(new ClipboardItem
|
||||
{
|
||||
Content = text,
|
||||
Format = ClipboardFormat.Text,
|
||||
Timestamp = item.Timestamp,
|
||||
Item = item,
|
||||
});
|
||||
items.Add(new ClipboardItem { Content = text, Item = item });
|
||||
}
|
||||
else if (item.Content.Contains(StandardDataFormats.Bitmap))
|
||||
{
|
||||
items.Add(new ClipboardItem
|
||||
{
|
||||
Format = ClipboardFormat.Image,
|
||||
Timestamp = item.Timestamp,
|
||||
Item = item,
|
||||
});
|
||||
items.Add(new ClipboardItem { Item = item });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,9 +187,10 @@ namespace AdvancedPaste.Pages
|
||||
}
|
||||
}
|
||||
|
||||
private async void ClipboardHistory_ItemInvoked(ItemsView sender, ItemsViewItemInvokedEventArgs args)
|
||||
private async void ClipboardHistory_ItemClick(object sender, ItemClickEventArgs e)
|
||||
{
|
||||
if (args.InvokedItem is ClipboardItem item)
|
||||
var item = e.ClickedItem as ClipboardItem;
|
||||
if (item is not null)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteClipboardItemClicked());
|
||||
if (!string.IsNullOrEmpty(item.Content))
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals">
|
||||
|
||||
<Style x:Key="SubtleDropDownButtonStyle" TargetType="DropDownButton">
|
||||
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SubtleButtonBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
|
||||
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
|
||||
<Setter Property="FocusVisualMargin" Value="-3" />
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Grid
|
||||
x:Name="RootGrid"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</Grid.BackgroundTransition>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentPresenter
|
||||
x:Name="ContentPresenter"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}" />
|
||||
<AnimatedIcon
|
||||
xmlns:local="using:Microsoft.UI.Xaml.Controls"
|
||||
x:Name="ChevronIcon"
|
||||
Grid.Column="1"
|
||||
Width="12"
|
||||
Height="12"
|
||||
Margin="-4,0,0,0"
|
||||
local:AnimatedIcon.State="Normal"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Foreground="{ThemeResource DropDownButtonForegroundSecondary}">
|
||||
<animatedvisuals:AnimatedChevronDownSmallVisualSource />
|
||||
<AnimatedIcon.FallbackIconSource>
|
||||
<FontIconSource
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="8"
|
||||
Glyph=""
|
||||
IsTextScaleFactorEnabled="False" />
|
||||
</AnimatedIcon.FallbackIconSource>
|
||||
</AnimatedIcon>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ChevronIcon" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource DropDownButtonForegroundSecondaryPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ChevronIcon.(AnimatedIcon.State)" Value="PointerOver" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ChevronIcon" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource DropDownButtonForegroundSecondaryPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ChevronIcon.(AnimatedIcon.State)" Value="Pressed" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ChevronIcon" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<!-- DisabledVisual Should be handled by the control, not the animated icon. -->
|
||||
<Setter Target="ChevronIcon.(AnimatedIcon.State)" Value="Normal" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -1,54 +0,0 @@
|
||||
// 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 AdvancedPaste.Models;
|
||||
using Microsoft.SemanticKernel;
|
||||
|
||||
namespace AdvancedPaste.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Helper class for extracting AI service usage information from chat messages.
|
||||
/// </summary>
|
||||
public static class AIServiceUsageHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Extracts AI service usage information from OpenAI chat message metadata.
|
||||
/// </summary>
|
||||
/// <param name="chatMessage">The chat message containing usage metadata.</param>
|
||||
/// <returns>AI service usage information or AIServiceUsage.None if extraction fails.</returns>
|
||||
public static AIServiceUsage GetOpenAIServiceUsage(ChatMessageContent chatMessage)
|
||||
{
|
||||
// Try to get usage information from metadata
|
||||
if (chatMessage.Metadata?.TryGetValue("Usage", out var usageObj) == true)
|
||||
{
|
||||
// Handle different possible usage types through reflection to be version-agnostic
|
||||
var usageType = usageObj.GetType();
|
||||
|
||||
try
|
||||
{
|
||||
// Try common property names for prompt tokens
|
||||
var promptTokensProp = usageType.GetProperty("PromptTokens") ??
|
||||
usageType.GetProperty("InputTokens") ??
|
||||
usageType.GetProperty("InputTokenCount");
|
||||
|
||||
var completionTokensProp = usageType.GetProperty("CompletionTokens") ??
|
||||
usageType.GetProperty("OutputTokens") ??
|
||||
usageType.GetProperty("OutputTokenCount");
|
||||
|
||||
if (promptTokensProp != null && completionTokensProp != null)
|
||||
{
|
||||
var promptTokens = (int)(promptTokensProp.GetValue(usageObj) ?? 0);
|
||||
var completionTokens = (int)(completionTokensProp.GetValue(usageObj) ?? 0);
|
||||
return new AIServiceUsage(promptTokens, completionTokens);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If reflection fails, fall back to no usage
|
||||
}
|
||||
}
|
||||
|
||||
return AIServiceUsage.None;
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using AdvancedPaste.Models;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
|
||||
namespace AdvancedPaste.Helpers
|
||||
{
|
||||
internal static class ClipboardItemHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a ClipboardItem from current clipboard data.
|
||||
/// </summary>
|
||||
public static async Task<ClipboardItem> CreateFromCurrentClipboardAsync(
|
||||
DataPackageView clipboardData,
|
||||
ClipboardFormat availableFormats,
|
||||
DateTimeOffset? timestamp = null,
|
||||
BitmapImage existingImage = null)
|
||||
{
|
||||
if (clipboardData == null || availableFormats == ClipboardFormat.None)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var clipboardItem = new ClipboardItem
|
||||
{
|
||||
Format = availableFormats,
|
||||
Timestamp = timestamp,
|
||||
};
|
||||
|
||||
// Text or HTML content
|
||||
if (availableFormats.HasFlag(ClipboardFormat.Text) || availableFormats.HasFlag(ClipboardFormat.Html))
|
||||
{
|
||||
clipboardItem.Content = await clipboardData.GetTextOrEmptyAsync();
|
||||
}
|
||||
|
||||
// Image content
|
||||
else if (availableFormats.HasFlag(ClipboardFormat.Image))
|
||||
{
|
||||
// Reuse existing image if provided
|
||||
if (existingImage != null)
|
||||
{
|
||||
clipboardItem.Image = existingImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
clipboardItem.Image = await TryCreateBitmapImageAsync(clipboardData);
|
||||
}
|
||||
}
|
||||
|
||||
return clipboardItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a BitmapImage from clipboard data.
|
||||
/// </summary>
|
||||
private static async Task<BitmapImage> TryCreateBitmapImageAsync(DataPackageView clipboardData)
|
||||
{
|
||||
try
|
||||
{
|
||||
var imageReference = await clipboardData.GetBitmapAsync();
|
||||
if (imageReference != null)
|
||||
{
|
||||
using (var imageStream = await imageReference.OpenReadAsync())
|
||||
{
|
||||
var bitmapImage = new BitmapImage();
|
||||
await bitmapImage.SetSourceAsync(imageStream);
|
||||
return bitmapImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Silently fail - caller can check for null
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,11 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using AdvancedPaste.Models;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Microsoft.Win32;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using Windows.Data.Html;
|
||||
@@ -182,46 +180,6 @@ internal static class DataPackageHelpers
|
||||
}
|
||||
}
|
||||
|
||||
internal static async Task<string> GetClipboardTextOrThrowAsync(this DataPackageView dataPackageView, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(dataPackageView);
|
||||
|
||||
try
|
||||
{
|
||||
if (dataPackageView.Contains(StandardDataFormats.Text))
|
||||
{
|
||||
return await dataPackageView.GetTextAsync();
|
||||
}
|
||||
|
||||
if (dataPackageView.Contains(StandardDataFormats.Html))
|
||||
{
|
||||
var html = await dataPackageView.GetHtmlFormatAsync();
|
||||
return HtmlUtilities.ConvertToText(html);
|
||||
}
|
||||
|
||||
if (dataPackageView.Contains(StandardDataFormats.Bitmap))
|
||||
{
|
||||
var bitmap = await dataPackageView.GetImageContentAsync();
|
||||
if (bitmap != null)
|
||||
{
|
||||
return await OcrHelpers.ExtractTextAsync(bitmap, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (ex is COMException or InvalidOperationException)
|
||||
{
|
||||
throw CreateClipboardTextMissingException(ex);
|
||||
}
|
||||
|
||||
throw CreateClipboardTextMissingException();
|
||||
}
|
||||
|
||||
private static PasteActionException CreateClipboardTextMissingException(Exception innerException = null)
|
||||
{
|
||||
var message = ResourceLoaderInstance.ResourceLoader.GetString("ClipboardEmptyWarning");
|
||||
return new PasteActionException(message, innerException ?? new InvalidOperationException("Clipboard does not contain text content."));
|
||||
}
|
||||
|
||||
internal static async Task<string> GetHtmlContentAsync(this DataPackageView dataPackageView) =>
|
||||
dataPackageView.Contains(StandardDataFormats.Html) ? await dataPackageView.GetHtmlFormatAsync() : string.Empty;
|
||||
|
||||
@@ -237,22 +195,6 @@ internal static class DataPackageHelpers
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static async Task<BitmapImage> GetPreviewBitmapAsync(this DataPackageView dataPackageView)
|
||||
{
|
||||
var stream = await dataPackageView.GetImageStreamAsync();
|
||||
if (stream == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using (stream)
|
||||
{
|
||||
var bitmapImage = new BitmapImage();
|
||||
bitmapImage.SetSource(stream);
|
||||
return bitmapImage;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IRandomAccessStream> GetImageStreamAsync(this DataPackageView dataPackageView)
|
||||
{
|
||||
if (dataPackageView.Contains(StandardDataFormats.StorageItems))
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using AdvancedPaste.Models;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
@@ -13,7 +12,7 @@ namespace AdvancedPaste.Settings
|
||||
{
|
||||
public interface IUserSettings
|
||||
{
|
||||
public bool IsAIEnabled { get; }
|
||||
public bool IsAdvancedAIEnabled { get; }
|
||||
|
||||
public bool ShowCustomPreview { get; }
|
||||
|
||||
@@ -23,10 +22,6 @@ namespace AdvancedPaste.Settings
|
||||
|
||||
public IReadOnlyList<PasteFormats> AdditionalActions { get; }
|
||||
|
||||
public PasteAIConfiguration PasteAIConfiguration { get; }
|
||||
|
||||
public event EventHandler Changed;
|
||||
|
||||
Task SetActiveAIProviderAsync(string providerId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ using AdvancedPaste.Models;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Windows.Security.Credentials;
|
||||
|
||||
namespace AdvancedPaste.Settings
|
||||
{
|
||||
@@ -34,7 +33,7 @@ namespace AdvancedPaste.Settings
|
||||
|
||||
public event EventHandler Changed;
|
||||
|
||||
public bool IsAIEnabled { get; private set; }
|
||||
public bool IsAdvancedAIEnabled { get; private set; }
|
||||
|
||||
public bool ShowCustomPreview { get; private set; }
|
||||
|
||||
@@ -44,16 +43,13 @@ namespace AdvancedPaste.Settings
|
||||
|
||||
public IReadOnlyList<AdvancedPasteCustomAction> CustomActions => _customActions;
|
||||
|
||||
public PasteAIConfiguration PasteAIConfiguration { get; private set; }
|
||||
|
||||
public UserSettings(IFileSystem fileSystem)
|
||||
{
|
||||
_settingsUtils = new SettingsUtils(fileSystem);
|
||||
|
||||
IsAIEnabled = false;
|
||||
IsAdvancedAIEnabled = false;
|
||||
ShowCustomPreview = true;
|
||||
CloseAfterLosingFocus = false;
|
||||
PasteAIConfiguration = new PasteAIConfiguration();
|
||||
_additionalActions = [];
|
||||
_customActions = [];
|
||||
_taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
@@ -98,16 +94,13 @@ namespace AdvancedPaste.Settings
|
||||
var settings = _settingsUtils.GetSettingsOrDefault<AdvancedPasteSettings>(AdvancedPasteModuleName);
|
||||
if (settings != null)
|
||||
{
|
||||
bool migratedLegacyEnablement = TryMigrateLegacyAIEnablement(settings);
|
||||
|
||||
void UpdateSettings()
|
||||
{
|
||||
var properties = settings.Properties;
|
||||
|
||||
IsAIEnabled = properties.IsAIEnabled;
|
||||
IsAdvancedAIEnabled = properties.IsAdvancedAIEnabled;
|
||||
ShowCustomPreview = properties.ShowCustomPreview;
|
||||
CloseAfterLosingFocus = properties.CloseAfterLosingFocus;
|
||||
PasteAIConfiguration = properties.PasteAIConfiguration ?? new PasteAIConfiguration();
|
||||
|
||||
var sourceAdditionalActions = properties.AdditionalActions;
|
||||
(PasteFormats Format, IAdvancedPasteAction[] Actions)[] additionalActionFormats =
|
||||
@@ -133,11 +126,6 @@ namespace AdvancedPaste.Settings
|
||||
Task.Factory
|
||||
.StartNew(UpdateSettings, CancellationToken.None, TaskCreationOptions.None, _taskScheduler)
|
||||
.Wait();
|
||||
|
||||
if (migratedLegacyEnablement)
|
||||
{
|
||||
settings.Save(_settingsUtils);
|
||||
}
|
||||
}
|
||||
|
||||
retry = false;
|
||||
@@ -156,114 +144,6 @@ namespace AdvancedPaste.Settings
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryMigrateLegacyAIEnablement(AdvancedPasteSettings settings)
|
||||
{
|
||||
if (settings?.Properties is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (settings.Properties.IsAIEnabled || !LegacyOpenAIKeyExists())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
settings.Properties.IsAIEnabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool LegacyOpenAIKeyExists()
|
||||
{
|
||||
try
|
||||
{
|
||||
PasswordVault vault = new();
|
||||
return vault.Retrieve("https://platform.openai.com/api-keys", "PowerToys_AdvancedPaste_OpenAIKey") is not null;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SetActiveAIProviderAsync(string providerId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(providerId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
var settings = _settingsUtils.GetSettingsOrDefault<AdvancedPasteSettings>(AdvancedPasteModuleName);
|
||||
var configuration = settings?.Properties?.PasteAIConfiguration;
|
||||
var providers = configuration?.Providers;
|
||||
|
||||
if (configuration == null || providers == null || providers.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var target = providers.FirstOrDefault(provider => string.Equals(provider.Id, providerId, StringComparison.OrdinalIgnoreCase));
|
||||
if (target == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.Equals(configuration.ActiveProvider?.Id, providerId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
configuration.ActiveProviderId = providerId;
|
||||
|
||||
foreach (var provider in providers)
|
||||
{
|
||||
provider.IsActive = string.Equals(provider.Id, providerId, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
settings.Save(_settingsUtils);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed to set active AI provider", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Task.Factory
|
||||
.StartNew(
|
||||
() =>
|
||||
{
|
||||
PasteAIConfiguration.ActiveProviderId = providerId;
|
||||
|
||||
if (PasteAIConfiguration.Providers is not null)
|
||||
{
|
||||
foreach (var provider in PasteAIConfiguration.Providers)
|
||||
{
|
||||
provider.IsActive = string.Equals(provider.Id, providerId, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
Changed?.Invoke(this, EventArgs.Empty);
|
||||
},
|
||||
CancellationToken.None,
|
||||
TaskCreationOptions.None,
|
||||
_taskScheduler)
|
||||
.Wait();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed to dispatch active AI provider change", ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using AdvancedPaste.Helpers;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
@@ -13,15 +12,10 @@ public class ClipboardItem
|
||||
{
|
||||
public string Content { get; set; }
|
||||
|
||||
public BitmapImage Image { get; set; }
|
||||
|
||||
public ClipboardFormat Format { get; set; }
|
||||
|
||||
public DateTimeOffset? Timestamp { get; set; }
|
||||
|
||||
// Only used for clipboard history items that have a ClipboardHistoryItem
|
||||
public ClipboardHistoryItem Item { get; set; }
|
||||
|
||||
public BitmapImage Image { get; set; }
|
||||
|
||||
public string Description => !string.IsNullOrEmpty(Content) ? Content :
|
||||
Image is not null ? ResourceLoaderInstance.ResourceLoader.GetString("ClipboardHistoryImage") :
|
||||
string.Empty;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user