mirror of
https://github.com/microsoft/PowerToys
synced 2024-11-21 15:53:19 +00:00
Introduce Command Not Found module (#26319)
* Introduce Command Not Found module * rewrite module to depend on WinGet PowerShell module * address Dongbo's feedback * try and implement settings UI * fix SUI build; try and store PowerShell object * add and use object pool * apply Dongbo's feedback * add warm up; implement IPooledObjectPolicy * Add module interface * WIP trying to import module from settings * Add EnableModule.ps1 * spellcheck * spellcheck again * Installer. Add DisableModule.ps1 * Fix styling * Give the user some output from installing * Prettify the Settings controls * Add button to check PowerShell 7's version * Fix Settings Assets paths * Fix PowerShell 7 output * Make module enable and disable scripts give better information * Fix spellcheck * Fix image files and placeholders * Don't remove CmdNotFound on upgrade and don't fail on uninstall of CmdNotFound * Consistent install module scripts location on debug and installed * installer: Avoid messageboxes and hide powershell on uninstalling CmdNotFound * Fix psd1 file resolution when installed * Fix spellcheck * Add telemetry events * Fix gpo files * If GPO is set, enable/disable module on PT start depending on gpo value * Cleanup module interface * Cleanup settings code * If GPO is set, disable Settings page logic * Adding icons * Update settings UI and strings * Add telemetry for suggestions and feedbacks * Fix sln file * Fix build * minor fixes * Updating icon * Remove global.json * Remove unused PowerShell dependency * Don't use preview version of Automation and fix NOTICE * Fix signing * Fix NOTICE.md * Fix version checking for getfilesiginforedist.dll * Fix spellchecker * Fix README.md * Fix false positives section in expect.txt * Add logs to module interface --------- Co-authored-by: Stefan Markovic <stefan@janeasystems.com> Co-authored-by: Jaime Bernardo <jaime@janeasystems.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
parent
3b90f73bd0
commit
46f5316858
27
.github/actions/spell-check/expect.txt
vendored
27
.github/actions/spell-check/expect.txt
vendored
@ -161,7 +161,6 @@ CHANGECBCHAIN
|
||||
changecursor
|
||||
CHILDACTIVATE
|
||||
CHILDWINDOW
|
||||
CHT
|
||||
cidl
|
||||
cim
|
||||
CImage
|
||||
@ -182,6 +181,7 @@ clrcall
|
||||
CLSCTX
|
||||
Clusion
|
||||
cmder
|
||||
CMDNOTFOUNDMODULEINTERFACE
|
||||
Cmds
|
||||
CMIC
|
||||
CMINVOKECOMMANDINFO
|
||||
@ -219,7 +219,6 @@ CONFIGW
|
||||
CONFLICTINGMODIFIERKEY
|
||||
CONFLICTINGMODIFIERSHORTCUT
|
||||
CONOUT
|
||||
constexpr
|
||||
consts
|
||||
contentdialog
|
||||
contentfiles
|
||||
@ -319,7 +318,6 @@ DESKTOPABSOLUTEEDITING
|
||||
DESKTOPABSOLUTEPARSING
|
||||
desktopshorcutinstalled
|
||||
desktopwindowxamlsource
|
||||
DEU
|
||||
devblogs
|
||||
devdocs
|
||||
devenum
|
||||
@ -508,6 +506,7 @@ GETCLIENTAREAANIMATION
|
||||
GETDESKWALLPAPER
|
||||
GETDLGCODE
|
||||
GETDPISCALEDSIZE
|
||||
getfilesiginforedist
|
||||
GETICON
|
||||
GETMINMAXINFO
|
||||
GETPROPERTYSTOREFLAGS
|
||||
@ -538,7 +537,6 @@ Hanzi
|
||||
Hardlines
|
||||
hardlinks
|
||||
HARDWAREINPUT
|
||||
hashcode
|
||||
Hashset
|
||||
hashtag
|
||||
HASHVAL
|
||||
@ -557,7 +555,6 @@ hcwhite
|
||||
hdc
|
||||
hdrop
|
||||
hdwwiz
|
||||
HEB
|
||||
Helpline
|
||||
helptext
|
||||
HGFE
|
||||
@ -720,7 +717,6 @@ jif
|
||||
jjw
|
||||
jobject
|
||||
jpe
|
||||
JPN
|
||||
jpnime
|
||||
Jsons
|
||||
jsonval
|
||||
@ -746,10 +742,7 @@ killrunner
|
||||
Knownfolders
|
||||
KSPROPERTY
|
||||
Kybd
|
||||
LAlt
|
||||
Lambson
|
||||
languagesjson
|
||||
langword
|
||||
lastcodeanalysissucceeded
|
||||
Lastdevice
|
||||
LAYOUTRTL
|
||||
@ -907,6 +900,8 @@ MOUSEHWHEEL
|
||||
MOUSEINPUT
|
||||
MOVESIZEEND
|
||||
MOVESIZESTART
|
||||
MOZILLAPL
|
||||
MOZPL
|
||||
mpmc
|
||||
MRM
|
||||
MRT
|
||||
@ -972,6 +967,7 @@ newdev
|
||||
newitem
|
||||
newpath
|
||||
newrow
|
||||
newsgroups
|
||||
NIF
|
||||
NLD
|
||||
NLog
|
||||
@ -984,7 +980,6 @@ NOCLOSEPROCESS
|
||||
NOCOALESCE
|
||||
NOCOPYBITS
|
||||
nodeca
|
||||
nodiscard
|
||||
nodoc
|
||||
NODRAWCAPTION
|
||||
NODRAWICON
|
||||
@ -1093,7 +1088,6 @@ pcch
|
||||
pcelt
|
||||
pch
|
||||
PCIDLIST
|
||||
pcs
|
||||
PCWSTR
|
||||
pdisp
|
||||
pdo
|
||||
@ -1304,7 +1298,6 @@ RKey
|
||||
RNumber
|
||||
roadmap
|
||||
rop
|
||||
roundf
|
||||
ROUNDSMALL
|
||||
rpcrt
|
||||
RRF
|
||||
@ -1320,12 +1313,11 @@ rundll
|
||||
rungameid
|
||||
RUNLEVEL
|
||||
runsettings
|
||||
runspace
|
||||
runtimeclass
|
||||
runtimeobject
|
||||
runtimepack
|
||||
runtimes
|
||||
RUS
|
||||
RValue
|
||||
rvm
|
||||
rwin
|
||||
rwl
|
||||
@ -1506,7 +1498,6 @@ subquery
|
||||
Superbar
|
||||
sut
|
||||
svchost
|
||||
SVE
|
||||
SVGIn
|
||||
SVGIO
|
||||
svgz
|
||||
@ -1579,7 +1570,6 @@ tlbimp
|
||||
TMPVAR
|
||||
TNP
|
||||
toggleswitch
|
||||
tonos
|
||||
toolkitcontrols
|
||||
toolkitconverters
|
||||
Toolset
|
||||
@ -1715,7 +1705,6 @@ wcsnicmp
|
||||
WDA
|
||||
wdp
|
||||
wdupenv
|
||||
weakme
|
||||
webbrowsers
|
||||
webcam
|
||||
webpage
|
||||
@ -1724,7 +1713,6 @@ wekyb
|
||||
Wevtapi
|
||||
wgpocpl
|
||||
WIC
|
||||
wifi
|
||||
wil
|
||||
winapi
|
||||
winappdriver
|
||||
@ -1852,9 +1840,6 @@ zonable
|
||||
zoneset
|
||||
Zoneszonabletester
|
||||
zzz
|
||||
newsgroups
|
||||
MOZILLAPL
|
||||
MOZPL
|
||||
|
||||
# FALSE POSITIVES
|
||||
|
||||
|
3
.github/actions/spell-check/patterns.txt
vendored
3
.github/actions/spell-check/patterns.txt
vendored
@ -118,6 +118,9 @@ aka\.ms/[a-zA-Z0-9]+
|
||||
# YouTube url
|
||||
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
|
||||
|
||||
# power shell gallery website
|
||||
\bpowershellgallery.com/[-_a-zA-Z0-9()=./%]*
|
||||
|
||||
# uuid: (or CompGUIDPrefix)
|
||||
L?(["']|[-<({>]|\b)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{10,12}(?:\g{-1}|[<})>])
|
||||
|
||||
|
@ -28,7 +28,10 @@
|
||||
|
||||
"PowerToys.AlwaysOnTop.exe",
|
||||
"PowerToys.AlwaysOnTopModuleInterface.dll",
|
||||
|
||||
|
||||
"PowerToys.CmdNotFoundModuleInterface.dll",
|
||||
"PowerToys.CmdNotFound.dll",
|
||||
|
||||
"PowerToys.ColorPicker.dll",
|
||||
"PowerToys.ColorPickerUI.dll",
|
||||
"PowerToys.ColorPickerUI.exe",
|
||||
@ -251,6 +254,7 @@
|
||||
"Mages.Core.dll",
|
||||
"JetBrains.Annotations.dll",
|
||||
"NLog.Extensions.Logging.dll",
|
||||
"getfilesiginforedist.dll",
|
||||
"concrt140_app.dll",
|
||||
"msvcp140_1_app.dll",
|
||||
"msvcp140_2_app.dll",
|
||||
|
@ -24,6 +24,7 @@ $versionExceptions = @(
|
||||
$nullVersionExceptions = @(
|
||||
"codicon.ttf",
|
||||
"e_sqlite3.dll",
|
||||
"getfilesiginforedist.dll",
|
||||
"vcamp140_app.dll",
|
||||
"vcruntime140_app.dll",
|
||||
"vcruntime140_1_app.dll",
|
||||
|
@ -33,6 +33,7 @@
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.ObjectPool" Version="5.0.17" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2088.41" />
|
||||
@ -66,6 +67,7 @@
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="17.2.3" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="17.2.3" />
|
||||
<PackageVersion Include="System.Management" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Management.Automation" Version="7.4.0" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.0-preview.9" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="8.0.0" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="8.0.0" />
|
||||
|
@ -1321,6 +1321,7 @@ EXHIBIT A -Mozilla Public License.
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 8.0.0
|
||||
- Microsoft.Extensions.Logging 8.0.0
|
||||
- Microsoft.Extensions.Logging.Abstractions 8.0.0
|
||||
- Microsoft.Extensions.ObjectPool 5.0.17
|
||||
- Microsoft.NET.Test.Sdk 17.6.3
|
||||
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
|
||||
- Microsoft.Web.WebView2 1.0.2088.41
|
||||
@ -1350,6 +1351,7 @@ EXHIBIT A -Mozilla Public License.
|
||||
- System.IO.Abstractions 17.2.3
|
||||
- System.IO.Abstractions.TestingHelpers 17.2.3
|
||||
- System.Management 8.0.0
|
||||
- System.Management.Automation 7.4.0
|
||||
- System.Reactive 6.0.0-preview.9
|
||||
- System.Runtime.Caching 8.0.0
|
||||
- System.ServiceProcess.ServiceController 8.0.0
|
||||
|
@ -538,6 +538,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CropAndLock", "src\modules\
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CropAndLockModuleInterface", "src\modules\CropAndLock\CropAndLockModuleInterface\CropAndLockModuleInterface.vcxproj", "{3157FA75-86CF-4EE2-8F62-C43F776493C6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CmdNotFound", "src\modules\cmdNotFound\CmdNotFound\CmdNotFound.csproj", "{A37865FE-2881-449F-8ADB-B8CD373D6D79}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cmdNotFound", "cmdNotFound", "{4C0D0746-BE5B-49EE-BD5D-A7811628AE8B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-FancyZonesEditor", "src\modules\fancyzones\UnitTests-FancyZonesEditor\UnitTests-FancyZonesEditor.csproj", "{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EnvironmentVariables", "EnvironmentVariables", "{538ED0BB-B863-4B20-98CC-BCDF7FA0B68A}"
|
||||
@ -558,6 +562,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-QoiPreviewHandler
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-QoiThumbnailProvider", "src\modules\previewpane\UnitTests-QoiThumbnailProvider\UnitTests-QoiThumbnailProvider.csproj", "{F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdNotFoundModuleInterface", "src\modules\cmdNotFound\CmdNotFoundModuleInterface\CmdNotFoundModuleInterface.vcxproj", "{0014D652-901F-4456-8D65-06FC5F997FB0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
@ -2328,6 +2334,18 @@ Global
|
||||
{3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|x64.Build.0 = Release|x64
|
||||
{3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|x86.ActiveCfg = Release|x64
|
||||
{3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|x86.Build.0 = Release|x64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|x64.Build.0 = Debug|x64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|x86.Build.0 = Debug|x64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|x64.ActiveCfg = Release|x64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|x64.Build.0 = Release|x64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|x86.ActiveCfg = Release|x64
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|x86.Build.0 = Release|x64
|
||||
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@ -2436,6 +2454,18 @@ Global
|
||||
{F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Release|x64.Build.0 = Release|x64
|
||||
{F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Release|x86.ActiveCfg = Release|x64
|
||||
{F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Release|x86.Build.0 = Release|x64
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Debug|x64.Build.0 = Debug|x64
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Debug|x86.Build.0 = Debug|Win32
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Release|x64.ActiveCfg = Release|x64
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Release|x64.Build.0 = Release|x64
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Release|x86.ActiveCfg = Release|Win32
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -2630,6 +2660,8 @@ Global
|
||||
{3B227528-4BA6-4CAF-B44A-A10C78A64849} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{F5E1146E-B7B3-4E11-85FD-270A500BD78C} = {3B227528-4BA6-4CAF-B44A-A10C78A64849}
|
||||
{3157FA75-86CF-4EE2-8F62-C43F776493C6} = {3B227528-4BA6-4CAF-B44A-A10C78A64849}
|
||||
{A37865FE-2881-449F-8ADB-B8CD373D6D79} = {4C0D0746-BE5B-49EE-BD5D-A7811628AE8B}
|
||||
{4C0D0746-BE5B-49EE-BD5D-A7811628AE8B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
|
||||
{538ED0BB-B863-4B20-98CC-BCDF7FA0B68A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA} = {538ED0BB-B863-4B20-98CC-BCDF7FA0B68A}
|
||||
@ -2640,6 +2672,7 @@ Global
|
||||
{6B04803D-B418-4833-A67E-B0FC966636A5} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{3940AD4D-F748-4BE4-9083-85769CD553EF} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{0014D652-901F-4456-8D65-06FC5F997FB0} = {4C0D0746-BE5B-49EE-BD5D-A7811628AE8B}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||
|
16
README.md
16
README.md
@ -17,14 +17,14 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
|
||||
|
||||
| | Current utilities: | |
|
||||
|--------------|--------------------|--------------|
|
||||
| [Always on Top](https://aka.ms/PowerToysOverview_AoT) | [PowerToys Awake](https://aka.ms/PowerToysOverview_Awake) | [Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) |
|
||||
| [Crop And Lock](https://aka.ms/PowerToysOverview_CropAndLock) | [Environment Variables](https://aka.ms/PowerToysOverview_EnvironmentVariables) | [FancyZones](https://aka.ms/PowerToysOverview_FancyZones) |
|
||||
| [File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) | [Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) |
|
||||
| [Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) | [Mouse utilities](https://aka.ms/PowerToysOverview_MouseUtilities) |
|
||||
| [Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) | [Peek](https://aka.ms/PowerToysOverview_Peek) | [Paste as Plain Text](https://aka.ms/PowerToysOverview_PastePlain) |
|
||||
| [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) |
|
||||
| [Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) |
|
||||
| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Video Conference Mute](https://aka.ms/PowerToysOverview_VideoConference) |
|
||||
| [Always on Top](https://aka.ms/PowerToysOverview_AoT) | [PowerToys Awake](https://aka.ms/PowerToysOverview_Awake) | [Command Not Found](https://aka.ms/PowerToysOverview_CmdNotFound) |
|
||||
| [Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) | [Crop And Lock](https://aka.ms/PowerToysOverview_CropAndLock) | [Environment Variables](https://aka.ms/PowerToysOverview_EnvironmentVariables) |
|
||||
| [FancyZones](https://aka.ms/PowerToysOverview_FancyZones) | [File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) |
|
||||
| [Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) | [Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) |
|
||||
| [Mouse utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) | [Peek](https://aka.ms/PowerToysOverview_Peek) |
|
||||
| [Paste as Plain Text](https://aka.ms/PowerToysOverview_PastePlain) | [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) |
|
||||
| [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | [Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) |
|
||||
| [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) | [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Video Conference Mute](https://aka.ms/PowerToysOverview_VideoConference) |
|
||||
|
||||
## Installing and running Microsoft PowerToys
|
||||
|
||||
|
BIN
doc/images/icons/Command Not Found.png
Normal file
BIN
doc/images/icons/Command Not Found.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
24
installer/PowerToysSetup/CmdNotFound.wxs
Normal file
24
installer/PowerToysSetup/CmdNotFound.wxs
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
|
||||
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="INSTALLFOLDER" FileSource="$(var.BinDir)">
|
||||
<!-- !Warning! Make sure to change Component Guid if you update the file list -->
|
||||
<Component Id="Module_CmdNotFound" Win64="yes" Guid="80F648F2-29F6-4685-AED4-04DC1B6EE176">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="Module_CmdNotFound" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Source="$(var.BinDir)WinGetCommandNotFound.psd1" />
|
||||
<!-- The dll files will be picked up by BaseApplications generateAllFileComponents.ps1-->
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<ComponentGroup Id="CmdNotFoundComponentGroup">
|
||||
<ComponentRef Id="Module_CmdNotFound" />
|
||||
</ComponentGroup>
|
||||
|
||||
</Fragment>
|
||||
</Wix>
|
@ -18,6 +18,7 @@
|
||||
<?define PastePlainProjectName="PastePlain"?>
|
||||
<?define RegistryPreviewProjectName="RegistryPreview"?>
|
||||
<?define PeekProjectName="Peek"?>
|
||||
<?define CmdNotFoundProjectName="CmdNotFound"?>
|
||||
|
||||
<?define RepoDir="$(var.ProjectDir)..\..\" ?>
|
||||
<?if $(var.Platform) = x64?>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureNuGetPackageBuildImports" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureNuGetPackageBuildImports"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\wix.props" Condition="Exists('..\wix.props')" />
|
||||
<Import Project="..\..\src\Version.props" />
|
||||
<PropertyGroup Condition="'$(Platform)' == 'x64'">
|
||||
@ -14,7 +15,7 @@ SET PTRoot=$(SolutionDir)\..
|
||||
call "..\..\..\publish.cmd" x64
|
||||
)
|
||||
call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuildThisFileDirectory)\generateMonacoWxs.ps1 -monacoWxsFile "$(MSBuildThisFileDirectory)\MonacoSRC.wxs"
|
||||
</PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Platform)' != 'x64'">
|
||||
@ -25,7 +26,7 @@ SET PTRoot=$(SolutionDir)\..
|
||||
call "..\..\..\publish.cmd" arm64
|
||||
)
|
||||
call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuildThisFileDirectory)\generateMonacoWxs.ps1 -monacoWxsFile "$(MSBuildThisFileDirectory)\MonacoSRC.wxs"
|
||||
</PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||
@ -67,7 +68,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- We do not support debug installer builds -->
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||
<Platform>$(Platform)</Platform>
|
||||
<ProductVersion>3.10</ProductVersion>
|
||||
<ProjectGuid>022a9d30-7c4f-416d-a9df-5ff2661cc0ad</ProjectGuid>
|
||||
@ -103,6 +104,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
|
||||
<Compile Include="Awake.wxs" />
|
||||
<Compile Include="BaseApplications.wxs" />
|
||||
<Compile Include="CmdNotFound.wxs" />
|
||||
<Compile Include="ColorPicker.wxs" />
|
||||
<Compile Include="EnvironmentVariables.wxs" />
|
||||
<Compile Include="FileExplorerPreview.wxs" />
|
||||
@ -180,17 +182,6 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
<Target Name="AfterBuild">
|
||||
</Target> -->
|
||||
<Target Name="BeforeBuild">
|
||||
<HeatDirectory Directory="..\..\src\common\FilePreviewCommon\Assets\Monaco\monacoSRC"
|
||||
PreprocessorVariable="var.MonacoSRCHarvestPath"
|
||||
OutputFile="MonacoSRC.wxs"
|
||||
ComponentGroupName="MonacoSRCHeatGenerated"
|
||||
DirectoryRefId="MonacoPreviewHandlerMonacoSRCFolder"
|
||||
AutogenerateGuids="false"
|
||||
GenerateGuidsNow="true"
|
||||
ToolPath="$(WixToolPath)"
|
||||
RunAsSeparateProcess="true"
|
||||
SuppressFragments="false"
|
||||
SuppressRegistry="false"
|
||||
SuppressRootDirectory="true"/>
|
||||
<HeatDirectory Directory="..\..\src\common\FilePreviewCommon\Assets\Monaco\monacoSRC" PreprocessorVariable="var.MonacoSRCHarvestPath" OutputFile="MonacoSRC.wxs" ComponentGroupName="MonacoSRCHeatGenerated" DirectoryRefId="MonacoPreviewHandlerMonacoSRCFolder" AutogenerateGuids="false" GenerateGuidsNow="true" ToolPath="$(WixToolPath)" RunAsSeparateProcess="true" SuppressFragments="false" SuppressRegistry="false" SuppressRootDirectory="true"/>
|
||||
</Target>
|
||||
</Project>
|
@ -72,6 +72,7 @@
|
||||
<ComponentGroupRef Id="VideoConferenceComponentGroup" />
|
||||
<ComponentGroupRef Id="MouseWithoutBordersComponentGroup" />
|
||||
<ComponentGroupRef Id="EnvironmentVariablesComponentGroup" />
|
||||
<ComponentGroupRef Id="CmdNotFoundComponentGroup" />
|
||||
|
||||
<ComponentGroupRef Id="ResourcesComponentGroup" />
|
||||
<ComponentGroupRef Id="WindowsAppSDKComponentGroup" />
|
||||
@ -133,6 +134,7 @@
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="DetectPrevInstallPath" After="AppSearch" />
|
||||
<Custom Action="SetLaunchPowerToysParam" Before="LaunchPowerToys" />
|
||||
<Custom Action="SetUninstallCommandNotFoundParam" Before="UninstallCommandNotFound" />
|
||||
<Custom Action="SetApplyModulesRegistryChangeSetsParam" Before="ApplyModulesRegistryChangeSets" />
|
||||
<Custom Action="SetUnApplyModulesRegistryChangeSetsParam" Before="UnApplyModulesRegistryChangeSets" />
|
||||
<Custom Action="CheckGPO" After="InstallInitialize">
|
||||
@ -159,6 +161,9 @@
|
||||
<Custom Action="UnRegisterContextMenuPackages" Before="RemoveFiles">
|
||||
Installed AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
<Custom Action="UninstallCommandNotFound" Before="RemoveFiles">
|
||||
Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
<Custom Action="UninstallServicesTask" After="InstallFinalize">
|
||||
Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
@ -200,6 +205,10 @@
|
||||
Property="UnApplyModulesRegistryChangeSets"
|
||||
Value="[INSTALLFOLDER]" />
|
||||
|
||||
<CustomAction Id="SetUninstallCommandNotFoundParam"
|
||||
Property="UninstallCommandNotFound"
|
||||
Value="[INSTALLFOLDER]" />
|
||||
|
||||
<CustomAction Id="SetCreateWinAppSDKHardlinksParam"
|
||||
Property="CreateWinAppSDKHardlinks"
|
||||
Value="[INSTALLFOLDER]" />
|
||||
@ -252,7 +261,15 @@
|
||||
BinaryKey="PTCustomActions"
|
||||
DllEntry="UninstallServicesCA"
|
||||
/>
|
||||
|
||||
|
||||
<CustomAction Id="UninstallCommandNotFound"
|
||||
Return="ignore"
|
||||
Impersonate="yes"
|
||||
Execute="deferred"
|
||||
BinaryKey="PTCustomActions"
|
||||
DllEntry="UninstallCommandNotFoundModuleCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="TelemetryLogInstallSuccess"
|
||||
Return="ignore"
|
||||
Impersonate="yes"
|
||||
|
@ -19,12 +19,14 @@
|
||||
<Fragment>
|
||||
<DirectoryRef Id="WinUI3AppsAssetsFolder">
|
||||
<Directory Id="SettingsV2AssetsInstallFolder" Name="Settings">
|
||||
<Directory Id="SettingsAppAssetsScriptsFolder" Name="Scripts"/>
|
||||
<Directory Id="SettingsV2OOBEAssetsFluentIconsInstallFolder" Name="FluentIcons" />
|
||||
<Directory Id="SettingsV2AssetsModulesInstallFolder" Name="Modules" >
|
||||
<Directory Id="SettingsV2OOBEAssetsModulesInstallFolder" Name="OOBE" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="SettingsV2AssetsInstallFolder" FileSource="$(var.SettingsV2AssetsFilesPath)">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--SettingsV2AssetsFiles_Component_Def-->
|
||||
@ -45,6 +47,16 @@
|
||||
<!--SettingsV2OOBEAssetsFluentIconsFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="SettingsAppAssetsScriptsFolder" FileSource="$(var.SettingsV2AssetsFilesPath)\Scripts\">
|
||||
<Component Id="CommandNotFound_Scripts" Win64="yes" Guid="898EFA1E-EDD3-4F4B-8C7F-4A14B0D05B02">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="CommandNotFound_Scripts" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Id="CommandNotFound_Scripts_EnableModule.ps1" Source="$(var.SettingsV2AssetsFilesPath)\Scripts\EnableModule.ps1" />
|
||||
<File Id="CommandNotFound_Scripts_DisableModule.ps1" Source="$(var.SettingsV2AssetsFilesPath)\Scripts\DisableModule.ps1" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<ComponentGroup Id="SettingsComponentGroup">
|
||||
|
||||
<Component Id="RemoveSettingsFolder" Guid="2D3AEF68-4E5A-4FF9-A5C0-9E53391AC754" Directory="SettingsV2AssetsInstallFolder" >
|
||||
@ -55,7 +67,9 @@
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2OOBEAssetsFluentIconsInstallFolder" Directory="SettingsV2OOBEAssetsFluentIconsInstallFolder" On="uninstall"/>
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2AssetsModulesInstallFolder" Directory="SettingsV2AssetsModulesInstallFolder" On="uninstall"/>
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2OOBEAssetsModulesInstallFolder" Directory="SettingsV2OOBEAssetsModulesInstallFolder" On="uninstall"/>
|
||||
<RemoveFolder Id="RemoveFolderSettingsAppAssetsScriptsFolder" Directory="SettingsAppAssetsScriptsFolder" On="uninstall"/>
|
||||
</Component>
|
||||
<ComponentRef Id="CommandNotFound_Scripts"/>
|
||||
</ComponentGroup>
|
||||
|
||||
</Fragment>
|
||||
|
@ -433,7 +433,29 @@ UINT __stdcall RemoveWindowsServiceByName(std::wstring serviceName)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT __stdcall UninstallCommandNotFoundModuleCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
std::wstring installationFolder;
|
||||
std::string command;
|
||||
|
||||
hr = WcaInitialize(hInstall, "UninstallCommandNotFoundModule");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
hr = getInstallFolder(hInstall, installationFolder);
|
||||
ExitOnFailure(hr, "Failed to get installFolder.");
|
||||
|
||||
command = "pwsh.exe";
|
||||
command += " ";
|
||||
command += "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + winrt::to_string(installationFolder) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\DisableModule.ps1" + "\"";
|
||||
|
||||
system(command.c_str());
|
||||
|
||||
LExit:
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall UninstallServicesCA(MSIHANDLE hInstall)
|
||||
{
|
||||
|
@ -22,4 +22,5 @@ EXPORTS
|
||||
UninstallVirtualCameraDriverCA
|
||||
UnRegisterContextMenuPackagesCA
|
||||
UninstallEmbeddedMSIXCA
|
||||
UninstallServicesCA
|
||||
UninstallServicesCA
|
||||
UninstallCommandNotFoundModuleCA
|
@ -12,6 +12,10 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredAwakeEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredCmdNotFoundEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredCmdNotFoundEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredColorPickerEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredColorPickerEnabledValue());
|
||||
|
@ -9,6 +9,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
GPOWrapper() = default;
|
||||
static GpoRuleConfigured GetConfiguredAlwaysOnTopEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredAwakeEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCmdNotFoundEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredColorPickerEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCropAndLockEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredFancyZonesEnabledValue();
|
||||
|
@ -13,6 +13,7 @@ namespace PowerToys
|
||||
[default_interface] static runtimeclass GPOWrapper {
|
||||
static GpoRuleConfigured GetConfiguredAlwaysOnTopEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredAwakeEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCmdNotFoundEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredColorPickerEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCropAndLockEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredFancyZonesEnabledValue();
|
||||
|
@ -27,6 +27,11 @@ namespace PowerToys.GPOWrapperProjection
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredFancyZonesEnabledValue();
|
||||
}
|
||||
|
||||
public static GpoRuleConfigured GetConfiguredCmdNotFoundEnabledValue()
|
||||
{
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredCmdNotFoundEnabledValue();
|
||||
}
|
||||
|
||||
public static GpoRuleConfigured GetConfiguredColorPickerEnabledValue()
|
||||
{
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredColorPickerEnabledValue();
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<Version>$(Version).0</Version>
|
||||
<Authors>Microsoft Corporation</Authors>
|
||||
<Product>PowerToys</Product>
|
||||
|
@ -9,6 +9,7 @@ namespace ManagedCommon
|
||||
AlwaysOnTop,
|
||||
Awake,
|
||||
ColorPicker,
|
||||
CmdNotFound,
|
||||
CropAndLock,
|
||||
EnvironmentVariables,
|
||||
FancyZones,
|
||||
|
@ -67,6 +67,8 @@ struct LogSettings
|
||||
inline const static std::string cropAndLockLoggerName = "crop-and-lock";
|
||||
inline const static std::wstring registryPreviewLogPath = L"Logs\\registryPreview-log.txt";
|
||||
inline const static std::string environmentVariablesLoggerName = "environment-variables";
|
||||
inline const static std::wstring cmdNotFoundLogPath = L"Logs\\cmd-not-found-log.txt";
|
||||
inline const static std::string cmdNotFoundLoggerName = "cmd-not-found";
|
||||
inline const static int retention = 30;
|
||||
std::wstring logLevel;
|
||||
LogSettings();
|
||||
|
@ -24,6 +24,7 @@ namespace powertoys_gpo {
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_GLOBAL_ALL_UTILITIES = L"ConfigureGlobalUtilityEnabledState";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_ALWAYS_ON_TOP = L"ConfigureEnabledUtilityAlwaysOnTop";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_AWAKE = L"ConfigureEnabledUtilityAwake";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_CMD_NOT_FOUND = L"ConfigureEnabledUtilityCmdNotFound";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_COLOR_PICKER = L"ConfigureEnabledUtilityColorPicker";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_CROP_AND_LOCK = L"ConfigureEnabledUtilityCropAndLock";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_FANCYZONES = L"ConfigureEnabledUtilityFancyZones";
|
||||
@ -224,6 +225,11 @@ namespace powertoys_gpo {
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_AWAKE);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredCmdNotFoundEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_CMD_NOT_FOUND);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredColorPickerEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_COLOR_PICKER);
|
||||
|
@ -15,6 +15,7 @@
|
||||
<definition name="SUPPORTED_POWERTOYS_0_73_0" displayName="$(string.SUPPORTED_POWERTOYS_0_73_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_75_0" displayName="$(string.SUPPORTED_POWERTOYS_0_75_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_76_0" displayName="$(string.SUPPORTED_POWERTOYS_0_76_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_77_0" displayName="$(string.SUPPORTED_POWERTOYS_0_77_0)"/>
|
||||
</definitions>
|
||||
</supportedOn>
|
||||
<categories>
|
||||
@ -59,6 +60,16 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityCmdNotFound" class="Both" displayName="$(string.ConfigureEnabledUtilityCmdNotFound)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityCmdNotFound">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_77_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityColorPicker" class="Both" displayName="$(string.ConfigureEnabledUtilityColorPicker)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityColorPicker">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_64_0" />
|
||||
|
@ -17,6 +17,7 @@
|
||||
<string id="SUPPORTED_POWERTOYS_0_73_0">PowerToys version 0.73.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_75_0">PowerToys version 0.75.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_76_0">PowerToys version 0.76.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_77_0">PowerToys version 0.77.0 or later</string>
|
||||
|
||||
<string id="ConfigureGlobalUtilityEnabledStateDescription">This policy configures the enabled state for all PowerToys utilities.
|
||||
|
||||
@ -112,6 +113,7 @@ Note: Changes require a restart of PowerToys Run.
|
||||
<string id="ConfigureEnabledUtilityAlwaysOnTop">Always On Top: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityAwake">Awake: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityColorPicker">Color Picker: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityCmdNotFound">Command Not Found: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityCropAndLock">Crop And Lock: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityEnvironmentVariables">Environment Variables: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFancyZones">FancyZones: Configure enabled state</string>
|
||||
|
67
src/modules/cmdNotFound/CmdNotFound/CmdNotFound.csproj
Normal file
67
src/modules/cmdNotFound/CmdNotFound/CmdNotFound.csproj
Normal file
@ -0,0 +1,67 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Authors>Microsoft Corporation</Authors>
|
||||
<Product>PowerToys</Product>
|
||||
<Nullable>enable</Nullable>
|
||||
<Description>PowerToys CommandNotFound</Description>
|
||||
<AssemblyName>PowerToys.CmdNotFound</AssemblyName>
|
||||
<GenerateDependencyFile>false</GenerateDependencyFile>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<SelfContained>true</SelfContained>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<DefineConstants>TRACE;RELEASE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool">
|
||||
<ExcludeAssets>contentFiles</ExcludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Management.Automation">
|
||||
<ExcludeAssets>contentFiles</ExcludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<Content Include="WinGetCommandNotFound.psd1">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
57
src/modules/cmdNotFound/CmdNotFound/Init.cs
Normal file
57
src/modules/cmdNotFound/CmdNotFound/Init.cs
Normal file
@ -0,0 +1,57 @@
|
||||
// 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.Management.Automation;
|
||||
using System.Management.Automation.Subsystem;
|
||||
using System.Management.Automation.Subsystem.Feedback;
|
||||
using System.Management.Automation.Subsystem.Prediction;
|
||||
|
||||
namespace WinGetCommandNotFound
|
||||
{
|
||||
public sealed class Init : IModuleAssemblyInitializer, IModuleAssemblyCleanup
|
||||
{
|
||||
internal const string Id = "e5351aa4-dfde-4d4d-bf0f-1a2f5a37d8d6";
|
||||
|
||||
public void OnImport()
|
||||
{
|
||||
if (!Platform.IsWindows || !IsWinGetInstalled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SubsystemManager.RegisterSubsystem(SubsystemKind.FeedbackProvider, WinGetCommandNotFoundFeedbackPredictor.Singleton);
|
||||
SubsystemManager.RegisterSubsystem(SubsystemKind.CommandPredictor, WinGetCommandNotFoundFeedbackPredictor.Singleton);
|
||||
}
|
||||
|
||||
public void OnRemove(PSModuleInfo psModuleInfo)
|
||||
{
|
||||
if (!IsWinGetInstalled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SubsystemManager.UnregisterSubsystem<IFeedbackProvider>(new Guid(Id));
|
||||
SubsystemManager.UnregisterSubsystem<ICommandPredictor>(new Guid(Id));
|
||||
}
|
||||
|
||||
private bool IsWinGetInstalled()
|
||||
{
|
||||
// Ensure WinGet is installed
|
||||
using (var pwsh = PowerShell.Create(RunspaceMode.CurrentRunspace))
|
||||
{
|
||||
var results = pwsh.AddCommand("Get-Command")
|
||||
.AddParameter("Name", "winget")
|
||||
.AddParameter("CommandType", "Application")
|
||||
.Invoke();
|
||||
|
||||
if (results.Count is 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
// 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.Management.Automation;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace WinGetCommandNotFound
|
||||
{
|
||||
public sealed class PooledPowerShellObjectPolicy : IPooledObjectPolicy<PowerShell>
|
||||
{
|
||||
private static readonly string[] WingetClientModuleName = new[] { "Microsoft.WinGet.Client" };
|
||||
|
||||
public PowerShell Create()
|
||||
{
|
||||
var iss = InitialSessionState.CreateDefault2();
|
||||
iss.ImportPSModule(WingetClientModuleName);
|
||||
return PowerShell.Create(iss);
|
||||
}
|
||||
|
||||
public bool Return(PowerShell obj)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
obj.Commands.Clear();
|
||||
obj.Streams.ClearStreams();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
// 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.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace WinGetCommandNotFound.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class CmdNotFoundFeedbackProvidedEvent : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
// 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.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace WinGetCommandNotFound.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class CmdNotFoundSuggestionProvidedEvent : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
@{
|
||||
ModuleVersion = '0.1.0'
|
||||
GUID = '28c9afa2-92e5-413e-8e53-44b2d7a83ac6'
|
||||
Author = 'Carlos Zamora'
|
||||
CompanyName = "Microsoft Corporation"
|
||||
Copyright = "Copyright (c) Microsoft Corporation."
|
||||
Description = 'Enable suggestions on how to install missing commands via winget'
|
||||
PowerShellVersion = '7.4'
|
||||
NestedModules = @('PowerToys.CmdNotFound.dll')
|
||||
RequiredModules = @(@{ModuleName = 'Microsoft.WinGet.Client'; ModuleVersion = "0.2.1"; })
|
||||
}
|
@ -0,0 +1,206 @@
|
||||
// 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;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Subsystem.Feedback;
|
||||
using System.Management.Automation.Subsystem.Prediction;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
|
||||
namespace WinGetCommandNotFound
|
||||
{
|
||||
public sealed class WinGetCommandNotFoundFeedbackPredictor : IFeedbackProvider, ICommandPredictor
|
||||
{
|
||||
private readonly Guid _guid;
|
||||
|
||||
private readonly ObjectPool<PowerShell> _pool;
|
||||
|
||||
private const int _maxSuggestions = 20;
|
||||
|
||||
private List<string>? _candidates;
|
||||
|
||||
private bool _warmedUp;
|
||||
|
||||
public static WinGetCommandNotFoundFeedbackPredictor Singleton { get; } = new WinGetCommandNotFoundFeedbackPredictor(Init.Id);
|
||||
|
||||
private WinGetCommandNotFoundFeedbackPredictor(string guid)
|
||||
{
|
||||
_guid = new Guid(guid);
|
||||
|
||||
var provider = new DefaultObjectPoolProvider();
|
||||
_pool = provider.Create(new PooledPowerShellObjectPolicy());
|
||||
_pool.Return(_pool.Get());
|
||||
Task.Run(() => WarmUp());
|
||||
}
|
||||
|
||||
public Guid Id => _guid;
|
||||
|
||||
public string Name => "Windows Package Manager - WinGet";
|
||||
|
||||
public string Description => "Finds missing commands that can be installed via WinGet.";
|
||||
|
||||
public Dictionary<string, string>? FunctionsToDefine => null;
|
||||
|
||||
private void WarmUp()
|
||||
{
|
||||
var ps = _pool.Get();
|
||||
try
|
||||
{
|
||||
ps.AddCommand("Find-WinGetPackage")
|
||||
.AddParameter("Count", 1)
|
||||
.Invoke();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_pool.Return(ps);
|
||||
_warmedUp = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets feedback based on the given commandline and error record.
|
||||
/// </summary>
|
||||
public FeedbackItem? GetFeedback(FeedbackContext context, CancellationToken token)
|
||||
{
|
||||
var target = (string)context.LastError!.TargetObject;
|
||||
if (target is not null)
|
||||
{
|
||||
bool tooManySuggestions = false;
|
||||
string packageMatchFilterField = "command";
|
||||
var pkgList = FindPackages(target, ref tooManySuggestions, ref packageMatchFilterField);
|
||||
if (pkgList.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Build list of suggestions
|
||||
_candidates = new List<string>();
|
||||
foreach (var pkg in pkgList)
|
||||
{
|
||||
_candidates.Add(string.Format(CultureInfo.InvariantCulture, "winget install --id {0}", pkg.Members["Id"].Value.ToString()));
|
||||
}
|
||||
|
||||
// Build footer message
|
||||
var footerMessage = tooManySuggestions ?
|
||||
string.Format(CultureInfo.InvariantCulture, "Additional results can be found using \"winget search --{0} {1}\"", packageMatchFilterField, target) :
|
||||
null;
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.CmdNotFoundFeedbackProvidedEvent());
|
||||
|
||||
return new FeedbackItem(
|
||||
"Try installing this package using winget:",
|
||||
_candidates,
|
||||
footerMessage,
|
||||
FeedbackDisplayLayout.Portrait);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Collection<PSObject> FindPackages(string query, ref bool tooManySuggestions, ref string packageMatchFilterField)
|
||||
{
|
||||
if (!_warmedUp)
|
||||
{
|
||||
return new Collection<PSObject>();
|
||||
}
|
||||
|
||||
var ps = _pool.Get();
|
||||
try
|
||||
{
|
||||
var common = new Hashtable()
|
||||
{
|
||||
["Source"] = "winget",
|
||||
};
|
||||
|
||||
// 1) Search by command
|
||||
var pkgList = ps.AddCommand("Find-WinGetPackage")
|
||||
.AddParameter("Command", query)
|
||||
.AddParameter("MatchOption", "StartsWithCaseInsensitive")
|
||||
.AddParameters(common)
|
||||
.Invoke();
|
||||
if (pkgList.Count > 0)
|
||||
{
|
||||
tooManySuggestions = pkgList.Count > _maxSuggestions;
|
||||
packageMatchFilterField = "command";
|
||||
return pkgList;
|
||||
}
|
||||
|
||||
// 2) No matches found,
|
||||
// search by name
|
||||
ps.Commands.Clear();
|
||||
pkgList = ps.AddCommand("Find-WinGetPackage")
|
||||
.AddParameter("Name", query)
|
||||
.AddParameter("MatchOption", "ContainsCaseInsensitive")
|
||||
.AddParameters(common)
|
||||
.Invoke();
|
||||
if (pkgList.Count > 0)
|
||||
{
|
||||
tooManySuggestions = pkgList.Count > _maxSuggestions;
|
||||
packageMatchFilterField = "name";
|
||||
return pkgList;
|
||||
}
|
||||
|
||||
// 3) No matches found,
|
||||
// search by moniker
|
||||
ps.Commands.Clear();
|
||||
pkgList = ps.AddCommand("Find-WinGetPackage")
|
||||
.AddParameter("Moniker", query)
|
||||
.AddParameter("MatchOption", "ContainsCaseInsensitive")
|
||||
.AddParameters(common)
|
||||
.Invoke();
|
||||
tooManySuggestions = pkgList.Count > _maxSuggestions;
|
||||
packageMatchFilterField = "moniker";
|
||||
return pkgList;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_pool.Return(ps);
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanAcceptFeedback(PredictionClient client, PredictorFeedbackKind feedback)
|
||||
{
|
||||
return feedback switch
|
||||
{
|
||||
PredictorFeedbackKind.CommandLineAccepted => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
public SuggestionPackage GetSuggestion(PredictionClient client, PredictionContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_candidates is not null)
|
||||
{
|
||||
string input = context.InputAst.Extent.Text;
|
||||
List<PredictiveSuggestion>? result = null;
|
||||
|
||||
foreach (string c in _candidates)
|
||||
{
|
||||
if (c.StartsWith(input, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result ??= new List<PredictiveSuggestion>(_candidates.Count);
|
||||
result.Add(new PredictiveSuggestion(c));
|
||||
}
|
||||
}
|
||||
|
||||
if (result is not null)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.CmdNotFoundSuggestionProvidedEvent());
|
||||
return new SuggestionPackage(result);
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public void OnCommandLineAccepted(PredictionClient client, IReadOnlyList<string> history)
|
||||
{
|
||||
// Reset the candidate state.
|
||||
_candidates = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../../../common/version/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
PRODUCTVERSION PRODUCT_VERSION
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
|
||||
BEGIN
|
||||
VALUE "CompanyName", COMPANY_NAME
|
||||
VALUE "FileDescription", FILE_DESCRIPTION
|
||||
VALUE "FileVersion", FILE_VERSION_STRING
|
||||
VALUE "InternalName", INTERNAL_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||
VALUE "ProductName", PRODUCT_NAME
|
||||
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CMD_NOT_FOUND_NAME "Command Not Found"
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{0014d652-901f-4456-8d65-06fc5f997fb0}</ProjectGuid>
|
||||
<RootNamespace>CmdNotFoundModuleInterface</RootNamespace>
|
||||
<TargetName>PowerToys.CmdNotFoundModuleInterface</TargetName>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<ProjectName>CmdNotFoundModuleInterface</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;CMDNOTFOUNDMODULEINTERFACE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>Shlwapi.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;CMDNOTFOUNDMODULEINTERFACE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>Shlwapi.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="CmdNotFoundModuleInterface.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="CmdNotFoundModuleInterface.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
161
src/modules/cmdNotFound/CmdNotFoundModuleInterface/dllmain.cpp
Normal file
161
src/modules/cmdNotFound/CmdNotFoundModuleInterface/dllmain.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "pch.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/logger/logger_settings.h>
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
#include <common/utils/gpo.h>
|
||||
#include <common/utils/logger_helper.h>
|
||||
#include <common/utils/process_path.h>
|
||||
#include <common/utils/resources.h>
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
|
||||
#include "resource.h"
|
||||
#include "trace.h"
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
Trace::RegisterProvider();
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
Trace::UnregisterProvider();
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const static wchar_t* MODULE_NAME = L"Command Not Found";
|
||||
const static wchar_t* MODULE_DESC = L"A module that detects an error thrown by a command in PowerShell and suggests a relevant WinGet package to install, if available.";
|
||||
|
||||
inline const std::wstring ModuleKey = L"CmdNotFound";
|
||||
|
||||
class CmdNotFound : public PowertoyModuleIface
|
||||
{
|
||||
std::wstring app_name;
|
||||
std::wstring app_key;
|
||||
|
||||
private:
|
||||
bool m_enabled = false;
|
||||
|
||||
void install_module()
|
||||
{
|
||||
auto module_path = get_module_folderpath();
|
||||
|
||||
std::string command = "pwsh.exe";
|
||||
command += " ";
|
||||
command += "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + winrt::to_string(module_path) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\EnableModule.ps1" + "\"" + " -scriptPath \"" + winrt::to_string(module_path) + "\"";
|
||||
|
||||
int ret = system(command.c_str());
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
Logger::error("Running EnableModule.ps1 script failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info("Module installed successfully.");
|
||||
Trace::EnableCmdNotFoundGpo(true);
|
||||
}
|
||||
}
|
||||
|
||||
void uninstall_module()
|
||||
{
|
||||
auto module_path = get_module_folderpath();
|
||||
|
||||
std::string command = "pwsh.exe";
|
||||
command += " ";
|
||||
command += "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + winrt::to_string(module_path) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\DisableModule.ps1" + "\"";
|
||||
|
||||
int ret = system(command.c_str());
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
Logger::error("Running EnableModule.ps1 script failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info("Module uninstalled successfully.");
|
||||
Trace::EnableCmdNotFoundGpo(false);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
CmdNotFound()
|
||||
{
|
||||
app_name = GET_RESOURCE_STRING(IDS_CMD_NOT_FOUND_NAME);
|
||||
app_key = ModuleKey;
|
||||
|
||||
std::filesystem::path logFilePath(PTSettingsHelper::get_module_save_folder_location(this->app_key));
|
||||
logFilePath.append(LogSettings::cmdNotFoundLogPath);
|
||||
Logger::init(LogSettings::cmdNotFoundLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location());
|
||||
Logger::info("CmdNotFound object is constructing");
|
||||
|
||||
powertoys_gpo::gpo_rule_configured_t gpo_rule_configured_value = gpo_policy_enabled_configuration();
|
||||
if (gpo_rule_configured_value == powertoys_gpo::gpo_rule_configured_t::gpo_rule_configured_enabled)
|
||||
{
|
||||
install_module();
|
||||
m_enabled = true;
|
||||
}
|
||||
else if (gpo_rule_configured_value == powertoys_gpo::gpo_rule_configured_t::gpo_rule_configured_disabled)
|
||||
{
|
||||
uninstall_module();
|
||||
m_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override
|
||||
{
|
||||
return powertoys_gpo::getConfiguredCmdNotFoundEnabledValue();
|
||||
}
|
||||
|
||||
virtual void destroy() override
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual const wchar_t* get_name() override
|
||||
{
|
||||
return MODULE_NAME;
|
||||
}
|
||||
|
||||
virtual const wchar_t* get_key() override
|
||||
{
|
||||
return app_key.c_str();
|
||||
}
|
||||
|
||||
virtual bool get_config(wchar_t* /*buffer*/, int* /*buffer_size*/) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void set_config(const wchar_t* config) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void enable()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void disable()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool is_enabled() override
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
{
|
||||
return new CmdNotFound();
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
// pch.cpp: source file corresponding to the pre-compiled header
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
|
16
src/modules/cmdNotFound/CmdNotFoundModuleInterface/pch.h
Normal file
16
src/modules/cmdNotFound/CmdNotFoundModuleInterface/pch.h
Normal file
@ -0,0 +1,16 @@
|
||||
// pch.h: This is a precompiled header file.
|
||||
// Files listed below are compiled only once, improving build performance for future builds.
|
||||
// This also affects IntelliSense performance, including code completion and many code browsing features.
|
||||
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
|
||||
// Do not add files here that you will be updating frequently as this negates the performance advantage.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files
|
||||
#include <windows.h>
|
||||
|
||||
#include <ProjectTelemetry.h>
|
||||
|
||||
#endif //PCH_H
|
@ -0,0 +1,21 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Awake.rc
|
||||
//
|
||||
#define IDS_CMD_NOT_FOUND_NAME 101
|
||||
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys Command Not Found"
|
||||
#define INTERNAL_NAME "PowerToys.CmdNotFoundModuleInterface"
|
||||
#define ORIGINAL_FILENAME "PowerToys.CmdNotFoundModuleInterface.dll"
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
30
src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.cpp
Normal file
30
src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "pch.h"
|
||||
#include "trace.h"
|
||||
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
g_hProvider,
|
||||
"Microsoft.PowerToys",
|
||||
// {38e8889b-9731-53f5-e901-e8a7c1753074}
|
||||
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
|
||||
TraceLoggingOptionProjectTelemetry());
|
||||
|
||||
void Trace::RegisterProvider()
|
||||
{
|
||||
TraceLoggingRegister(g_hProvider);
|
||||
}
|
||||
|
||||
void Trace::UnregisterProvider()
|
||||
{
|
||||
TraceLoggingUnregister(g_hProvider);
|
||||
}
|
||||
|
||||
// Log if the user has CmdNotFound enabled or disabled
|
||||
void Trace::EnableCmdNotFoundGpo(const bool enabled) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"CmdNotFound_EnableCmdNotFound",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingBoolean(enabled, "Enabled"));
|
||||
}
|
11
src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.h
Normal file
11
src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class Trace
|
||||
{
|
||||
public:
|
||||
static void RegisterProvider();
|
||||
static void UnregisterProvider();
|
||||
|
||||
// Log if the user has CmdNotFound enabled or disabled
|
||||
static void EnableCmdNotFoundGpo(const bool enabled) noexcept;
|
||||
};
|
@ -158,6 +158,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||
L"WinUI3Apps/PowerToys.EnvironmentVariablesModuleInterface.dll",
|
||||
L"PowerToys.MouseWithoutBordersModuleInterface.dll",
|
||||
L"PowerToys.CropAndLockModuleInterface.dll",
|
||||
L"PowerToys.CmdNotFoundModuleInterface.dll",
|
||||
};
|
||||
const auto VCM_PATH = L"PowerToys.VideoConferenceModule.dll";
|
||||
if (const auto mf = LoadLibraryA("mf.dll"))
|
||||
|
42
src/settings-ui/Settings.UI.Library/CmdNotFoundSettings.cs
Normal file
42
src/settings-ui/Settings.UI.Library/CmdNotFoundSettings.cs
Normal file
@ -0,0 +1,42 @@
|
||||
// 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.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
public class CmdNotFoundSettings : BasePTModuleSettings, ISettingsConfig
|
||||
{
|
||||
private static readonly JsonSerializerOptions SerializerOptions = new()
|
||||
{
|
||||
WriteIndented = true,
|
||||
};
|
||||
|
||||
public const string ModuleName = "CmdNotFound";
|
||||
|
||||
public CmdNotFoundSettings()
|
||||
{
|
||||
Version = "1";
|
||||
Name = ModuleName;
|
||||
}
|
||||
|
||||
public virtual void Save(ISettingsUtils settingsUtils)
|
||||
{
|
||||
// Save settings to file
|
||||
ArgumentNullException.ThrowIfNull(settingsUtils);
|
||||
|
||||
settingsUtils.SaveSettings(JsonSerializer.Serialize(this, SerializerOptions), ModuleName);
|
||||
}
|
||||
|
||||
public string GetModuleName()
|
||||
=> Name;
|
||||
|
||||
// This can be utilized in the future if the settings.json file is to be modified/deleted.
|
||||
public bool UpgradeSettingsConfiguration()
|
||||
=> false;
|
||||
}
|
||||
}
|
@ -427,6 +427,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
}
|
||||
}
|
||||
|
||||
private bool cmdNotFound = true;
|
||||
|
||||
[JsonPropertyName("CmdNotFound")]
|
||||
public bool CmdNotFound
|
||||
{
|
||||
get => cmdNotFound;
|
||||
set
|
||||
{
|
||||
if (cmdNotFound != value)
|
||||
{
|
||||
LogTelemetryEvent(value);
|
||||
cmdNotFound = value;
|
||||
NotifyChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool environmentVariables = true;
|
||||
|
||||
[JsonPropertyName("EnvironmentVariables")]
|
||||
|
@ -0,0 +1,16 @@
|
||||
// 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.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events
|
||||
{
|
||||
[EventData]
|
||||
public class CmdNotFoundInstallEvent : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
// 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.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events
|
||||
{
|
||||
[EventData]
|
||||
public class CmdNotFoundUninstallEvent : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
@ -0,0 +1,35 @@
|
||||
$profileContent = Get-Content $PROFILE
|
||||
|
||||
$newContent = ""
|
||||
$linesToDeleteFound = $False
|
||||
$atLeastOneInstanceFound = $False
|
||||
|
||||
$profileContent | ForEach-Object {
|
||||
if ($_.Contains("34de4b3d-13a8-4540-b76d-b9e8d3851756") -and !$linesToDeleteFound)
|
||||
{
|
||||
$linesToDeleteFound = $True
|
||||
$atLeastOneInstanceFound = $True
|
||||
return
|
||||
}
|
||||
|
||||
if ($_.Contains("34de4b3d-13a8-4540-b76d-b9e8d3851756") -and $linesToDeleteFound)
|
||||
{
|
||||
$linesToDeleteFound = $False
|
||||
return
|
||||
}
|
||||
|
||||
if($linesToDeleteFound)
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
$newContent += $_ + "`r`n"
|
||||
}
|
||||
|
||||
if($atLeastOneInstanceFound)
|
||||
{
|
||||
Set-Content -Path $PROFILE -Value $newContent
|
||||
Write-Host "Removed the Command Not Found reference from the profile file."
|
||||
} else {
|
||||
Write-Host "No instance of Command Not Found was found in the profile file."
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$True,Position=1)]
|
||||
[string]$scriptPath
|
||||
)
|
||||
|
||||
Write-Host "Enabling experimental feature: PSFeedbackProvider"
|
||||
Enable-ExperimentalFeature PSFeedbackProvider
|
||||
Write-Host "Enabling experimental feature: PSCommandNotFoundSuggestion"
|
||||
Enable-ExperimentalFeature PSCommandNotFoundSuggestion
|
||||
|
||||
if (Get-Module -ListAvailable -Name Microsoft.WinGet.Client) {
|
||||
Write-Host "WinGet Client module detected"
|
||||
}
|
||||
else {
|
||||
Write-Host "WinGet module was not found. Installation instructions can be found on https://www.powershellgallery.com/packages/Microsoft.WinGet.Client `r`n"
|
||||
}
|
||||
|
||||
if (!(Test-Path $PROFILE))
|
||||
{
|
||||
Write-Host "Profile file $PROFILE not found".
|
||||
New-Item -Path $PROFILE -ItemType File
|
||||
Write-Host "Created profile file $PROFILE".
|
||||
}
|
||||
|
||||
$profileContent = Get-Content -Path $PROFILE -Raw
|
||||
|
||||
if ((-not [string]::IsNullOrEmpty($profileContent)) -and ($profileContent.Contains("34de4b3d-13a8-4540-b76d-b9e8d3851756")))
|
||||
{
|
||||
Write-Host "Module is already registered in the profile file."
|
||||
}
|
||||
else
|
||||
{
|
||||
Add-Content -Path $PROFILE -Value "`r`n#34de4b3d-13a8-4540-b76d-b9e8d3851756 PowerToys CommandNotFound module"
|
||||
Add-Content -Path $PROFILE -Value "`r`nImport-Module `"$scriptPath\WinGetCommandNotFound.psd1`""
|
||||
Add-Content -Path $PROFILE -Value "#34de4b3d-13a8-4540-b76d-b9e8d3851756"
|
||||
Write-Host "Module was successfully registered in the profile file."
|
||||
}
|
@ -44,6 +44,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
case ModuleType.AlwaysOnTop: return generalSettingsConfig.Enabled.AlwaysOnTop;
|
||||
case ModuleType.Awake: return generalSettingsConfig.Enabled.Awake;
|
||||
case ModuleType.ColorPicker: return generalSettingsConfig.Enabled.ColorPicker;
|
||||
case ModuleType.CmdNotFound: return generalSettingsConfig.Enabled.CmdNotFound;
|
||||
case ModuleType.CropAndLock: return generalSettingsConfig.Enabled.CropAndLock;
|
||||
case ModuleType.EnvironmentVariables: return generalSettingsConfig.Enabled.EnvironmentVariables;
|
||||
case ModuleType.FancyZones: return generalSettingsConfig.Enabled.FancyZones;
|
||||
@ -76,6 +77,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
case ModuleType.AlwaysOnTop: generalSettingsConfig.Enabled.AlwaysOnTop = isEnabled; break;
|
||||
case ModuleType.Awake: generalSettingsConfig.Enabled.Awake = isEnabled; break;
|
||||
case ModuleType.ColorPicker: generalSettingsConfig.Enabled.ColorPicker = isEnabled; break;
|
||||
case ModuleType.CmdNotFound: generalSettingsConfig.Enabled.CmdNotFound = isEnabled; break;
|
||||
case ModuleType.CropAndLock: generalSettingsConfig.Enabled.CropAndLock = isEnabled; break;
|
||||
case ModuleType.EnvironmentVariables: generalSettingsConfig.Enabled.EnvironmentVariables = isEnabled; break;
|
||||
case ModuleType.FancyZones: generalSettingsConfig.Enabled.FancyZones = isEnabled; break;
|
||||
@ -107,6 +109,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
case ModuleType.AlwaysOnTop: return GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue();
|
||||
case ModuleType.Awake: return GPOWrapper.GetConfiguredAwakeEnabledValue();
|
||||
case ModuleType.ColorPicker: return GPOWrapper.GetConfiguredColorPickerEnabledValue();
|
||||
case ModuleType.CmdNotFound: return GPOWrapper.GetConfiguredCmdNotFoundEnabledValue();
|
||||
case ModuleType.CropAndLock: return GPOWrapper.GetConfiguredCropAndLockEnabledValue();
|
||||
case ModuleType.EnvironmentVariables: return GPOWrapper.GetConfiguredEnvironmentVariablesEnabledValue();
|
||||
case ModuleType.FancyZones: return GPOWrapper.GetConfiguredFancyZonesEnabledValue();
|
||||
@ -139,6 +142,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
ModuleType.AlwaysOnTop => Color.FromArgb(255, 74, 196, 242), // #4ac4f2
|
||||
ModuleType.Awake => Color.FromArgb(255, 40, 177, 233), // #28b1e9
|
||||
ModuleType.ColorPicker => Color.FromArgb(255, 7, 129, 211), // #0781d3
|
||||
ModuleType.CmdNotFound => Color.FromArgb(255, 31, 164, 227), // #1fa4e3
|
||||
ModuleType.CropAndLock => Color.FromArgb(255, 32, 166, 228), // #20a6e4
|
||||
ModuleType.EnvironmentVariables => Color.FromArgb(255, 16, 132, 208), // #1084d0
|
||||
ModuleType.FancyZones => Color.FromArgb(255, 65, 209, 247), // #41d1f7
|
||||
@ -171,6 +175,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
ModuleType.AlwaysOnTop => typeof(AlwaysOnTopPage),
|
||||
ModuleType.Awake => typeof(AwakePage),
|
||||
ModuleType.ColorPicker => typeof(ColorPickerPage),
|
||||
ModuleType.CmdNotFound => typeof(CmdNotFoundPage),
|
||||
ModuleType.CropAndLock => typeof(CropAndLockPage),
|
||||
ModuleType.EnvironmentVariables => typeof(EnvironmentVariablesPage),
|
||||
ModuleType.FancyZones => typeof(FancyZonesPage),
|
||||
|
@ -9,6 +9,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Enums
|
||||
Overview = 0,
|
||||
AlwaysOnTop,
|
||||
Awake,
|
||||
CmdNotFound,
|
||||
ColorPicker,
|
||||
CropAndLock,
|
||||
EnvironmentVariables,
|
||||
|
@ -53,7 +53,7 @@
|
||||
<WarningsNotAsErrors>CA1720</WarningsNotAsErrors>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
<PropertyGroup>
|
||||
<CsWinRTIncludes>PowerToys.GPOWrapper</CsWinRTIncludes>
|
||||
@ -61,10 +61,10 @@
|
||||
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Needed for CommunityToolkit.Labs.WinUI.SettingsControls. -->
|
||||
<PropertyGroup>
|
||||
<RestoreAdditionalProjectSources>https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-Labs/nuget/v3/index.json</RestoreAdditionalProjectSources>
|
||||
</PropertyGroup>
|
||||
<!-- Needed for CommunityToolkit.Labs.WinUI.SettingsControls. -->
|
||||
<PropertyGroup>
|
||||
<RestoreAdditionalProjectSources>https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-Labs/nuget/v3/index.json</RestoreAdditionalProjectSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\Settings\SplashScreen.scale-200.png" />
|
||||
@ -96,11 +96,11 @@
|
||||
<!-- Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
|
||||
Tools extension to be activated for this project even if the Windows App SDK Nuget
|
||||
package has not yet been restored -->
|
||||
|
||||
|
||||
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnablePreviewMsixTooling)'=='true'">
|
||||
<ProjectCapability Include="Msix" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<!-- 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" />
|
||||
@ -111,7 +111,7 @@
|
||||
<ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
||||
<ProjectReference Include="..\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- TODO: fix issues and reenable -->
|
||||
<!-- These are caused by streamjsonrpc dependency on Microsoft.VisualStudio.Threading.Analyzers -->
|
||||
@ -119,10 +119,19 @@
|
||||
<NoWarn>VSTHRD002;VSTHRD110;VSTHRD100;VSTHRD200;VSTHRD101</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Assets\Settings\icon.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Assets\Settings\icon.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Assets\Settings\Scripts\EnableModule.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Assets\Settings\Scripts\DisableModule.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -395,6 +395,7 @@ namespace Microsoft.PowerToys.Settings.UI
|
||||
case "Overview": return typeof(GeneralPage);
|
||||
case "AlwaysOnTop": return typeof(AlwaysOnTopPage);
|
||||
case "Awake": return typeof(AwakePage);
|
||||
case "CmdNotFound": return typeof(CmdNotFoundPage);
|
||||
case "ColorPicker": return typeof(ColorPickerPage);
|
||||
case "FancyZones": return typeof(FancyZonesPage);
|
||||
case "FileLocksmith": return typeof(FileLocksmithPage);
|
||||
|
@ -0,0 +1,32 @@
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeCmdNotFound"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<controls:OOBEPageControl x:Uid="Oobe_CmdNotFound" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/CmdNotFound.png">
|
||||
|
||||
<controls:OOBEPageControl.PageContent>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
|
||||
|
||||
<controls:ShortcutWithTextLabelControl x:Name="HotkeyControl" x:Uid="Oobe_CmdNotFound_HowToUse" />
|
||||
|
||||
<StackPanel
|
||||
Margin="0,24,0,0"
|
||||
Orientation="Horizontal"
|
||||
Spacing="12">
|
||||
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />
|
||||
<HyperlinkButton NavigateUri="https://aka.ms/PowerToysOverview_CmdNotFound" Style="{StaticResource TextButtonStyle}">
|
||||
<TextBlock x:Uid="LearnMore_CmdNotFound" TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</controls:OOBEPageControl.PageContent>
|
||||
</controls:OOBEPageControl>
|
||||
</Page>
|
@ -0,0 +1,45 @@
|
||||
// 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.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
|
||||
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
|
||||
using Microsoft.PowerToys.Settings.UI.Views;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
{
|
||||
public sealed partial class OobeCmdNotFound : Page
|
||||
{
|
||||
public OobePowerToysModule ViewModel { get; set; }
|
||||
|
||||
public OobeCmdNotFound()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.CmdNotFound]);
|
||||
DataContext = ViewModel;
|
||||
}
|
||||
|
||||
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
if (OobeShellPage.OpenMainWindowCallback != null)
|
||||
{
|
||||
OobeShellPage.OpenMainWindowCallback(typeof(CmdNotFoundPage));
|
||||
}
|
||||
|
||||
ViewModel.LogOpeningSettingsEvent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
ViewModel.LogOpeningModuleEvent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||
{
|
||||
ViewModel.LogClosingModuleEvent();
|
||||
}
|
||||
}
|
||||
}
|
@ -69,6 +69,10 @@
|
||||
x:Uid="Shell_Awake"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsAwake.png}"
|
||||
Tag="Awake" />
|
||||
<NavigationViewItem
|
||||
x:Uid="Shell_CmdNotFound"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsCmdNotFound.png}"
|
||||
Tag="CmdNotFound" />
|
||||
<NavigationViewItem
|
||||
x:Uid="Shell_ColorPicker"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsColorPicker.png}"
|
||||
|
@ -79,6 +79,11 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
ModuleName = "Awake",
|
||||
IsNew = false,
|
||||
});
|
||||
Modules.Insert((int)PowerToysModules.CmdNotFound, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "CmdNotFound",
|
||||
IsNew = true,
|
||||
});
|
||||
Modules.Insert((int)PowerToysModules.ColorPicker, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "ColorPicker",
|
||||
@ -250,6 +255,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
case "WhatsNew": NavigationFrame.Navigate(typeof(OobeWhatsNew)); break;
|
||||
case "AlwaysOnTop": NavigationFrame.Navigate(typeof(OobeAlwaysOnTop)); break;
|
||||
case "Awake": NavigationFrame.Navigate(typeof(OobeAwake)); break;
|
||||
case "CmdNotFound": NavigationFrame.Navigate(typeof(OobeCmdNotFound)); break;
|
||||
case "ColorPicker": NavigationFrame.Navigate(typeof(OobeColorPicker)); break;
|
||||
case "CropAndLock": NavigationFrame.Navigate(typeof(OobeCropAndLock)); break;
|
||||
case "EnvironmentVariables": NavigationFrame.Navigate(typeof(OobeEnvironmentVariables)); break;
|
||||
|
@ -0,0 +1,60 @@
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.Views.CmdNotFoundPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:custom="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
AutomationProperties.LandmarkType="Main"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<custom:SettingsPageControl x:Uid="CmdNotFound" ModuleImageSource="ms-appx:///Assets/Settings/Modules/CmdNotFound.png">
|
||||
<custom:SettingsPageControl.ModuleContent>
|
||||
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}" Orientation="Vertical">
|
||||
<InfoBar
|
||||
x:Uid="GPO_IsSettingForced"
|
||||
IsClosable="False"
|
||||
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
|
||||
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
|
||||
Severity="Informational" />
|
||||
|
||||
<controls:SettingsCard
|
||||
x:Uid="CmdNotFound_Enable"
|
||||
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsCmdNotFound.png}"
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<Button
|
||||
x:Uid="CmdNotFound_InstallButton"
|
||||
Command="{x:Bind ViewModel.InstallModuleEventHandler}"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
<HyperlinkButton x:Uid="CmdNotFound_UninstallButton" Command="{x:Bind ViewModel.UninstallModuleEventHandler}" />
|
||||
</StackPanel>
|
||||
<controls:SettingsCard.Description>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock x:Uid="CmdNotFound_Enable_DescriptionText" />
|
||||
<HyperlinkButton x:Uid="CmdNotFound_CheckCompatibility" Command="{x:Bind ViewModel.CheckPowershellVersionEventHandler}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard.Description>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<TextBlock
|
||||
x:Uid="CmdNotFound_ModuleInstallationLogs"
|
||||
Margin="0,12,0,4"
|
||||
Style="{ThemeResource BodyStrongTextBlockStyle}" />
|
||||
<TextBox
|
||||
Height="300"
|
||||
FontFamily="Consolas"
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}"
|
||||
IsReadOnly="True"
|
||||
Text="{x:Bind Mode=OneWay, Path=ViewModel.CommandOutputLog}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</custom:SettingsPageControl.ModuleContent>
|
||||
|
||||
<custom:SettingsPageControl.PrimaryLinks>
|
||||
<custom:PageLink x:Uid="LearnMore_CmdNotFound" Link="https://aka.ms/PowerToysOverview_CmdNotFound" />
|
||||
</custom:SettingsPageControl.PrimaryLinks>
|
||||
</custom:SettingsPageControl>
|
||||
</Page>
|
@ -0,0 +1,21 @@
|
||||
// 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.PowerToys.Settings.UI.ViewModels;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
{
|
||||
public sealed partial class CmdNotFoundPage : Page
|
||||
{
|
||||
private CmdNotFoundViewModel ViewModel { get; set; }
|
||||
|
||||
public CmdNotFoundPage()
|
||||
{
|
||||
ViewModel = new CmdNotFoundViewModel();
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
@ -115,6 +115,11 @@
|
||||
helpers:NavHelper.NavigateTo="views:AwakePage"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsAwake.png}" />
|
||||
|
||||
<NavigationViewItem
|
||||
x:Uid="Shell_CmdNotFound"
|
||||
helpers:NavHelper.NavigateTo="views:CmdNotFoundPage"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsCmdNotFound.png}" />
|
||||
|
||||
<NavigationViewItem
|
||||
x:Uid="Shell_ColorPicker"
|
||||
helpers:NavHelper.NavigateTo="views:ColorPickerPage"
|
||||
|
@ -2358,6 +2358,10 @@ From there, simply click on one of the supported files in the File Explorer and
|
||||
<value>Learn more about Awake</value>
|
||||
<comment>Awake is a product name, do not loc</comment>
|
||||
</data>
|
||||
<data name="LearnMore_CmdNotFound.Text" xml:space="preserve">
|
||||
<value>Learn more about Command Not Found</value>
|
||||
<comment> Command Not Found is the name of the module. </comment>
|
||||
</data>
|
||||
<data name="SecondaryLink_Awake.Text" xml:space="preserve">
|
||||
<value>Den Delimarsky's work on creating Awake</value>
|
||||
<comment>Awake is a product name, do not loc</comment>
|
||||
@ -3655,6 +3659,51 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="Oobe_PastePlain_HowToUse.Text" xml:space="preserve">
|
||||
<value>to paste your clipboard data as plain text. Note: this will replace the formatted text in your clipboard with the plain text.</value>
|
||||
</data>
|
||||
<data name="Shell_CmdNotFound.Content" xml:space="preserve">
|
||||
<value>Command Not Found</value>
|
||||
<comment>Product name: Navigation view item name for Command Not Found</comment>
|
||||
</data>
|
||||
<data name="CmdNotFound.ModuleDescription" xml:space="preserve">
|
||||
<value>A PowerShell module that detects an error thrown by a command and suggests a relevant WinGet package to install, if available.</value>
|
||||
<comment>"Command Not Found" is a product name</comment>
|
||||
</data>
|
||||
<data name="CmdNotFound.ModuleTitle" xml:space="preserve">
|
||||
<value>Command Not Found</value>
|
||||
<comment>"Command Not Found" is a product name</comment>
|
||||
</data>
|
||||
<data name="CmdNotFound_Enable.Header" xml:space="preserve">
|
||||
<value>Command Not Found</value>
|
||||
<comment>"Command Not Found" is a product name</comment>
|
||||
</data>
|
||||
<data name="CmdNotFound_Enable_DescriptionText.Text" xml:space="preserve">
|
||||
<value>Add this module to the PowerShell 7 profile script so that it is enabled with every new session</value>
|
||||
</data>
|
||||
<data name="CmdNotFound_ModuleInstallationLogs.Text" xml:space="preserve">
|
||||
<value>Installation logs</value>
|
||||
</data>
|
||||
<data name="CmdNotFound_CheckPowerShellVersionButtonControl.Description" xml:space="preserve">
|
||||
<value>PowerShell 7 is required to use this module</value>
|
||||
</data>
|
||||
<data name="CmdNotFound_CheckCompatibility.Content" xml:space="preserve">
|
||||
<value>Check if your PowerShell configuration is compatible</value>
|
||||
</data>
|
||||
<data name="CmdNotFound_InstallButton.Content" xml:space="preserve">
|
||||
<value>Install</value>
|
||||
</data>
|
||||
<data name="CmdNotFound_UninstallButton.Content" xml:space="preserve">
|
||||
<value>Uninstall</value>
|
||||
</data>
|
||||
<data name="Oobe_CmdNotFound.Description" xml:space="preserve">
|
||||
<value>Command Not Found detects an error thrown by a command in PowerShell and suggests a relevant WinGet package to install, if available.</value>
|
||||
<comment>"Command Not Found" is a product name</comment>
|
||||
</data>
|
||||
<data name="Oobe_CmdNotFound.Title" xml:space="preserve">
|
||||
<value>Command Not Found</value>
|
||||
<comment>"Command Not Found" is a product name</comment>
|
||||
</data>
|
||||
<data name="Oobe_CmdNotFound_HowToUse.Text" xml:space="preserve">
|
||||
<value>If a command returns an error, the module will suggest a WinGet package that may provide the relevant executable.</value>
|
||||
</data>
|
||||
<data name="AllAppsTxt.Text" xml:space="preserve">
|
||||
<value>All apps</value>
|
||||
</data>
|
||||
|
123
src/settings-ui/Settings.UI/ViewModels/CmdNotFoundViewModel.cs
Normal file
123
src/settings-ui/Settings.UI/ViewModels/CmdNotFoundViewModel.cs
Normal file
@ -0,0 +1,123 @@
|
||||
// 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.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public class CmdNotFoundViewModel : Observable
|
||||
{
|
||||
public ButtonClickCommand CheckPowershellVersionEventHandler => new ButtonClickCommand(CheckPowershellVersion);
|
||||
|
||||
public ButtonClickCommand InstallModuleEventHandler => new ButtonClickCommand(InstallModule);
|
||||
|
||||
public ButtonClickCommand UninstallModuleEventHandler => new ButtonClickCommand(UninstallModule);
|
||||
|
||||
private GpoRuleConfigured _enabledGpoRuleConfiguration;
|
||||
private bool _enabledStateIsGPOConfigured;
|
||||
|
||||
public static string AssemblyDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
string codeBase = Assembly.GetExecutingAssembly().Location;
|
||||
UriBuilder uri = new UriBuilder(codeBase);
|
||||
string path = Uri.UnescapeDataString(uri.Path);
|
||||
return Path.GetDirectoryName(path);
|
||||
}
|
||||
}
|
||||
|
||||
public CmdNotFoundViewModel()
|
||||
{
|
||||
InitializeEnabledValue();
|
||||
}
|
||||
|
||||
private void InitializeEnabledValue()
|
||||
{
|
||||
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredCmdNotFoundEnabledValue();
|
||||
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
// Get the enabled state from GPO.
|
||||
_enabledStateIsGPOConfigured = true;
|
||||
}
|
||||
}
|
||||
|
||||
private string _commandOutputLog;
|
||||
|
||||
public string CommandOutputLog
|
||||
{
|
||||
get => _commandOutputLog;
|
||||
set
|
||||
{
|
||||
if (_commandOutputLog != value)
|
||||
{
|
||||
_commandOutputLog = value;
|
||||
OnPropertyChanged(nameof(CommandOutputLog));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabledGpoConfigured
|
||||
{
|
||||
get => _enabledStateIsGPOConfigured;
|
||||
}
|
||||
|
||||
public void RunPowerShellScript(string powershellArguments)
|
||||
{
|
||||
string outputLog = string.Empty;
|
||||
try
|
||||
{
|
||||
var startInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = "pwsh.exe",
|
||||
Arguments = powershellArguments,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
};
|
||||
startInfo.EnvironmentVariables["NO_COLOR"] = "1";
|
||||
var process = Process.Start(startInfo);
|
||||
while (!process.StandardOutput.EndOfStream)
|
||||
{
|
||||
outputLog += process.StandardOutput.ReadLine() + "\r\n"; // Weirdly, PowerShell 7 won't give us new lines.
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
outputLog = ex.ToString();
|
||||
}
|
||||
|
||||
CommandOutputLog = outputLog;
|
||||
}
|
||||
|
||||
public void CheckPowershellVersion()
|
||||
{
|
||||
var arguments = $"-NoProfile -NonInteractive -Command $PSVersionTable";
|
||||
RunPowerShellScript(arguments);
|
||||
}
|
||||
|
||||
public void InstallModule()
|
||||
{
|
||||
var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\EnableModule.ps1";
|
||||
var arguments = $"-NoProfile -ExecutionPolicy Unrestricted -File \"{ps1File}\" -scriptPath \"{AssemblyDirectory}\\..\"";
|
||||
RunPowerShellScript(arguments);
|
||||
PowerToysTelemetry.Log.WriteEvent(new CmdNotFoundInstallEvent());
|
||||
}
|
||||
|
||||
public void UninstallModule()
|
||||
{
|
||||
var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\DisableModule.ps1";
|
||||
var arguments = $"-NoProfile -ExecutionPolicy Unrestricted -File \"{ps1File}\"";
|
||||
RunPowerShellScript(arguments);
|
||||
PowerToysTelemetry.Log.WriteEvent(new CmdNotFoundUninstallEvent());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user