mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-27 14:59:16 +08:00
[CmdNotFound]Improve installation workflow (#30727)
* [CmdNotFound]Improve installation workflow * Fix typo * Fix XAML styling * Update src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml Co-authored-by: Davide Giacometti <davide.giacometti@outlook.it> * Update src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml Co-authored-by: Davide Giacometti <davide.giacometti@outlook.it> * Update src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml Co-authored-by: Davide Giacometti <davide.giacometti@outlook.it> * Update src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml Co-authored-by: Davide Giacometti <davide.giacometti@outlook.it> * Update src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml Co-authored-by: Davide Giacometti <davide.giacometti@outlook.it> * Update src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml Co-authored-by: Davide Giacometti <davide.giacometti@outlook.it> * Don't create window for checking requirements * Hide install/uninstall buttons for CmdNotFound module * Also install winget before Powershell 7 * Better detect processor architecture * Fix spellcheck * [CMDNotFound] UX improvements (#30740) * UI improvements * Updated label * Update CmdNotFoundPage.xaml * Update CmdNotFoundPage.xaml * Update CmdNotFoundPage.xaml * Better version detection * Add some logging * Add missing package install that's a prerequisite for winget * Remove unused AllExperiments include * Fix Logger library include * Update PATH Environment variable after installing PS * Fix OOBE UI spacing * Use Invoke-WebRequest to get the deps and then install them from local path * Spellcheck * TEMP -> TMP * User path is supposed to come after machine path --------- Co-authored-by: Davide Giacometti <davide.giacometti@outlook.it> Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Stefan Markovic <stefan@janeasystems.com>
This commit is contained in:
parent
5f2d8216ad
commit
a7907ff63a
2
.github/actions/spell-check/expect.txt
vendored
2
.github/actions/spell-check/expect.txt
vendored
@ -745,6 +745,7 @@ Kybd
|
||||
languagesjson
|
||||
lastcodeanalysissucceeded
|
||||
Lastdevice
|
||||
LASTEXITCODE
|
||||
LAYOUTRTL
|
||||
LCIDTo
|
||||
lcl
|
||||
@ -917,6 +918,7 @@ MSIFASTINSTALL
|
||||
MSIHANDLE
|
||||
msiquery
|
||||
MSIRESTARTMANAGERCONTROL
|
||||
msixbundle
|
||||
MSIXCA
|
||||
MSLLHOOKSTRUCT
|
||||
Mso
|
||||
|
@ -54,6 +54,9 @@
|
||||
</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" />
|
||||
<File Id="CommandNotFound_Scripts_CheckCmdNotFoundRequirements.ps1" Source="$(var.SettingsV2AssetsFilesPath)\Scripts\CheckCmdNotFoundRequirements.ps1" />
|
||||
<File Id="CommandNotFound_Scripts_InstallWinGetClientModule.ps1" Source="$(var.SettingsV2AssetsFilesPath)\Scripts\InstallWinGetClientModule.ps1" />
|
||||
<File Id="CommandNotFound_Scripts_InstallPowerShell7.ps1" Source="$(var.SettingsV2AssetsFilesPath)\Scripts\InstallPowerShell7.ps1" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
|
@ -0,0 +1,41 @@
|
||||
Write-Host $PSVersionTable
|
||||
if ($PSVersionTable.PSVersion -ge 7.4)
|
||||
{
|
||||
Write-Host "PowerShell 7.4 or greater detected."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "PowerShell 7.4 or greater not detected. Installation instructions can be found on https://learn.microsoft.com/powershell/scripting/install/installing-powershell-on-windows `r`n"
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
|
||||
if (Get-Module -ListAvailable -Name Microsoft.WinGet.Client)
|
||||
{
|
||||
Write-Host "WinGet Client module detected."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
else {
|
||||
Write-Host "WinGet Client module not detected. Installation instructions can be found on https://www.powershellgallery.com/packages/Microsoft.WinGet.Client `r`n"
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
|
||||
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 "Command Not Found module is registered in the profile file."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Command Not Found module is not registered in the profile file."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
@ -30,6 +30,8 @@ if($atLeastOneInstanceFound)
|
||||
{
|
||||
Set-Content -Path $PROFILE -Value $newContent
|
||||
Write-Host "Removed the Command Not Found reference from the profile file."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
} else {
|
||||
Write-Host "No instance of Command Not Found was found in the profile file."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ $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."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -35,4 +36,5 @@ else
|
||||
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."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
|
||||
if ((Get-AppxPackage microsoft.DesktopAppInstaller).Version -ge [System.Version]"1.21")
|
||||
{
|
||||
Write-Host "Detected winget. Will try to install PowerShell."
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "WinGet not detected. Will try to install."
|
||||
# To speed up Invoke-WebRequest. Older versions are very slow when printing the progress.
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
$cpuArchitecture="x64"
|
||||
$detectedArchitecture=""
|
||||
if ($env:PROCESSOR_ARCHITEW6432 -eq $null) {
|
||||
$detectedArchitecture=$env:PROCESSOR_ARCHITECTURE
|
||||
} else {
|
||||
$detectedArchitecture=$env:PROCESSOR_ARCHITEW6432
|
||||
}
|
||||
Write-Host "Detected the CPU architecture:$detectedArchitecture"
|
||||
if ($detectedArchitecture -ne "AMD64")
|
||||
{
|
||||
Write-Host "Mismatch with AMD64, setting it to arm64, since that's where we're likely running."
|
||||
$cpuArchitecture="arm64"
|
||||
}
|
||||
if((Get-AppxPackage Microsoft.VCLibs.140.00).Version -ge [System.Version]"14.0.30704")
|
||||
{
|
||||
Write-Host "Detected Microsoft.VCLibs.140.00."
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Microsoft.VCLibs.140.00 not detected. Will try to install."
|
||||
Invoke-WebRequest -Uri https://aka.ms/Microsoft.VCLibs.$cpuArchitecture.14.00.Desktop.appx -OutFile "$Env:TMP\Microsoft.VCLibs.14.00.appx"
|
||||
Add-AppxPackage -Path "$Env:TMP\Microsoft.VCLibs.14.00.appx"
|
||||
Remove-Item -Path "$Env:TMP\Microsoft.VCLibs.14.00.appx" -Force
|
||||
}
|
||||
if((Get-AppxPackage Microsoft.VCLibs.140.00.UWPDesktop).Version -ge [System.Version]"14.0.30704")
|
||||
{
|
||||
Write-Host "Detected Microsoft.VCLibs.140.00.UWPDesktop"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Microsoft.VCLibs.140.00.UWPDesktop not detected. Will try to install."
|
||||
Invoke-WebRequest -Uri https://aka.ms/Microsoft.VCLibs.$cpuArchitecture.14.00.Desktop.appx -OutFile "$Env:TMP\Microsoft.VCLibs.14.00.Desktop.appx"
|
||||
Add-AppxPackage -Path "$Env:TMP\Microsoft.VCLibs.14.00.Desktop.appx"
|
||||
Remove-Item -Path "$Env:TMP\Microsoft.VCLibs.14.00.Desktop.appx" -Force
|
||||
}
|
||||
if (Get-AppxPackage Microsoft.UI.Xaml.2.7)
|
||||
{
|
||||
Write-Host "Detected Microsoft.UI.Xaml.2.7"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Microsoft.UI.Xaml.2.7 not detected. Will try to install."
|
||||
Write-Host "Downloading to $Env:TMP\microsoft.ui.xaml.2.7.3.zip"
|
||||
Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.7.3 -OutFile "$Env:TMP\microsoft.ui.xaml.2.7.3.zip"
|
||||
Write-Host "Extracting $Env:TMP\microsoft.ui.xaml.2.7.3.zip"
|
||||
Expand-Archive "$Env:TMP\microsoft.ui.xaml.2.7.3.zip" -DestinationPath "$Env:TMP\microsoft.ui.xaml.2.7.3"
|
||||
Write-Host "Installing $Env:TMP\microsoft.ui.xaml.2.7.3\tools\AppX\$cpuArchitecture\Release\Microsoft.UI.Xaml.2.7.appx"
|
||||
Add-AppxPackage "$Env:TMP\microsoft.ui.xaml.2.7.3\tools\AppX\$cpuArchitecture\Release\Microsoft.UI.Xaml.2.7.appx"
|
||||
Remove-Item -Path "$Env:TMP\microsoft.ui.xaml.2.7.3" -Recurse -Force
|
||||
Remove-Item -Path "$Env:TMP\microsoft.ui.xaml.2.7.3.zip" -Force
|
||||
}
|
||||
Write-Host "Getting winget to the latest stable"
|
||||
Invoke-WebRequest -Uri https://aka.ms/getwinget -OutFile "$Env:TMP\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
|
||||
Add-AppxPackage -Path "$Env:TMP\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
|
||||
Remove-Item -Path "$Env:TMP\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -Force
|
||||
|
||||
#winget is not visible right away, so reload the PATH variable.
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
}
|
||||
|
||||
winget install Microsoft.PowerShell --source winget
|
||||
if ($LASTEXITCODE -eq 0)
|
||||
{
|
||||
Write-Host "Powershell 7 successfully installed."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Powershell 7 was not installed."
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
if (Get-Module -ListAvailable -Name Microsoft.WinGet.Client)
|
||||
{
|
||||
Write-Host "WinGet Client module detected."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
else {
|
||||
Install-Module -Name Microsoft.WinGet.Client
|
||||
if (Get-Module -ListAvailable -Name Microsoft.WinGet.Client)
|
||||
{
|
||||
Write-Host "WinGet Client module detected."
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
} else {
|
||||
Write-Host "WinGet Client module not detected. Installation instructions can be found on https://www.powershellgallery.com/packages/Microsoft.WinGet.Client `r`n"
|
||||
# This message will be compared against in Command Not Found Settings page code behind. Take care when changing it.
|
||||
}
|
||||
}
|
@ -119,19 +119,28 @@
|
||||
<NoWarn>VSTHRD002;VSTHRD110;VSTHRD100;VSTHRD200;VSTHRD101</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Assets\Settings\icon.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Assets\Settings\icon.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Assets\Settings\Scripts\EnableModule.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Assets\Settings\Scripts\DisableModule.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Assets\Settings\Scripts\CheckCmdNotFoundRequirements.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Assets\Settings\Scripts\InstallWinGetClientModule.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Assets\Settings\Scripts\InstallPowerShell7.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Assets\Settings\Scripts\EnableModule.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Assets\Settings\Scripts\DisableModule.ps1">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -12,10 +12,10 @@
|
||||
<controls:OOBEPageControl x:Uid="Oobe_CmdNotFound" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/CmdNotFound.png">
|
||||
|
||||
<controls:OOBEPageControl.PageContent>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Vertical" Spacing="12">
|
||||
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
|
||||
|
||||
<controls:ShortcutWithTextLabelControl x:Name="HotkeyControl" x:Uid="Oobe_CmdNotFound_HowToUse" />
|
||||
<toolkitcontrols:MarkdownTextBlock x:Uid="Oobe_CmdNotFound_HowToUse" Background="Transparent" />
|
||||
|
||||
<StackPanel
|
||||
Margin="0,24,0,0"
|
||||
|
@ -6,10 +6,17 @@
|
||||
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:toolkitConverters="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
AutomationProperties.LandmarkType="Main"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Page.Resources>
|
||||
<toolkitConverters:BoolToVisibilityConverter
|
||||
x:Key="BoolToInvertedVisibilityConverter"
|
||||
FalseValue="Visible"
|
||||
TrueValue="Collapsed" />
|
||||
<toolkitConverters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||
</Page.Resources>
|
||||
<custom:SettingsPageControl x:Uid="CmdNotFound" ModuleImageSource="ms-appx:///Assets/Settings/Modules/CmdNotFound.png">
|
||||
<custom:SettingsPageControl.ModuleContent>
|
||||
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}" Orientation="Vertical">
|
||||
@ -20,25 +27,115 @@
|
||||
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
|
||||
Severity="Informational" />
|
||||
|
||||
<controls:SettingsCard
|
||||
<controls:SettingsExpander
|
||||
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>
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}"
|
||||
IsExpanded="True">
|
||||
<controls:SwitchPresenter TargetType="x:Boolean" Value="{x:Bind ViewModel.IsCommandNotFoundModuleInstalled, Mode=OneWay}">
|
||||
<controls:Case Value="True">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBlock
|
||||
x:Uid="InstalledLabel"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
<FontIcon
|
||||
Margin="0,0,4,0"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Foreground="{ThemeResource SystemFillColorSuccessBrush}"
|
||||
Glyph="" />
|
||||
<HyperlinkButton x:Uid="CmdNotFound_UninstallButton" Command="{x:Bind ViewModel.UninstallModuleEventHandler}" />
|
||||
</StackPanel>
|
||||
</controls:Case>
|
||||
<controls:Case Value="False">
|
||||
<Button
|
||||
x:Uid="CmdNotFound_InstallButton"
|
||||
Command="{x:Bind ViewModel.InstallModuleEventHandler}"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</controls:Case>
|
||||
</controls:SwitchPresenter>
|
||||
<controls:SettingsExpander.ItemsHeader>
|
||||
<InfoBar
|
||||
x:Uid="CmdNotFound_RequirementsBar"
|
||||
BorderThickness="0"
|
||||
CornerRadius="0"
|
||||
IsClosable="False"
|
||||
IsOpen="True">
|
||||
<InfoBar.ActionButton>
|
||||
<HyperlinkButton x:Uid="CmdNotFound_CheckCompatibility" Command="{x:Bind ViewModel.CheckRequirementsEventHandler}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="CmdNotFound_CheckCompatibilityTooltip" TextWrapping="Wrap" />
|
||||
</ToolTipService.ToolTip>
|
||||
</HyperlinkButton>
|
||||
</InfoBar.ActionButton>
|
||||
</InfoBar>
|
||||
</controls:SettingsExpander.ItemsHeader>
|
||||
<controls:SettingsExpander.Items>
|
||||
|
||||
<controls:SettingsCard x:Uid="CmdNotFound_PowerShellDetection">
|
||||
<controls:SwitchPresenter TargetType="x:Boolean" Value="{x:Bind ViewModel.IsPowerShell7Detected, Mode=OneWay}">
|
||||
<controls:Case Value="True">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBlock
|
||||
x:Uid="DetectedLabel"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
<FontIcon
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Foreground="{ThemeResource SystemFillColorSuccessBrush}"
|
||||
Glyph="" />
|
||||
</StackPanel>
|
||||
</controls:Case>
|
||||
<controls:Case Value="False">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBlock
|
||||
x:Uid="NotDetectedLabel"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
<FontIcon
|
||||
Margin="0,0,4,0"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Foreground="{ThemeResource SystemFillColorCriticalBrush}"
|
||||
Glyph="" />
|
||||
<Button x:Uid="CmdNotFound_InstallButton" Command="{x:Bind ViewModel.InstallPowerShell7EventHandler}" />
|
||||
</StackPanel>
|
||||
</controls:Case>
|
||||
</controls:SwitchPresenter>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="CmdNotFound_WinGetClientDetection">
|
||||
<controls:SwitchPresenter TargetType="x:Boolean" Value="{x:Bind ViewModel.IsWinGetClientModuleDetected, Mode=OneWay}">
|
||||
<controls:Case Value="True">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBlock
|
||||
x:Uid="DetectedLabel"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
<FontIcon
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Foreground="{ThemeResource SystemFillColorSuccessBrush}"
|
||||
Glyph="" />
|
||||
</StackPanel>
|
||||
</controls:Case>
|
||||
<controls:Case Value="False">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBlock
|
||||
x:Uid="NotDetectedLabel"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
<FontIcon
|
||||
Margin="0,0,4,0"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Foreground="{ThemeResource SystemFillColorCriticalBrush}"
|
||||
Glyph="" />
|
||||
<Button x:Uid="CmdNotFound_InstallButton" Command="{x:Bind ViewModel.InstallWinGetClientModuleEventHandler}" />
|
||||
</StackPanel>
|
||||
</controls:Case>
|
||||
</controls:SwitchPresenter>
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
<TextBlock
|
||||
x:Uid="CmdNotFound_ModuleInstallationLogs"
|
||||
Margin="0,12,0,4"
|
||||
|
@ -3676,12 +3676,30 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="CmdNotFound.ModuleTitle" xml:space="preserve">
|
||||
<value>Command Not Found</value>
|
||||
<comment>"Command Not Found" is a product name</comment>
|
||||
</data>
|
||||
<data name="InstalledLabel.Text" xml:space="preserve">
|
||||
<value>Installed</value>
|
||||
</data>
|
||||
<data name="DetectedLabel.Text" xml:space="preserve">
|
||||
<value>Detected</value>
|
||||
</data>
|
||||
<data name="NotDetectedLabel.Text" xml:space="preserve">
|
||||
<value>Not detected</value>
|
||||
</data>
|
||||
<data name="CmdNotFound_RequirementsBar.Title" xml:space="preserve">
|
||||
<value>The following components are required</value>
|
||||
</data>
|
||||
<data name="CmdNotFound_PowerShellDetection.Header" xml:space="preserve">
|
||||
<value>PowerShell 7.4 or greater</value>
|
||||
</data>
|
||||
<data name="CmdNotFound_WinGetClientDetection.Header" xml:space="preserve">
|
||||
<value>WinGet Client PowerShell module</value>
|
||||
</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">
|
||||
<data name="CmdNotFound_Enable.Description" 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">
|
||||
@ -3691,7 +3709,10 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<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>
|
||||
<value>Refresh</value>
|
||||
</data>
|
||||
<data name="CmdNotFound_CheckCompatibilityTooltip.Text" xml:space="preserve">
|
||||
<value>Check if your PowerShell configuration is compatible and configured correctly</value>
|
||||
</data>
|
||||
<data name="CmdNotFound_InstallButton.Content" xml:space="preserve">
|
||||
<value>Install</value>
|
||||
|
@ -7,6 +7,7 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands;
|
||||
@ -16,7 +17,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public class CmdNotFoundViewModel : Observable
|
||||
{
|
||||
public ButtonClickCommand CheckPowershellVersionEventHandler => new ButtonClickCommand(CheckPowershellVersion);
|
||||
public ButtonClickCommand CheckRequirementsEventHandler => new ButtonClickCommand(CheckCommandNotFoundRequirements);
|
||||
|
||||
public ButtonClickCommand InstallPowerShell7EventHandler => new ButtonClickCommand(InstallPowerShell7);
|
||||
|
||||
public ButtonClickCommand InstallWinGetClientModuleEventHandler => new ButtonClickCommand(InstallWinGetClientModule);
|
||||
|
||||
public ButtonClickCommand InstallModuleEventHandler => new ButtonClickCommand(InstallModule);
|
||||
|
||||
@ -49,6 +54,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
// Get the enabled state from GPO.
|
||||
_enabledStateIsGPOConfigured = true;
|
||||
}
|
||||
|
||||
CheckCommandNotFoundRequirements();
|
||||
}
|
||||
|
||||
private string _commandOutputLog;
|
||||
@ -66,20 +73,66 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isPowerShell7Detected;
|
||||
|
||||
public bool IsPowerShell7Detected
|
||||
{
|
||||
get => _isPowerShell7Detected;
|
||||
set
|
||||
{
|
||||
if (_isPowerShell7Detected != value)
|
||||
{
|
||||
_isPowerShell7Detected = value;
|
||||
OnPropertyChanged(nameof(IsPowerShell7Detected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isWinGetClientModuleDetected;
|
||||
|
||||
public bool IsWinGetClientModuleDetected
|
||||
{
|
||||
get => _isWinGetClientModuleDetected;
|
||||
set
|
||||
{
|
||||
if (_isWinGetClientModuleDetected != value)
|
||||
{
|
||||
_isWinGetClientModuleDetected = value;
|
||||
OnPropertyChanged(nameof(IsWinGetClientModuleDetected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isCommandNotFoundModuleInstalled;
|
||||
|
||||
public bool IsCommandNotFoundModuleInstalled
|
||||
{
|
||||
get => _isCommandNotFoundModuleInstalled;
|
||||
set
|
||||
{
|
||||
if (_isCommandNotFoundModuleInstalled != value)
|
||||
{
|
||||
_isCommandNotFoundModuleInstalled = value;
|
||||
OnPropertyChanged(nameof(IsCommandNotFoundModuleInstalled));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabledGpoConfigured
|
||||
{
|
||||
get => _enabledStateIsGPOConfigured;
|
||||
}
|
||||
|
||||
public void RunPowerShellScript(string powershellArguments)
|
||||
public string RunPowerShellScript(string powershellExecutable, string powershellArguments, bool hidePowerShellWindow = false)
|
||||
{
|
||||
string outputLog = string.Empty;
|
||||
try
|
||||
{
|
||||
var startInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = "pwsh.exe",
|
||||
FileName = powershellExecutable,
|
||||
Arguments = powershellArguments,
|
||||
CreateNoWindow = hidePowerShellWindow,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
};
|
||||
@ -96,28 +149,112 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
|
||||
CommandOutputLog = outputLog;
|
||||
return outputLog;
|
||||
}
|
||||
|
||||
public void CheckPowershellVersion()
|
||||
public void CheckCommandNotFoundRequirements()
|
||||
{
|
||||
var arguments = $"-NoProfile -NonInteractive -Command $PSVersionTable";
|
||||
RunPowerShellScript(arguments);
|
||||
var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\CheckCmdNotFoundRequirements.ps1";
|
||||
var arguments = $"-NoProfile -NonInteractive -ExecutionPolicy Unrestricted -File \"{ps1File}\"";
|
||||
var result = RunPowerShellScript("pwsh.exe", arguments, true);
|
||||
|
||||
if (result.Contains("PowerShell 7.4 or greater detected."))
|
||||
{
|
||||
IsPowerShell7Detected = true;
|
||||
}
|
||||
else if (result.Contains("PowerShell 7.4 or greater not detected."))
|
||||
{
|
||||
IsPowerShell7Detected = false;
|
||||
}
|
||||
else if (result.Contains("pwsh.exe"))
|
||||
{
|
||||
// Likely an error saying there was an error starting pwsh.exe, so we can assume Powershell 7 was not detected.
|
||||
CommandOutputLog += "PowerShell 7.4 or greater not detected. Installation instructions can be found on https://learn.microsoft.com/powershell/scripting/install/installing-powershell-on-windows \r\n";
|
||||
IsPowerShell7Detected = false;
|
||||
}
|
||||
|
||||
if (result.Contains("WinGet Client module detected."))
|
||||
{
|
||||
IsWinGetClientModuleDetected = true;
|
||||
}
|
||||
else if (result.Contains("WinGet Client module not detected."))
|
||||
{
|
||||
IsWinGetClientModuleDetected = false;
|
||||
}
|
||||
|
||||
if (result.Contains("Command Not Found module is registered in the profile file."))
|
||||
{
|
||||
IsCommandNotFoundModuleInstalled = true;
|
||||
}
|
||||
else if (result.Contains("Command Not Found module is not registered in the profile file."))
|
||||
{
|
||||
IsCommandNotFoundModuleInstalled = false;
|
||||
}
|
||||
|
||||
Logger.LogInfo(result);
|
||||
}
|
||||
|
||||
public void InstallPowerShell7()
|
||||
{
|
||||
var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\InstallPowerShell7.ps1";
|
||||
var arguments = $"-NoProfile -ExecutionPolicy Unrestricted -File \"{ps1File}\"";
|
||||
var result = RunPowerShellScript("powershell.exe", arguments);
|
||||
if (result.Contains("Powershell 7 successfully installed."))
|
||||
{
|
||||
IsPowerShell7Detected = true;
|
||||
}
|
||||
|
||||
Logger.LogInfo(result);
|
||||
|
||||
// Update PATH environment variable to get pwsh.exe on further calls.
|
||||
Environment.SetEnvironmentVariable("PATH", (Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine) ?? string.Empty) + ";" + (Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User) ?? string.Empty), EnvironmentVariableTarget.Process);
|
||||
}
|
||||
|
||||
public void InstallWinGetClientModule()
|
||||
{
|
||||
var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\InstallWinGetClientModule.ps1";
|
||||
var arguments = $"-NoProfile -ExecutionPolicy Unrestricted -File \"{ps1File}\"";
|
||||
var result = RunPowerShellScript("pwsh.exe", arguments);
|
||||
if (result.Contains("WinGet Client module detected."))
|
||||
{
|
||||
IsWinGetClientModuleDetected = true;
|
||||
}
|
||||
else if (result.Contains("WinGet Client module not detected."))
|
||||
{
|
||||
IsWinGetClientModuleDetected = false;
|
||||
}
|
||||
|
||||
Logger.LogInfo(result);
|
||||
}
|
||||
|
||||
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());
|
||||
var result = RunPowerShellScript("pwsh.exe", arguments);
|
||||
|
||||
if (result.Contains("Module is already registered in the profile file.") || result.Contains("Module was successfully registered in the profile file."))
|
||||
{
|
||||
IsCommandNotFoundModuleInstalled = true;
|
||||
PowerToysTelemetry.Log.WriteEvent(new CmdNotFoundInstallEvent());
|
||||
}
|
||||
|
||||
Logger.LogInfo(result);
|
||||
}
|
||||
|
||||
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());
|
||||
var result = RunPowerShellScript("pwsh.exe", arguments);
|
||||
|
||||
if (result.Contains("Removed the Command Not Found reference from the profile file.") || result.Contains("No instance of Command Not Found was found in the profile file."))
|
||||
{
|
||||
IsCommandNotFoundModuleInstalled = false;
|
||||
PowerToysTelemetry.Log.WriteEvent(new CmdNotFoundUninstallEvent());
|
||||
}
|
||||
|
||||
Logger.LogInfo(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user