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}|[<})>])
|
||||
|
||||
|
@ -29,6 +29,9 @@
|
||||
"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>
|
||||
@ -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]" />
|
||||
@ -253,6 +262,14 @@
|
||||
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)
|
||||
{
|
||||
|
@ -23,3 +23,4 @@ EXPORTS
|
||||
UnRegisterContextMenuPackagesCA
|
||||
UninstallEmbeddedMSIXCA
|
||||
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();
|
||||
|
@ -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,
|
||||
|
@ -125,4 +125,13 @@
|
||||
</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