diff --git a/Sophia/PowerShell 7.x/Sophia.ps1 b/Sophia/PowerShell 7.x/Sophia.ps1 index bdcbc1b1..45905d8c 100644 --- a/Sophia/PowerShell 7.x/Sophia.ps1 +++ b/Sophia/PowerShell 7.x/Sophia.ps1 @@ -2,8 +2,8 @@ .SYNOPSIS Default preset file for "Windows 10 Sophia Script" - Version: v5.7 - Date: 05.03.2021 + Version: v5.8 + Date: 17.03.2021 Copyright (c) 2015–2021 farag & oZ-Zo https://github.com/farag2 @@ -57,7 +57,7 @@ param Clear-Host -$Host.UI.RawUI.WindowTitle = "Windows 10 Sophia Script v5.7 | $([char]0x00A9) farag & oz-zo, 2015–2021" +$Host.UI.RawUI.WindowTitle = "Windows 10 Sophia Script v5.8 | Made with $([char]::ConvertFromUtf32(0x1F497)) of Windows 10 | $([char]0x00A9) farag & oz-zo, 2015–2021" Remove-Module -Name Sophia -Force -ErrorAction Ignore Import-Module -Name $PSScriptRoot\Sophia.psd1 -PassThru -Force @@ -862,20 +862,14 @@ DeviceRestartAfterUpdate -Enable <# Register app, calculate hash, and set as default for specific extension without the "How do you want to open this?" pop-up - Зарегистрировать приложение, вычислить хэш и установить как приложение по умолчанию для конкретного расширения без всплывающего окошка "Каким образом вы хотите открыть этот файл?" + Зарегистрировать приложение, вычислить хэш и установить как приложение по умолчанию для конкретного расширения без всплывающего окна "Каким образом вы хотите открыть этот файл?" Examples: Примеры: Set-Association -ProgramPath "C:\SumatraPDF.exe" -Extension .pdf -Icon "shell32.dll,100" - Set-Association -ProgramPath "C:\Program Files\Notepad++\notepad++.exe" -Extension .psm1 -Icon "C:\Program Files\Notepad++\notepad++.exe,0" - - The app must be installed - Приложение должно быть установлено - - Do not use relative paths like "%Program Files%" - Не используйте относительные пути вида "%Program Files%" + Set-Association -ProgramPath "%ProgramFiles%\Notepad++\notepad++.exe" -Extension .txt -Icon "%ProgramFiles%\Notepad++\notepad++.exe,0" #> -# Set-Association -ProgramPath "C:\Program Files\Notepad++\notepad++.exe" -Extension .psm1 -Icon "C:\Program Files\Notepad++\notepad++.exe,0" +# Set-Association -ProgramPath "%ProgramFiles%\Notepad++\notepad++.exe" -Extension .txt -Icon "%ProgramFiles%\Notepad++\notepad++.exe,0" #endregion System #region WSL @@ -925,11 +919,11 @@ RunPowerShellShortcut -Elevated # RunPowerShellShortcut -NonElevated <# - Assign what shortcuts to pin to Start - Valid shortcuts: ControlPanel, DevicesPrinters and PowerShell + Pin to Start the following links: Control Panel, Devices and Printers, PowerShell + Valid shortcuts values: ControlPanel, DevicesPrinters and PowerShell - Указать, какие ярлыки закрепить на начальном экране - Валидные ярлыки: ControlPanel, DevicesPrinters and PowerShell + Закрепить на начальном экране следующие ярлыки: Панель управдения, Устройства и принтеры, PowerShell + Валидные значения ярлыков: ControlPanel, DevicesPrinters, PowerShell #> PinToStart -Tiles ControlPanel, DevicesPrinters, PowerShell @@ -947,13 +941,26 @@ PinToStart -Tiles ControlPanel, DevicesPrinters, PowerShell #region UWP apps <# Uninstall UWP apps using the pop-up dialog box - App packages will not be installed for new users if "Uninstall for All Users" is checked + If the "For All Users" is checked apps packages will not be installed for new users + The "For All Users" checkbox isn't checked by default Удалить UWP-приложения, используя всплывающее диалоговое окно - Приложения не будут установлены для новых пользователей, если отмечено "Удалять для всех пользователей" + Пакеты приложений не будут установлены для новых пользователей, если отмечена галочка "Для всех пользователей" + Галочка "Для всех пользователей" не отмечена по умолчанию #> UninstallUWPApps +<# + Uninstall UWP apps using the pop-up dialog box + If the "For All Users" is checked apps packages will not be installed for new users + The "For All Users" checkbox checked by default + + Удалить UWP-приложения, используя всплывающее диалоговое окно + Пакеты приложений не будут установлены для новых пользователей, если отмечена галочка "Для всех пользователей" + Галочка "Для всех пользователей" отмечена по умолчанию +#> +# UninstallUWPApps -ForAllUsers + <# Open Microsoft Store "HEVC Video Extensions from Device Manufacturer" page to install this extension manually to be able to open .heic and .heif formats The extension can be installed without Microsoft account @@ -1033,14 +1040,16 @@ GPUScheduling -Enable CleanupTask -Register # Delete the "Windows Cleanup" and "Windows Cleanup Notification" scheduled tasks for cleaning up Windows unused files and updates -# Удалить задачу "Windows Cleanup" и "Windows Cleanup Notification" по очистке неиспользуемых файлов и обновлений Windows из Планировщика заданий +# Удалить задачи "Windows Cleanup" и "Windows Cleanup Notification" по очистке неиспользуемых файлов и обновлений Windows из Планировщика заданий # CleanupTask -Delete <# Create the "SoftwareDistribution" scheduled task for cleaning up the %SystemRoot%\SoftwareDistribution\Download folder + The task will wait until the Windows Updates service finishes running The task runs every 90 days Создать задачу "SoftwareDistribution" по очистке папки %SystemRoot%\SoftwareDistribution\Download в Планировщике заданий + Задача будет ждать, пока служба обновлений Windows не закончит работу Задача выполняется каждые 90 дней #> SoftwareDistributionTask -Register diff --git a/Sophia/PowerShell 7.x/Sophia.psd1 b/Sophia/PowerShell 7.x/Sophia.psd1 index 45581eb7..dbdec1a7 100644 Binary files a/Sophia/PowerShell 7.x/Sophia.psd1 and b/Sophia/PowerShell 7.x/Sophia.psd1 differ diff --git a/Sophia/PowerShell 7.x/Sophia.psm1 b/Sophia/PowerShell 7.x/Sophia.psm1 index 7ae2a2e9..62bb0db8 100644 --- a/Sophia/PowerShell 7.x/Sophia.psm1 +++ b/Sophia/PowerShell 7.x/Sophia.psm1 @@ -2,8 +2,8 @@ .SYNOPSIS "Windows 10 Sophia Script" is a PowerShell module for Windows 10 fine-tuning and automating the routine tasks - Version: v5.7 - Date: 05.03.2021 + Version: v5.8 + Date: 17.03.2021 Copyright (c) 2015–2021 farag & oZ-Zo https://github.com/farag2 @@ -63,7 +63,7 @@ function Checkings } } - # Checking whether the current module version is the latest + # Checking if the current module version is the latest one try { $LatestRelease = (Invoke-RestMethod -Uri "https://api.github.com/repos/farag2/Windows-10-Sophia-Script/releases").tag_name | Select-Object -First 1 @@ -91,13 +91,7 @@ function Checkings Get-ChildItem -Path $PSScriptRoot -Recurse -Force | Unblock-File # Import PowerShell 5.1 modules - switch ($PSVersionTable.PSVersion.Major) - { - "7" - { - Import-Module -Name Microsoft.PowerShell.Management, PackageManagement, Appx -UseWindowsPowerShell - } - } + Import-Module -Name Microsoft.PowerShell.Management, PackageManagement, Appx -UseWindowsPowerShell # Turn off Controlled folder access to let the script proceed switch ((Get-MpPreference).EnableControlledFolderAccess) @@ -578,7 +572,7 @@ function ScheduledTasks [void]$Window.Close() - $SelectedTasks | ForEach-Object -Process {Write-Verbose $_.TaskName -Verbose} + $SelectedTasks | ForEach-Object -Process {Write-Verbose $_.TaskName -Verbose} $SelectedTasks | Disable-ScheduledTask } @@ -588,7 +582,7 @@ function ScheduledTasks [void]$Window.Close() - $SelectedTasks | ForEach-Object -Process {Write-Verbose $_.TaskName -Verbose} + $SelectedTasks | ForEach-Object -Process {Write-Verbose $_.TaskName -Verbose} $SelectedTasks | Enable-ScheduledTask } @@ -2530,16 +2524,25 @@ function UnpinTaskbarEdgeStore Add-Type @Signature -Using System.Text } - # Extract the "Unpin from taskbar" string from shell32.dll + # Extract the localized "Unpin from taskbar" string from shell32.dll $LocalizedString = [WinAPI.GetStr]::GetString(5387) $Apps = (New-Object -ComObject Shell.Application).NameSpace("shell:::{4234d49b-0245-4df3-b780-3893943456e1}").Items() - [void]{$Apps | Where-Object -FilterScript {$_.Path -eq "MSEdge"} | ForEach-Object -Process { - $_.Verbs() | Where-Object -FilterScript {$_.Name -eq $LocalizedString} | ForEach-Object -Process {$_.DoIt()} - }} - [void]{$Apps | Where-Object -FilterScript {$_.Name -eq "Microsoft Store"} | ForEach-Object -Process { + + $VerbExists = $Apps | Where-Object -FilterScript {$_.Path -eq "MSEdge"} | ForEach-Object -Process {$_.Verbs() | Where-Object -FilterScript {$_.Name -eq $LocalizedString}} + if ($VerbExists) + { + $VerbExists | ForEach-Object -Process {$_.DoIt()} + } + else + { + Remove-Item -Path "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Edge.lnk" -ErrorAction Ignore + $VerbExists | ForEach-Object -Process {$_.DoIt()} + } + + $Apps | Where-Object -FilterScript {$_.Name -eq "Microsoft Store"} | ForEach-Object -Process { $_.Verbs() | Where-Object -FilterScript {$_.Name -eq $LocalizedString} | ForEach-Object -Process {$_.DoIt()} - }} + } } <# @@ -3314,12 +3317,11 @@ function OneDrive { Write-Verbose -Message $Localization.OneDriveDownloading -Verbose - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - $DownloadsFolder = Get-ItemPropertyValue -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name "{374DE290-123F-4565-9164-39C4925E467B}" $Parameters = @{ Uri = "https://go.microsoft.com/fwlink/p/?LinkID=2121808" OutFile = "$DownloadsFolder\OneDriveSetup.exe" + SslProtocol = "Tls12" Verbose = [switch]::Present } Invoke-WebRequest @Parameters @@ -3683,7 +3685,7 @@ function TempFolder New-Item -Path $env:SystemDrive\Temp -ItemType Directory -Force } - # Copy all imported module folders to the new %TEMP% folder. For PowerShell 7.x using only + # Copy all imported module folders to the new %TEMP% folder Get-ChildItem -Path $env:LOCALAPPDATA\Temp -Force | Where-Object -FilterScript {$_.Name -like "*remoteIpMoProxy*"} | ForEach-Object -Process { Copy-Item $_.FullName -Destination $env:SystemDrive\Temp -Recurse -Force } @@ -3701,9 +3703,9 @@ function TempFolder { $Title = "" $Message = $Localization.ClearFolder -f "$env:LOCALAPPDATA\Temp" - $Continue = $Localization.Continue + $Delete = $Localization.Delete $Skip = $Localization.Skip - $Options = "&$Continue", "&$Skip" + $Options = "&$Delete", "&$Skip" $DefaultChoice = 0 $Result = $Host.UI.PromptForChoice($Title, $Message, $Options, $DefaultChoice) @@ -5435,12 +5437,43 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int while ($k.Key -notin ([ConsoleKey]::Escape, [ConsoleKey]::Enter)) } + $Signature = @{ + Namespace = "WinAPI" + Name = "GetStr" + Language = "CSharp" + MemberDefinition = @" +[DllImport("kernel32.dll", CharSet = CharSet.Auto)] +public static extern IntPtr GetModuleHandle(string lpModuleName); +[DllImport("user32.dll", CharSet = CharSet.Auto)] +internal static extern int LoadString(IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax); +public static string GetString(uint strId) +{ + IntPtr intPtr = GetModuleHandle("shell32.dll"); + StringBuilder sb = new StringBuilder(255); + LoadString(intPtr, strId, sb, sb.Capacity); + return sb.ToString(); +} +"@ + } + if (-not ("WinAPI.GetStr" -as [type])) + { + Add-Type @Signature -Using System.Text + } + + $DesktopLocalizedString = [WinAPI.GetStr]::GetString(21769) + $DocumentsLocalizedString = [WinAPI.GetStr]::GetString(21770) + $DownloadsLocalizedString = [WinAPI.GetStr]::GetString(21798) + $MusicLocalizedString = [WinAPI.GetStr]::GetString(21790) + $PicturesLocalizedString = [WinAPI.GetStr]::GetString(21779) + $VideosLocalizedString = [WinAPI.GetStr]::GetString(21791) + switch ($PSCmdlet.ParameterSetName) { "Root" { - # Store all drives letters to use them within ShowMenu function Write-Verbose -Message $Localization.RetrievingDrivesList -Verbose + + # Store all drives letters to use them within ShowMenu function $DriveLetters = @((Get-Disk | Where-Object -FilterScript {$_.BusType -ne "USB"} | Get-Partition | Get-Volume | Where-Object -FilterScript {$null -ne $_.DriveLetter}).DriveLetter | Sort-Object) # If the number of disks is more than one, set the second drive in the list as default drive @@ -5454,11 +5487,11 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int } # Desktop - Write-Verbose -Message $Localization.DesktopDriveSelect -Verbose + Write-Verbose -Message ($Localization.DriveSelect -f $DesktopLocalizedString) -Verbose Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.DesktopRequest + $Message = $Localization.UserFolderRequest -f $DesktopLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5469,7 +5502,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int { "0" { - $SelectedDrive = ShowMenu -Title $Localization.DesktopDriveSelect -Menu $DriveLetters -Default $Script:Default + $SelectedDrive = ShowMenu -Title ($Localization.DriveSelect -f $DesktopLocalizedString) -Menu $DriveLetters -Default $Script:Default UserShellFolder -UserFolder Desktop -FolderPath "${SelectedDrive}:\Desktop" -RemoveDesktopINI } "1" @@ -5479,11 +5512,11 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int } # Documents - Write-Verbose -Message $Localization.DocumentsDriveSelect -Verbose + Write-Verbose -Message ($Localization.DriveSelect -f $DocumentsLocalizedString) -Verbose Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.DocumentsRequest + $Message = $Localization.UserFolderRequest -f $DocumentsLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5494,7 +5527,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int { "0" { - $SelectedDrive = ShowMenu -Title $Localization.DocumentsDriveSelect -Menu $DriveLetters -Default $Script:Default + $SelectedDrive = ShowMenu -Title ($Localization.DriveSelect -f $DocumentsLocalizedString) -Menu $DriveLetters -Default $Script:Default UserShellFolder -UserFolder Documents -FolderPath "${SelectedDrive}:\Documents" -RemoveDesktopINI } "1" @@ -5504,11 +5537,11 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int } # Downloads - Write-Verbose -Message $Localization.DownloadsDriveSelect -Verbose + Write-Verbose -Message ($Localization.DriveSelect -f $DownloadsLocalizedString) -Verbose Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.DownloadsRequest + $Message = $Localization.UserFolderRequest -f $DownloadsLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5519,7 +5552,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int { "0" { - $SelectedDrive = ShowMenu -Title $Localization.DownloadsDriveSelect -Menu $DriveLetters -Default $Script:Default + $SelectedDrive = ShowMenu -Title ($Localization.DriveSelect -f $DownloadsLocalizedString) -Menu $DriveLetters -Default $Script:Default UserShellFolder -UserFolder Downloads -FolderPath "${SelectedDrive}:\Downloads" -RemoveDesktopINI } "1" @@ -5529,11 +5562,11 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int } # Music - Write-Verbose -Message $Localization.MusicDriveSelect -Verbose + Write-Verbose -Message ($Localization.DriveSelect -f $MusicLocalizedString) -Verbose Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.MusicRequest + $Message = $Localization.UserFolderRequest -f $MusicLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5544,7 +5577,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int { "0" { - $SelectedDrive = ShowMenu -Title $Localization.MusicDriveSelect -Menu $DriveLetters -Default $Script:Default + $SelectedDrive = ShowMenu -Title ($Localization.DriveSelect -f $MusicLocalizedString) -Menu $DriveLetters -Default $Script:Default UserShellFolder -UserFolder Music -FolderPath "${SelectedDrive}:\Music" -RemoveDesktopINI } "1" @@ -5554,11 +5587,11 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int } # Pictures - Write-Verbose -Message $Localization.PicturesDriveSelect -Verbose + Write-Verbose -Message ($Localization.DriveSelect -f $PicturesLocalizedString) -Verbose Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.PicturesRequest + $Message = $Localization.UserFolderRequest -f $PicturesLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5569,7 +5602,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int { "0" { - $SelectedDrive = ShowMenu -Title $Localization.PicturesDriveSelect -Menu $DriveLetters -Default $Script:Default + $SelectedDrive = ShowMenu -Title ($Localization.DriveSelect -f $PicturesLocalizedString) -Menu $DriveLetters -Default $Script:Default UserShellFolder -UserFolder Pictures -FolderPath "${SelectedDrive}:\Pictures" -RemoveDesktopINI } "1" @@ -5579,11 +5612,11 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int } # Videos - Write-Verbose -Message $Localization.VideosDriveSelect -Verbose + Write-Verbose -Message ($Localization.DriveSelect -f $VideosLocalizedString) -Verbose Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.VideosRequest + $Message = $Localization.UserFolderRequest -f $VideosLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5594,7 +5627,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int { "0" { - $SelectedDrive = ShowMenu -Title $Localization.VideosDriveSelect -Menu $DriveLetters -Default $Script:Default + $SelectedDrive = ShowMenu -Title ($Localization.DriveSelect -f $VideosLocalizedString) -Menu $DriveLetters -Default $Script:Default UserShellFolder -UserFolder Videos -FolderPath "${SelectedDrive}:\Videos" -RemoveDesktopINI } "1" @@ -5609,7 +5642,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.DesktopFolderSelect + $Message = $Localization.UserFolderSelect -f $DesktopLocalizedString $Select = $Localization.Select $Skip = $Localization.Skip $Options = "&$Select", "&$Skip" @@ -5645,7 +5678,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.DocumentsFolderSelect + $Message = $Localization.UserFolderSelect -f $DocumentsLocalizedString $Select = $Localization.Select $Skip = $Localization.Skip $Options = "&$Select", "&$Skip" @@ -5681,7 +5714,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.DownloadsFolderSelect + $Message = $Localization.UserFolderSelect -f $DownloadsLocalizedString $Select = $Localization.Select $Skip = $Localization.Skip $Options = "&$Select", "&$Skip" @@ -5717,7 +5750,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.MusicFolderSelect + $Message = $Localization.UserFolderSelect -f $MusicLocalizedString $Select = $Localization.Select $Skip = $Localization.Skip $Options = "&$Select", "&$Skip" @@ -5753,7 +5786,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.PicturesFolderSelect + $Message = $Localization.UserFolderSelect -f $PicturesLocalizedString $Select = $Localization.Select $Skip = $Localization.Skip $Options = "&$Select", "&$Skip" @@ -5789,7 +5822,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.VideosFolderSelect + $Message = $Localization.UserFolderSelect -f $VideosLocalizedString $Select = $Localization.Select $Skip = $Localization.Skip $Options = "&$Select", "&$Skip" @@ -5827,7 +5860,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.DesktopDefaultFolder + $Message = $Localization.UserDefaultFolder -f $DesktopLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5850,7 +5883,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.DocumentsDefaultFolder + $Message = $Localization.UserDefaultFolder -f $DocumentsLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5873,7 +5906,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.DownloadsDefaultFolder + $Message = $Localization.UserDefaultFolder -f $DownloadsLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5896,7 +5929,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.MusicDefaultFolder + $Message = $Localization.UserDefaultFolder -f $MusicLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5919,7 +5952,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.PicturesDefaultFolder + $Message = $Localization.UserDefaultFolder -f $PicturesLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -5942,7 +5975,7 @@ public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, Int Write-Warning -Message $Localization.FilesWontBeMoved $Title = "" - $Message = $Localization.VideosDefaultFolder + $Message = $Localization.UserDefaultFolder -f $VideosLocalizedString $Change = $Localization.Change $Skip = $Localization.Skip $Options = "&$Change", "&$Skip" @@ -6254,7 +6287,7 @@ function F1HelpPage { New-Item -Path "HKCU:\SOFTWARE\Classes\Typelib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64" -Force } - New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\Typelib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64" -Name "(Default)" -PropertyType String -Value "" -Force + New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\Typelib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64" -Name "(default)" -PropertyType String -Value "" -Force } } } @@ -6742,427 +6775,601 @@ function DeviceRestartAfterUpdate Register app, calculate hash, and set as default for specific extension without the "How do you want to open this" pop-up .PARAMETER ProgramPath - Set path to the .exe + Set path to the program to be associate with .PARAMETER Extension - Set extension type + Set the extension type .PARAMETER Icon - Set path to the icon + Set the path to the icon .EXAMPLE Set-Association -ProgramPath "C:\SumatraPDF.exe" -Extension .pdf -Icon "shell32.dll,100" .EXAMPLE - Set-Association -ProgramPath "C:\Program Files\Notepad++\notepad++.exe" -Extension .psm1 -Icon "C:\Program Files\Notepad++\notepad++.exe,0" + Set-Association -ProgramPath "%ProgramFiles%\Notepad++\notepad++.exe" -Extension .txt -Icon "%ProgramFiles%\Notepad++\notepad++.exe,0" .LINK https://github.com/DanysysTeam/PS-SFTA + https://github.com/default-username-was-already-taken/set-fileassoc + https://forum.ru-board.com/profile.cgi?action=show&member=westlife .NOTES - The app must be installed - Do not use relative paths like "%Program Files%" - Current user + Machine-wide #> function Set-Association { [CmdletBinding()] - param + Param ( [Parameter( - Position = 0, - Mandatory = $true + Mandatory = $false, + Position = 0 )] - [ValidateScript({Test-Path -Path $_})] [String] $ProgramPath, [Parameter( - Position = 1, - Mandatory = $true + Mandatory = $true, + Position = 1 )] [String] $Extension, - [Parameter( - Position = 3, - Mandatory = $false - )] + [Parameter(Mandatory = $false)] [String] $Icon ) - $ProgId = "Applications\" + (Get-Item -Path $ProgramPath).BaseName + $Extension + $ProgramPath = [System.Environment]::ExpandEnvironmentVariables($ProgramPath) - if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids")) + if (Test-Path -Path $ProgramPath) { - New-Item -Path "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids" -Force + # Generate ProgId + $ProgId = (Get-Item -Path $ProgramPath).BaseName + $Extension.ToUpper() } - New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids" -Name $ProgId -PropertyType None -Value ([byte[]]@()) -Force - if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\$ProgId\shell\open\command")) + #region functions + $RegistryUtils = @' +using System; +using System.Runtime.InteropServices; +using System.Security.AccessControl; +using System.Text; +using Microsoft.Win32; +using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; + +namespace RegistryUtils +{ + public static class Action { - New-Item -Path "HKCU:\SOFTWARE\Classes\$ProgId\shell\open\command" -Force + [DllImport("advapi32.dll", CharSet = CharSet.Auto)] + private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult); + + [DllImport("advapi32.dll", EntryPoint = "RegQueryInfoKey", CallingConvention = CallingConvention.Winapi, SetLastError = true)] + private static extern int RegQueryInfoKey(UIntPtr hkey, out StringBuilder lpClass, ref uint lpcbClass, IntPtr lpReserved, + out uint lpcSubKeys, out uint lpcbMaxSubKeyLen, out uint lpcbMaxClassLen, out uint lpcValues, out uint lpcbMaxValueNameLen, + out uint lpcbMaxValueLen, out uint lpcbSecurityDescriptor, ref FILETIME lpftLastWriteTime); + + [DllImport("advapi32.dll", SetLastError = true)] + private static extern int RegCloseKey(UIntPtr hKey); + + [DllImport("advapi32.dll", SetLastError=true, CharSet = CharSet.Unicode)] + private static extern uint RegDeleteKey(UIntPtr hKey, string subKey); + + public static void DeleteKey(RegistryHive registryHive, string subkey) { + UIntPtr hKey = UIntPtr.Zero; + var hive = new UIntPtr(unchecked((uint)registryHive)); + RegOpenKeyEx(hive, subkey, 0, 0x20019, out hKey); + RegDeleteKey(hive, subkey); + } + + private static DateTime ToDateTime(FILETIME ft) + { + IntPtr buf = IntPtr.Zero; + try + { + long[] longArray = new long[1]; + int cb = Marshal.SizeOf(ft); + buf = Marshal.AllocHGlobal(cb); + Marshal.StructureToPtr(ft, buf, false); + Marshal.Copy(buf, longArray, 0, 1); + return DateTime.FromFileTime(longArray[0]); + } + finally + { + if (buf != IntPtr.Zero) Marshal.FreeHGlobal(buf); + } + } + + public static DateTime? GetLastModified(RegistryHive registryHive, string subKey) + { + var lastModified = new FILETIME(); + var lpcbClass = new uint(); + var lpReserved = new IntPtr(); + UIntPtr key = UIntPtr.Zero; + + try + { + try + { + var hive = new UIntPtr(unchecked((uint)registryHive)); + if (RegOpenKeyEx(hive, subKey, 0, (int)RegistryRights.ReadKey, out key) != 0) + { + return null; + } + + uint lpcbSubKeys; + uint lpcbMaxKeyLen; + uint lpcbMaxClassLen; + uint lpcValues; + uint maxValueName; + uint maxValueLen; + uint securityDescriptor; + StringBuilder sb; + + if (RegQueryInfoKey(key, out sb, ref lpcbClass, lpReserved, out lpcbSubKeys, out lpcbMaxKeyLen, out lpcbMaxClassLen, out lpcValues, out maxValueName, out maxValueLen, out securityDescriptor, ref lastModified) != 0) + { + return null; + } + + var result = ToDateTime(lastModified); + return result; + } + finally + { + if (key != UIntPtr.Zero) + { + RegCloseKey(key); + } + } + } + catch (Exception) + { + return null; + } + } } - New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$ProgId\shell\open\command" -Name "(Default)" -PropertyType String -Value "`"$ProgramPath`" `"%1`"" -Force +} +'@ - function Set-FTA + if (-not('RegistryUtils.Action' -as [type])) { - [CmdletBinding()] - param + Add-Type -TypeDefinition $RegistryUtils + } + + function Set-Icon + { + Param ( - [Parameter(Mandatory = $true)] - [String] - $ProgId, + [Parameter( + Mandatory = $true, + Position = 0 - [Parameter(Mandatory = $true)] + )] [String] - $Extension, + $ProgId, + [Parameter( + Mandatory = $true, + Position = 1 + )] [String] $Icon ) - function local:Set-Icon + if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\$ProgId\DefaultIcon")) { - param - ( - [Parameter( - Position = 0, - Mandatory = $true - )] - [String] - $ProgId, - - [Parameter( - Position = 1, - Mandatory = $true - )] - [String] - $Icon - ) + New-Item -Path "HKCU:\SOFTWARE\Classes\$ProgId\DefaultIcon" -Force + } + New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$ProgId\DefaultIcon" -Name "(default)" -PropertyType String -Value $Icon -Force + } + + function Remove-UserChoiceKey + { + Param + ( + [Parameter( + Mandatory = $true, + Position = 0 + )] + [string] + $SubKey + ) + + [RegistryUtils.Action]::DeleteKey([Microsoft.Win32.RegistryHive]::CurrentUser,$SubKey) + } + + function Set-UserAccessKey + { + Param + ( + [Parameter( + Mandatory = $true, + Position = 0 + )] + [string] + $SubKey + ) + + $OpenSubKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey($SubKey,'ReadWriteSubTree','TakeOwnership') + + $Acl = [System.Security.AccessControl.RegistrySecurity]::new() + $UserSID = (Get-CimInstance -ClassName Win32_UserAccount | Where-Object -FilterScript {$_.Name -eq $env:USERNAME}).SID + $Acl.SetSecurityDescriptorSddlForm("O:$UserSID`G:$UserSID`D:AI(D;;DC;;;$UserSID)") + $OpenSubKey.SetAccessControl($Acl) + $OpenSubKey.Close() + } + + function Write-ExtensionKeys + { + Param + ( + [Parameter( + Mandatory = $true, + Position = 0 + )] + [string] + $ProgId, - if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\$ProgId\DefaultIcon")) + [Parameter( + Mandatory = $true, + Position = 1 + )] + [String] + $Extension + ) + + $OrigProgID = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Classes\$Extension" -Name "(default)" -ErrorAction Ignore)."(default)" + + # If ProgId doesn't exist set the specified ProgId for the extansions + if (-not $OrigProgID) + { + if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\$Extension")) { - New-Item -Path "HKCU:\SOFTWARE\Classes\$ProgId\DefaultIcon" -Force + New-Item -Path "HKCU:\SOFTWARE\Classes\$Extension" -Force } - New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$ProgId\DefaultIcon" -Name "(Default)" -PropertyType String -Value $Icon -Force + New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$Extension" -Name "(default)" -PropertyType String -Value $ProgId -Force } - function local:Write-ExtensionKeys + # Set the specified ProgId в варианты возможных для назначения + if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids")) { - param - ( - [Parameter( - Position = 0, - Mandatory = $true - )] - [String] - $ProgId, - - [Parameter( - Position = 1, - Mandatory = $true - )] - [String] - $Extension, - - [Parameter( - Position = 2, - Mandatory = $true - )] - [String] - $ProgHash - ) + New-Item -Path "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids" -Force + } + New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids" -Name $ProgId -PropertyType None -Value ([byte[]]@()) -Force - function local:Remove-UserChoiceKey + # Set the system ProgId to the extension parameters for the File Explorer to the possible options for the assignment, and if absent set the specified ProgId + if ($OrigProgID) + { + if (-not (Test-Path -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\OpenWithProgids")) + { + New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\OpenWithProgids" -Force + } + New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\OpenWithProgids" -Name $OrigProgID -PropertyType None -Value ([byte[]]@()) -Force + } + else + { + if (-not (Test-Path -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\OpenWithProgids")) { - param - ( - [Parameter( - Position = 0, - Mandatory = $true - )] - [String] - $Key - ) + New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\OpenWithProgids" -Force + } + New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\OpenWithProgids" -Name $ProgID -PropertyType None -Value ([byte[]]@()) -Force + } - $Signature = @{ - Namespace = "Registry" - Name = "Utils" - Language = "CSharp" - MemberDefinition = @" -[DllImport("advapi32.dll", SetLastError = true)] -private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult); + # Removing the UserChoice key + Remove-UserChoiceKey -SubKey "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -[DllImport("advapi32.dll", SetLastError=true, CharSet = CharSet.Unicode)] -private static extern uint RegDeleteKey(UIntPtr hKey, string subKey); + # Setting parameters in UserChoice. The key is being autocreated + if (-not (Test-Path -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice")) + { + New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -Force + } + New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -Name ProgId -PropertyType String -Value $ProgID -Force -public static void DeleteKey(string key) -{ - UIntPtr hKey = UIntPtr.Zero; - RegOpenKeyEx((UIntPtr)0x80000001u, key, 0, 0x20019, out hKey); - RegDeleteKey((UIntPtr)0x80000001u, key); -} -"@ - } + # Getting a hash based on the time of the section's last modification. After creating and setting the first parameter + $ProgHash = Get-Hash -ProgId $ProgId -Extension $Extension -SubKey "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" - if (-not ("Registry.Utils" -as [type])) - { - Add-Type @Signature - } + if (-not (Test-Path -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice")) + { + New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -Force + } + New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -Name Hash -PropertyType String -Value $ProgHash -Force - [Registry.Utils]::DeleteKey($Key) - } + # Setting a ban on changing the UserChoice section + Set-UserAccessKey -SubKey "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" + } - Remove-UserChoiceKey -Key "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" + function Write-AdditionalKeys + { + Param + ( + [Parameter( + Mandatory = $true, + Position = 0 + )] + [string] + $ProgId, - if (-not (Test-Path -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice")) + [Parameter( + Mandatory = $true, + Position = 1 + )] + [string] + $Extension + ) + + # If there is the system extension ProgId, write it to the already configured by default + if ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Classes\$Extension" -Name "(default)" -ErrorAction Ignore)."(default)") + { + if (-not (Test-Path -Path Registry::HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\FileAssociations\ProgIds)) { - New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -Force + New-Item -Path Registry::HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\FileAssociations\ProgIds -Force } - New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -Name Hash -PropertyType String -Value $ProgHash -Force - New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice" -Name ProgId -PropertyType String -Value $ProgId -Force + New-ItemProperty -Path Registry::HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\FileAssociations\ProgIds -Name "_$Extension" -PropertyType DWord -Value 1 -Force } - function local:Get-HexDateTime + # Save possible ProgIds with extension + if (-not (Test-Path -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ApplicationAssociationToasts")) { - [OutputType([string])] + New-Item -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ApplicationAssociationToasts" -Force + } + New-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ApplicationAssociationToasts" -Name "$ProgId`_$Extension" -PropertyType String -Value 0 -Force - $now = [DateTime]::Now - $dateTime = [DateTime]::New($now.Year, $now.Month, $now.Day, $now.Hour, $now.Minute, 0) - $fileTime = $dateTime.ToFileTime() - $hi = ($fileTime -shr 32) - $low = ($fileTime -band 0xFFFFFFFFL) - $dateTimeHex = ($hi.ToString("X8") + $low.ToString("X8")).ToLower() + # Setting 'NoOpenWith' for all registered the extension ProgIDs + [psobject]$OpenSubkey = Get-Item -Path "Registry::HKEY_CLASSES_ROOT\$Extension\OpenWithProgids" -ErrorAction Ignore | Select-Object -ExpandProperty Property - return $dateTimeHex + if ($OpenSubkey) + { + foreach ($AppxProgID in ($OpenSubkey | Where-Object -FilterScript {$_ -match "AppX"})) + { + # If an app is installed + if ((Get-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$AppxProgID\Shell\open" -Name PackageId).PackageId) + { + New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$AppxProgID" -Name NoOpenWith -PropertyType String -Value "" -Force + } + } } - function Get-Hash + $picture = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\KindMap" -Name $Extension -ErrorAction Ignore).$Extension + $PBrush = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Classes\PBrush\CLSID" -Name "(default)" + + if (($picture -eq "picture") -and $PBrush) { - [CmdletBinding()] - param - ( - [Parameter( - Position = 0, - Mandatory = $true - )] - [string] - $BaseInfo - ) + New-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\ApplicationAssociationToasts" -Name "PBrush_$Extension" -PropertyType DWord -Value 0 -Force + } + } - function local:Get-ShiftRight - { - [CmdletBinding()] - param - ( - [Parameter( - Position = 0, - Mandatory = $true - )] - [long] - $iValue, - - [Parameter( - Position = 1, - Mandatory = $true - )] - [int] - $iCount - ) - - if ($iValue -band 0x80000000) - { - return (($iValue -shr $iCount) -bxor 0xFFFF0000) - } - else - { - return ($iValue -shr $iCount) - } + function Get-Hash + { + [CmdletBinding()] + [OutputType([string])] + Param + ( + [Parameter( + Mandatory = $true, + Position = 0 + )] + [string] + $ProgId, + + [Parameter( + Mandatory = $true, + Position = 1 + )] + [string] $Extension, + + [Parameter( + Mandatory = $true, + Position = 2 + )] + [string] + $SubKey + ) + + $PatentHash = @' +using System; + +namespace FileAssoc +{ + public static class PatentHash + { + public static uint[] WordSwap(byte[] a, int sz, byte[] md5) + { + if (sz < 2 || (sz & 1) == 1) { + throw new ArgumentException(String.Format("Invalid input size: {0}", sz), "sz"); } - function local:Get-Long - { - [CmdletBinding()] - param - ( - [Parameter( - Position = 0, - Mandatory = $true - )] - [byte[]] - $Bytes, - - [Parameter(Position = 1)] - [int] - $Index = 0 - ) - - return ([BitConverter]::ToInt32($Bytes, $Index)) - } - - function local:Convert-Int32 - { - param - ( - [Parameter( - Position = 0, - Mandatory = $true - )] - $Value - ) - - [byte[]]$bytes = [BitConverter]::GetBytes($Value) - return [BitConverter]::ToInt32($bytes, 0) - } - - [byte[]]$bytesBaseInfo = [System.Text.Encoding]::Unicode.GetBytes($baseInfo) - $bytesBaseInfo += 0x00, 0x00 - - $MD5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider - [byte[]]$bytesMD5 = $MD5.ComputeHash($bytesBaseInfo) - - $lengthBase = ($baseInfo.Length * 2) + 2 - $length = (($lengthBase -band 4) -le 1) + (Get-ShiftRight -iValue $lengthBase -iCount 2) - 1 - $base64Hash = "" - - if ($length -gt 1) - { - $Map = @{ - PDATA = 0 - CACHE = 0 - COUNTER = 0 - INDEX = 0 - MD51 = 0 - MD52 = 0 - OUTHASH1 = 0 - OUTHASH2 = 0 - R0 = 0 - R1 = @(0, 0) - R2 = @(0, 0) - R3 = 0 - R4 = @(0, 0) - R5 = @(0, 0) - R6 = @(0, 0) - R7 = @(0, 0) - } + unchecked { + uint o1 = 0; + uint o2 = 0; + int ta = 0; + int ts = sz; + int ti = ((sz - 2) >> 1) + 1; - $Map.CACHE = 0 - $Map.OUTHASH1 = 0 - $Map.PDATA = 0 - $Map.MD51 = (((Get-Long -Bytes $bytesMD5) -bor 1) + 0x69FB0000L) - $Map.MD52 = ((Get-Long -Bytes $bytesMD5 -Index 4) -bor 1) + 0x13DB0000L - $Map.INDEX = Get-ShiftRight -iValue ($length - 2) -iCount 1 - $Map.COUNTER = $Map.INDEX + 1 + uint c0 = (BitConverter.ToUInt32(md5, 0) | 1) + 0x69FB0000; + uint c1 = (BitConverter.ToUInt32(md5, 4) | 1) + 0x13DB0000; - while ($Map.COUNTER) - { - $Map.R0 = Convert-Int32 -Value ((Get-Long -Bytes $bytesBaseInfo -Index $Map.PDATA) + [long]$Map.OUTHASH1) - $Map.R1[0] = Convert-Int32 -Value (Get-Long -Bytes $bytesBaseInfo -Index ($Map.PDATA + 4)) - $Map.PDATA = $Map.PDATA + 8 - $Map.R2[0] = Convert-Int32 -Value (($Map.R0 * ([long]$Map.MD51)) - (0x10FA9605L * ((Get-ShiftRight -iValue $Map.R0 -iCount 16)))) - $Map.R2[1] = Convert-Int32 -Value ((0x79F8A395L * ([long]$Map.R2[0])) + (0x689B6B9FL * (Get-ShiftRight -iValue $Map.R2[0] -iCount 16))) - $Map.R3 = Convert-Int32 -Value ((0xEA970001L * $Map.R2[1]) - (0x3C101569L * (Get-ShiftRight -iValue $Map.R2[1] -iCount 16) )) - $Map.R4[0] = Convert-Int32 -Value ($Map.R3 + $Map.R1[0]) - $Map.R5[0] = Convert-Int32 -Value ($Map.CACHE + $Map.R3) - $Map.R6[0] = Convert-Int32 -Value (($Map.R4[0] * [long]$Map.MD52) - (0x3CE8EC25L * (Get-ShiftRight -iValue $Map.R4[0] -iCount 16))) - $Map.R6[1] = Convert-Int32 -Value ((0x59C3AF2DL * $Map.R6[0]) - (0x2232E0F1L * (Get-ShiftRight -iValue $Map.R6[0] -iCount 16))) - $Map.OUTHASH1 = Convert-Int32 -Value ((0x1EC90001L * $Map.R6[1]) + (0x35BD1EC9L * (Get-ShiftRight -iValue $Map.R6[1] -iCount 16))) - $Map.OUTHASH2 = Convert-Int32 -Value ([long]$Map.R5[0] + [long]$Map.OUTHASH1) - $Map.CACHE = ([long]$Map.OUTHASH2) - $Map.COUNTER = $Map.COUNTER - 1 + for (uint i = (uint)ti; i > 0; i--) { + uint n = BitConverter.ToUInt32(a, ta) + o1; + ta += 8; + ts -= 2; + + uint v1 = 0x79F8A395 * (n * c0 - 0x10FA9605 * (n >> 16)) + 0x689B6B9F * ((n * c0 - 0x10FA9605 * (n >> 16)) >> 16); + uint v2 = 0xEA970001 * v1 - 0x3C101569 * (v1 >> 16); + uint v3 = BitConverter.ToUInt32(a, ta - 4) + v2; + uint v4 = v3 * c1 - 0x3CE8EC25 * (v3 >> 16); + uint v5 = 0x59C3AF2D * v4 - 0x2232E0F1 * (v4 >> 16); + + o1 = 0x1EC90001 * v5 + 0x35BD1EC9 * (v5 >> 16); + o2 += o1 + v2; } - [byte[]] $outHash = @(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) - [byte[]] $buffer = [BitConverter]::GetBytes($Map.OUTHASH1) - $buffer.CopyTo($outHash, 0) - $buffer = [BitConverter]::GetBytes($Map.OUTHASH2) - $buffer.CopyTo($outHash, 4) - - $Map = @{ - PDATA = 0 - CACHE = 0 - COUNTER = 0 - INDEX = 0 - MD51 = 0 - MD52 = 0 - OUTHASH1 = 0 - OUTHASH2 = 0 - R0 = 0 - R1 = @(0, 0) - R2 = @(0, 0) - R3 = 0 - R4 = @(0, 0) - R5 = @(0, 0) - R6 = @(0, 0) - R7 = @(0, 0) + if (ts == 1) { + uint n = BitConverter.ToUInt32(a, ta) + o1; + + uint v1 = n * c0 - 0x10FA9605 * (n >> 16); + uint v2 = 0xEA970001 * (0x79F8A395 * v1 + 0x689B6B9F * (v1 >> 16)) - 0x3C101569 * ((0x79F8A395 * v1 + 0x689B6B9F * (v1 >> 16)) >> 16); + uint v3 = v2 * c1 - 0x3CE8EC25 * (v2 >> 16); + + o1 = 0x1EC90001 * (0x59C3AF2D * v3 - 0x2232E0F1 * (v3 >> 16)) + 0x35BD1EC9 * ((0x59C3AF2D * v3 - 0x2232E0F1 * (v3 >> 16)) >> 16); + o2 += o1 + v2; } - $Map.CACHE = 0 - $Map.OUTHASH1 = 0 - $Map.PDATA = 0 - $Map.MD51 = ((Get-Long -Bytes $bytesMD5) -bor 1) - $Map.MD52 = ((Get-Long -Bytes $bytesMD5 4) -bor 1) - $Map.INDEX = Get-ShiftRight -iValue ($length - 2) -iCount 1 - $Map.COUNTER = $Map.INDEX + 1 + uint[] ret = new uint[2]; + ret[0] = o1; + ret[1] = o2; + return ret; + } + } - while ($Map.COUNTER) - { - $Map.R0 = Convert-Int32 -Value ((Get-Long -Bytes $bytesBaseInfo -Index $Map.PDATA) + ([long]$Map.OUTHASH1)) - $Map.PDATA = $Map.PDATA + 8 - $Map.R1[0] = Convert-Int32 -Value ($Map.R0 * [long]$Map.MD51) - $Map.R1[1] = Convert-Int32 -Value ((0xB1110000L * $Map.R1[0]) - (0x30674EEFL * (Get-ShiftRight -iValue $Map.R1[0] -iCount 16))) - $Map.R2[0] = Convert-Int32 -Value ((0x5B9F0000L * $Map.R1[1]) - (0x78F7A461L * (Get-ShiftRight -iValue $Map.R1[1] -iCount 16))) - $Map.R2[1] = Convert-Int32 -Value ((0x12CEB96DL * (Get-ShiftRight -iValue $Map.R2[0] 16)) - (0x46930000L * $Map.R2[0])) - $Map.R3 = Convert-Int32 -Value ((0x1D830000L * $Map.R2[1]) + (0x257E1D83L * (Get-ShiftRight -iValue $Map.R2[1] -iCount 16))) - $Map.R4[0] = Convert-Int32 -Value ([long]$Map.MD52 * ([long]$Map.R3 + (Get-Long -Bytes $bytesBaseInfo -Index ($Map.PDATA - 4)))) - $Map.R4[1] = Convert-Int32 -Value ((0x16F50000L * $Map.R4[0]) - (0x5D8BE90BL * (Get-ShiftRight -iValue $Map.R4[0] -iCount 16))) - $Map.R5[0] = Convert-Int32 -Value ((0x96FF0000L * $Map.R4[1]) - (0x2C7C6901L * (Get-ShiftRight -iValue $Map.R4[1] -iCount 16))) - $Map.R5[1] = Convert-Int32 -Value ((0x2B890000L * $Map.R5[0]) + (0x7C932B89L * (Get-ShiftRight -iValue $Map.R5[0] -iCount 16))) - $Map.OUTHASH1 = Convert-Int32 -Value ((0x9F690000L * $Map.R5[1]) - (0x405B6097L * (Get-ShiftRight -iValue ($Map.R5[1]) -iCount 16))) - $Map.OUTHASH2 = Convert-Int32 -Value ([long]$Map.OUTHASH1 + $Map.CACHE + $Map.R3) - $Map.CACHE = ([long]$Map.OUTHASH2) - $Map.COUNTER = $Map.COUNTER - 1 + public static uint[] Reversible(byte[] a, int sz, byte[] md5) + { + if (sz < 2 || (sz & 1) == 1) { + throw new ArgumentException(String.Format("Invalid input size: {0}", sz), "sz"); + } + + unchecked { + uint o1 = 0; + uint o2 = 0; + int ta = 0; + int ts = sz; + int ti = ((sz - 2) >> 1) + 1; + + uint c0 = BitConverter.ToUInt32(md5, 0) | 1; + uint c1 = BitConverter.ToUInt32(md5, 4) | 1; + + for (uint i = (uint)ti; i > 0; i--) { + uint n = (BitConverter.ToUInt32(a, ta) + o1) * c0; + n = 0xB1110000 * n - 0x30674EEF * (n >> 16); + ta += 8; + ts -= 2; + + uint v1 = 0x5B9F0000 * n - 0x78F7A461 * (n >> 16); + uint v2 = 0x1D830000 * (0x12CEB96D * (v1 >> 16) - 0x46930000 * v1) + 0x257E1D83 * ((0x12CEB96D * (v1 >> 16) - 0x46930000 * v1) >> 16); + uint v3 = BitConverter.ToUInt32(a, ta - 4) + v2; + + uint v4 = 0x16F50000 * c1 * v3 - 0x5D8BE90B * (c1 * v3 >> 16); + uint v5 = 0x2B890000 * (0x96FF0000 * v4 - 0x2C7C6901 * (v4 >> 16)) + 0x7C932B89 * ((0x96FF0000 * v4 - 0x2C7C6901 * (v4 >> 16)) >> 16); + + o1 = 0x9F690000 * v5 - 0x405B6097 * (v5 >> 16); + o2 += o1 + v2; } - $buffer = [BitConverter]::GetBytes($Map.OUTHASH1) - $buffer.CopyTo($outHash, 8) - $buffer = [BitConverter]::GetBytes($Map.OUTHASH2) - $buffer.CopyTo($outHash, 12) + if (ts == 1) { + uint n = BitConverter.ToUInt32(a, ta) + o1; - [byte[]]$outHashBase = @(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) - $hashValue1 = ((Get-Long -Bytes $outHash -Index 8) -bxor (Get-Long -Bytes $outHash)) - $hashValue2 = ((Get-Long -Bytes $outHash 12) -bxor (Get-Long -Bytes $outHash -Index 4)) + uint v1 = 0xB1110000 * c0 * n - 0x30674EEF * ((c0 * n) >> 16); + uint v2 = 0x5B9F0000 * v1 - 0x78F7A461 * (v1 >> 16); + uint v3 = 0x1D830000 * (0x12CEB96D * (v2 >> 16) - 0x46930000 * v2) + 0x257E1D83 * ((0x12CEB96D * (v2 >> 16) - 0x46930000 * v2) >> 16); + uint v4 = 0x16F50000 * c1 * v3 - 0x5D8BE90B * ((c1 * v3) >> 16); + uint v5 = 0x96FF0000 * v4 - 0x2C7C6901 * (v4 >> 16); - $buffer = [BitConverter]::GetBytes($hashValue1) - $buffer.CopyTo($outHashBase, 0) - $buffer = [BitConverter]::GetBytes($hashValue2) - $buffer.CopyTo($outHashBase, 4) - $base64Hash = [Convert]::ToBase64String($outHashBase) + o1 = 0x9F690000 * (0x2B890000 * v5 + 0x7C932B89 * (v5 >> 16)) - 0x405B6097 * ((0x2B890000 * v5 + 0x7C932B89 * (v5 >> 16)) >> 16); + o2 += o1 + v2; + } + + uint[] ret = new uint[2]; + ret[0] = o1; + ret[1] = o2; + return ret; } + } + + public static long MakeLong(uint left, uint right) { + return (long)left << 32 | (long)right; + } + } +} +'@ + + if ( -not ('FileAssoc.PatentHash' -as [type])) + { + Add-Type -TypeDefinition $PatentHash + } + + function Get-KeyLastWriteTime ($SubKey) + { + $LM = [RegistryUtils.Action]::GetLastModified([Microsoft.Win32.RegistryHive]::CurrentUser,$SubKey) + $FT = ([DateTime]::New($LM.Year, $LM.Month, $LM.Day, $LM.Hour, $LM.Minute, 0, $LM.Kind)).ToFileTime() - return $base64Hash + return [string]::Format("{0:x8}{1:x8}", $FT -shr 32, $FT -band [uint32]::MaxValue) } - # Get current user SID - $userSid = (Get-CimInstance -ClassName Win32_UserAccount | Where-Object -FilterScript {$_.Name -eq $env:USERNAME}).SID - # Secret static string stored in %SystemRoot%\SysWOW64\shell32.dll - $userExperience = "User Choice set via Windows User Experience {D18B6DD5-6124-4341-9318-804003BAFA0B}" - $userDateTime = Get-HexDateTime - $baseInfo = "$Extension$userSid$ProgId$userDateTime$userExperience".ToLower() - $ProgHash = Get-Hash -BaseInfo $baseInfo + function Get-DataArray + { + [OutputType([array])] + + $userExperience = "User Choice set via Windows User Experience {D18B6DD5-6124-4341-9318-804003BAFA0B}" + $userSid = (Get-CimInstance -ClassName Win32_UserAccount | Where-Object -FilterScript {$_.Name -eq $env:USERNAME}).SID + $KeyLastWriteTime = Get-KeyLastWriteTime -SubKey $SubKey + $baseInfo = ("{0}{1}{2}{3}{4}" -f $Extension, $userSid, $ProgId, $KeyLastWriteTime, $userExperience).ToLowerInvariant() + $StringToUTF16LEArray = [System.Collections.ArrayList]@([System.Text.Encoding]::Unicode.GetBytes($baseInfo)) + $StringToUTF16LEArray += (0,0) + + return $StringToUTF16LEArray + } - # Handle Extension - Write-ExtensionKeys -ProgId $ProgId -Extension $Extension -ProgHash $ProgHash + function Get-PatentHash + { + [OutputType([string])] + param + ( + [Parameter(Mandatory = $true)] + [byte[]] + $A, + + [Parameter(Mandatory = $true)] + [byte[]] + $MD5 + ) + + $Size = $A.Count + $ShiftedSize = ($Size -shr 2) - ($Size -shr 2 -band 1) * 1 + + [uint32[]]$A1 = [FileAssoc.PatentHash]::WordSwap($A, [int]$ShiftedSize, $MD5) + [uint32[]]$A2 = [FileAssoc.PatentHash]::Reversible($A, [int]$ShiftedSize, $MD5) + + $Ret = [FileAssoc.PatentHash]::MakeLong($A1[1] -bxor $A2[1], $A1[0] -bxor $A2[0]) + + return [System.Convert]::ToBase64String([System.BitConverter]::GetBytes([Int64]$Ret)) + } + + $DataArray = Get-DataArray + $DataMD5 = [System.Security.Cryptography.HashAlgorithm]::Create("MD5").ComputeHash($DataArray) + $Hash = Get-PatentHash -A $DataArray -MD5 $DataMD5 + + return $Hash + } + #endregion functions + + if ($ProgramPath) + { + if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\$ProgId\shell\open\command")) + { + New-Item -Path "HKCU:\SOFTWARE\Classes\$ProgId\shell\open\command" -Force + } + New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\$ProgId\shell\open\command" -Name "(Default)" -PropertyType String -Value "`"$ProgramPath`" `"%1`"" -Force - if ($Icon) + $FileNameEXE = (Get-Item -Path $ProgramPath).Name + if (-not (Test-Path -Path "HKCU:\SOFTWARE\Classes\Applications\$FileNameEXE\shell\open\command")) { - Set-Icon -ProgId $ProgId -Icon $Icon + New-Item -Path "HKCU:\SOFTWARE\Classes\Applications\$FileNameEXE\shell\open\command" -Force } + New-ItemProperty -Path "HKCU:\SOFTWARE\Classes\Applications\$FileNameEXE\shell\open\command" -Name "(Default)" -PropertyType String -Value "`"$ProgramPath`" `"%1`"" -Force + } + + if ($Icon) + { + Set-Icon -ProgId $ProgId -Icon $Icon } - Set-FTA -ProgId $ProgId -Extension $Extension -Icon $Icon + Write-Verbose -Message $Localization.Patient -Verbose + + # Setting additional parameters to comply with the requirements before configuring the extension + Write-AdditionalKeys -ProgId $ProgId -Extension $Extension + + # If the file extension specified configure the extension + Write-ExtensionKeys -ProgId $ProgId -Extension $Extension } #endregion System @@ -7263,12 +7470,11 @@ function EnableWSL2 { Write-Verbose -Message $Localization.WSLUpdateDownloading -Verbose - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - $DownloadsFolder = Get-ItemPropertyValue -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name "{374DE290-123F-4565-9164-39C4925E467B}" $Parameters = @{ Uri = "https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi" OutFile = "$DownloadsFolder\wsl_update_x64.msi" + SslProtocol = "Tls12" Verbose = [switch]::Present } Invoke-WebRequest @Parameters @@ -7672,7 +7878,7 @@ public static string GetString(uint strId) $Parameter = $Parameters | Where-Object -FilterScript {$_.Name -eq $Tile} $Group = $XML.LayoutModificationTemplate.DefaultLayoutOverride.StartLayoutCollection.StartLayout.Group | Where-Object -FilterScript {$_.Name -eq "Sophia Script"} - # If "Sophia Script" group exists in Start + # If the "Sophia Script" group exists in Start if ($Group) { $DesktopApplicationID = ($Parameters | Where-Object -FilterScript {$_.Name -eq $Tile}).AppID @@ -7749,10 +7955,14 @@ public static string GetString(uint strId) .SYNOPSIS Uninstall UWP apps - .DESCRIPTION - Add UWP apps packages names to the $UncheckedAppXPackages array list by retrieving their packages names using the following command: - (Get-AppxPackage -PackageTypeFilter Bundle -AllUsers).Name - App packages will not be installed for new users if the "Uninstall for All Users" box is checked + .PARAMETER ForAllUsers + Set the "For All Users" checkbox checked by default + + .EXAMPLE + UninstallUWPApps + + .EXAMPLE + UninstallUWPApps -ForAllUsers .NOTES A pop-up dialog box enables the user to select packages @@ -7760,13 +7970,33 @@ public static string GetString(uint strId) #> function UninstallUWPApps { + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $false)] + [switch] + $ForAllUsers + ) + + <# + .SYNOPSIS + Add the classes from the WinRT.Runtime.dll and Microsoft.Windows.SDK.NET.dll libraries to the current session to be able to load localized UWP apps names + + .LINKS + https://github.com/microsoft/CsWinRT + https://www.nuget.org/packages/Microsoft.Windows.SDK.NET.Ref + + .NOTES + CsWinRT v1.1.3 + Microsoft.Windows.SDK.NET 10.0.19041.14 + #> + Add-Type -AssemblyName "$PSScriptRoot\Libraries\WinRT.Runtime.dll" + Add-Type -AssemblyName "$PSScriptRoot\Libraries\Microsoft.Windows.SDK.NET.dll" + Add-Type -AssemblyName PresentationCore, PresentationFramework #region Variables - # ArrayList containing the UWP apps to remove - $AppxPackages = New-Object -TypeName System.Collections.ArrayList($null) - - # List of UWP apps that won't be recommended for removal + # The following UWP apps will have their checkboxes unchecked $UncheckedAppxPackages = @( # AMD Radeon UWP panel # UWP-панель AMD Radeon @@ -7789,12 +8019,19 @@ function UninstallUWPApps # Фотографии и Видеоредактор "Microsoft.Windows.Photos", "Microsoft.Photos.MediaEngineDLC", - "Microsoft.HEVCVideoExtension" + + # HEVC Video Extensions from Device Manufacturer + # Расширения для видео HEVC от производителя устройства + "Microsoft.HEVCVideoExtension", # Calculator # Калькулятор "Microsoft.WindowsCalculator", + # Windows Camera + # Камера Windows + "Microsoft.WindowsCamera", + # Xbox Identity Provider # Поставщик удостоверений Xbox "Microsoft.XboxIdentityProvider", @@ -7843,7 +8080,6 @@ function UninstallUWPApps # Расширения для интернет-мультимедиа "Microsoft.WebMediaExtensions" ) - #endregion Variables #region XAML Markup # The section defines the design of the upcoming dialog box @@ -7852,24 +8088,37 @@ function UninstallUWPApps xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="Window" - MinHeight="450" MinWidth="400" + MinHeight="400" MinWidth="410" SizeToContent="Width" WindowStartupLocation="CenterScreen" TextOptions.TextFormattingMode="Display" SnapsToDevicePixels="True" - FontFamily="Segoe UI" FontSize="12" ShowInTaskbar="False"> + FontFamily="Candara" FontSize="16" ShowInTaskbar="True"> + + @@ -7881,19 +8130,23 @@ function UninstallUWPApps - + - - - + + + + + + + - - - -