diff --git a/.gitignore b/.gitignore index 215d85ed..4d77e17c 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,4 @@ Microsoft.PowerShell.ConsoleHost.dll microwin.log True test.ps1 +winutil.ps1 diff --git a/Compile.ps1 b/Compile.ps1 index 330c226a..2f568499 100644 --- a/Compile.ps1 +++ b/Compile.ps1 @@ -55,6 +55,9 @@ Get-ChildItem .\config | Where-Object {$psitem.extension -eq ".json"} | ForEach- $sync.configs.$($psitem.BaseName) = $json | convertfrom-json Write-output "`$sync.configs.$($psitem.BaseName) = '$json' `| convertfrom-json" | Out-File ./$scriptname -Append -Encoding ascii } +Get-ChildItem .\config | Where-Object {$PSItem.Extension -eq ".cfg"} | ForEach-Object { + Write-output "`$sync.configs.$($psitem.BaseName) = '$(Get-Content $PSItem.FullName)'" | Out-File ./$scriptname -Append -Encoding ascii +} $xaml = (Get-Content .\xaml\inputXML.xaml).replace("'","''") diff --git a/config/applications.json b/config/applications.json index 09d89ac1..9f69473b 100644 --- a/config/applications.json +++ b/config/applications.json @@ -735,6 +735,14 @@ "link": "https://desktop.github.com/", "winget": "Git.Git;GitHub.GitHubDesktop" }, + "WPFInstallgitkrakenclient": { + "category": "Development", + "choco": "gitkraken", + "content": "GitKraken Client", + "description": "GitKraken Client is a powerful visual Git client from Axosoft that works with ALL git repositories on any hosting environment.", + "link": "https://www.gitkraken.com/git-client", + "winget": "Axosoft.GitKraken" + }, "WPFInstallglaryutilities": { "category": "Utilities", "choco": "glaryutilities-free", @@ -743,6 +751,14 @@ "link": "https://www.glarysoft.com/glary-utilities/", "winget": "Glarysoft.GlaryUtilities" }, + "WPFInstallgodotengine": { + "category": "Development", + "choco": "godot", + "content": "Godot Engine", + "description": "Godot Engine is a free, open-source 2D and 3D game engine with a focus on usability and flexibility.", + "link": "https://godotengine.org/", + "winget": "GodotEngine.GodotEngine" + }, "WPFInstallgog": { "category": "Games", "choco": "goggalaxy", @@ -996,7 +1012,7 @@ "choco": "jellyfin-media-player", "content": "Jellyfin Media Player", "description": "Jellyfin Media Player is a client application for the Jellyfin media server, providing access to your media library.", - "link": "https://github.com/jellyfin/jellyfin-media-playerf", + "link": "https://github.com/jellyfin/jellyfin-media-player", "winget": "Jellyfin.JellyfinMediaPlayer" }, "WPFInstalljellyfinserver": { @@ -1170,8 +1186,8 @@ "WPFInstallmatrix": { "category": "Communications", "choco": "element-desktop", - "content": "Matrix", - "description": "Matrix is an open network for secure, decentralized communication with features like chat, VoIP, and collaboration tools.", + "content": "Element", + "description": "Element is a client for Matrix—an open network for secure, decentralized communication.", "link": "https://element.io/", "winget": "Element.Element" }, @@ -1239,6 +1255,46 @@ "link": "https://www.msi.com/Landing/afterburner", "winget": "Guru3D.Afterburner" }, + "WPFInstallBorderlessGaming": { + "category": "Utilities", + "choco": "na", + "content": "Borderless Gaming", + "description": "Play your favorite games in a borderless window; no more time consuming alt-tabs.", + "link": "https://github.com/Codeusa/Borderless-Gaming", + "winget": "Codeusa.BorderlessGaming" + }, + "WPFInstallEqualizerAPO": { + "category": "Multimedia Tools", + "choco": "equalizerapo", + "content": "Equalizer APO", + "description": "Equalizer APO is a parametric / graphic equalizer for Windows.", + "link": "https://sourceforge.net/projects/equalizerapo", + "winget": "na" + }, + "WPFInstallFreeFileSync": { + "category": "Utilities", + "choco": "freefilesync", + "content": "FreeFileSync", + "description": "Synchronize Files and Folders", + "link": "https://freefilesync.org", + "winget": "na" + }, + "WPFInstallCompactGUI": { + "category": "Utilities", + "choco": "compactgui", + "content": "Compact GUI", + "description": "Transparently compress active games and programs using Windows 10/11 APIs", + "link": "https://github.com/IridiumIO/CompactGUI", + "winget": "IridiumIO.CompactGUI" + }, + "WPFInstallExifCleaner": { + "category": "Utilities", + "choco": "na", + "content": "ExifCleaner", + "description": "Desktop app to clean metadata from images, videos, PDFs, and other files.", + "link": "https://github.com/szTheory/exifcleaner", + "winget": "szTheory.exifcleaner" + }, "WPFInstallmullvadbrowser": { "category": "Browsers", "choco": "na", @@ -1647,6 +1703,14 @@ "link": "https://bitsum.com/", "winget": "BitSum.ProcessLasso" }, + "WPFInstallspotify": { + "category": "Multimedia Tools", + "choco": "spotify", + "content": "Spotify", + "description": "Spotify is a digital music service that gives you access to millions of songs, podcasts, and videos from artists all over the world.", + "link": "https://www.spotify.com/", + "winget": "Spotify.Spotify" + }, "WPFInstallprocessmonitor": { "category": "Microsoft Tools", "choco": "procexp", @@ -2623,6 +2687,14 @@ "link": "https://www.smplayer.info", "winget": "SMPlayer.SMPlayer" }, + "WPFInstalglazewm": { + "category": "Utilities", + "choco": "na", + "content": "GlazeWM", + "description": "GlazeWM is a tiling window manager for Windows inspired by i3 and Polybar", + "link": "https://github.com/glzr-io/glazewm", + "winget": "glzr-io.glazewm" + }, "WPFInstallfancontrol": { "category": "Utilities", "choco": "na", @@ -2646,5 +2718,13 @@ "description": "The customization marketplace for Windows programs", "link": "https://windhawk.net", "winget": "RamenSoftware.Windhawk" + }, + "WPFInstallForceAutoHDR": { + "category": "Utilities", + "choco": "na", + "content": "GUI That Forces Auto HDR In Unsupported Games", + "description": "ForceAutoHDR simplifies the process of adding games to the AutoHDR list in the Windows Registry", + "link": "https://github.com/7gxycn08/ForceAutoHDR", + "winget": "ForceAutoHDR.7gxycn08" } } diff --git a/config/tweaks.json b/config/tweaks.json index 63e48bd3..e260bd3e 100644 --- a/config/tweaks.json +++ b/config/tweaks.json @@ -1926,27 +1926,6 @@ "Value": "1", "Type": "DWord" }, - { - "Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games", - "OriginalValue": "1", - "Name": "GPU Priority", - "Value": "8", - "Type": "DWord" - }, - { - "Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games", - "OriginalValue": "1", - "Name": "Priority", - "Value": "6", - "Type": "DWord" - }, - { - "Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games", - "OriginalValue": "High", - "Name": "Scheduling Category", - "Value": "High", - "Type": "String" - }, { "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\UserProfileEngagement", "OriginalValue": "1", diff --git a/functions/private/Get-WinUtilWingetLatest.ps1 b/functions/private/Get-WinUtilWingetLatest.ps1 index 5a18a536..f392cd17 100644 --- a/functions/private/Get-WinUtilWingetLatest.ps1 +++ b/functions/private/Get-WinUtilWingetLatest.ps1 @@ -5,14 +5,17 @@ function Get-WinUtilWingetLatest { .DESCRIPTION This function grabs the latest version of Winget and returns the download path to Install-WinUtilWinget for installation. #> - + # Invoke-WebRequest is notoriously slow when the byte progress is displayed. The following lines disable the progress bar and reset them at the end of the function + $PreviousProgressPreference = $ProgressPreference + $ProgressPreference = "silentlyContinue" Try{ # Grabs the latest release of Winget from the Github API for the install process. $response = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/Winget-cli/releases/latest" -Method Get -ErrorAction Stop $latestVersion = $response.tag_name #Stores version number of latest release. - $licenseWingetUrl = $response.assets.browser_download_url[0] #Index value for License file. + $licenseWingetUrl = $response.assets.browser_download_url | Where-Object {$_ -like "*License1.xml"} #Index value for License file. Write-Host "Latest Version:`t$($latestVersion)`n" - $assetUrl = $response.assets.browser_download_url[2] #Index value for download URL. + Write-Host "Downloading..." + $assetUrl = $response.assets.browser_download_url | Where-Object {$_ -like "*Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"} Invoke-WebRequest -Uri $licenseWingetUrl -OutFile $ENV:TEMP\License1.xml # The only pain is that the msixbundle for winget-cli is 246MB. In some situations this can take a bit, with slower connections. Invoke-WebRequest -Uri $assetUrl -OutFile $ENV:TEMP\Microsoft.DesktopAppInstaller.msixbundle @@ -20,4 +23,5 @@ function Get-WinUtilWingetLatest { Catch{ throw [WingetFailedInstall]::new('Failed to get latest Winget release and license') } + $ProgressPreference = $PreviousProgressPreference } diff --git a/functions/private/Install-WinUtilProgramWinget.ps1 b/functions/private/Install-WinUtilProgramWinget.ps1 index 4f840007..187bb37c 100644 --- a/functions/private/Install-WinUtilProgramWinget.ps1 +++ b/functions/private/Install-WinUtilProgramWinget.ps1 @@ -34,26 +34,41 @@ Function Install-WinUtilProgramWinget { # This is up to the individual package maintainers to enable these options. Aka. not as clean as Linux Package Managers. try { $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $Program --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru).ExitCode - if($status -ne 0){ - Write-Host "Attempt with User scope" - $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $Program --scope user --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru).ExitCode - if($status -ne 0){ - Write-Host "Attempt with Unelevated prompt" - $status = $(Start-Process -FilePath "powershell" -ArgumentList "-Command Start-Process winget -ArgumentList 'install --id $Program --silent --accept-source-agreements --accept-package-agreements' -Verb runAsUser" -Wait -PassThru).ExitCode - if($status -ne 0){ - Write-Host "Failed to install $Program." - } else { - Write-Host "$Program installed successfully with Unelevated prompt." - } - } else { - Write-Host "$Program installed successfully with User scope." - } - } else { + if($status -eq 0){ Write-Host "$Program installed successfully." + continue } - } catch { + Write-Host "Attempt with User scope" + $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $Program --scope user --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru).ExitCode + if($status -eq 0){ + Write-Host "$Program installed successfully with User scope." + continue + } + Write-Host "Attempt with User prompt" + $userChoice = [System.Windows.MessageBox]::Show("Do you want to attempt $Program installation with specific user credentials? Select 'Yes' to proceed or 'No' to skip.", "User Credential Prompt", [System.Windows.MessageBoxButton]::YesNo) + if ($userChoice -eq 'Yes') { + $getcreds = Get-Credential + $process = Start-Process -FilePath "winget" -ArgumentList "install --id $Program --silent --accept-source-agreements --accept-package-agreements" -Credential $getcreds -PassThru + Wait-Process -Id $process.Id + $status = $process.ExitCode + } else { + Write-Host "Skipping installation with specific user credentials." + } + if($status -eq 0){ + Write-Host "$Program installed successfully with User prompt." + continue + } + Write-Host "Attempting installation with Chocolatey as a fallback method" + Install-WinUtilChoco + $status = $(Start-Process -FilePath "choco" -ArgumentList "install $Program -y" -Wait -PassThru).ExitCode + if($status -eq 0){ + Write-Host "$Program installed successfully using Chocolatey." + continue + } + Write-Host "Failed to install $Program. You need to install it manually... Sorry!" + } catch { Write-Host "Failed to install $Program due to an error: $_" - } + } } if($manage -eq "Uninstalling"){ # Uninstall package via ID using winget directly. diff --git a/functions/private/Install-WinUtilWinget.ps1 b/functions/private/Install-WinUtilWinget.ps1 index 093a5c35..601d3c30 100644 --- a/functions/private/Install-WinUtilWinget.ps1 +++ b/functions/private/Install-WinUtilWinget.ps1 @@ -53,6 +53,8 @@ function Install-WinUtilWinget { Write-Host "Failure detected while installing via GitHub method. Continuing with Chocolatey method as fallback." -ForegroundColor Red # In case install fails via GitHub method. Try { + # Install Choco if not already present + Install-WinUtilChoco Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install winget-cli" Write-Host "Winget Installed" -ForegroundColor Green Write-Output "Refreshing Environment Variables...`n" diff --git a/functions/public/Invoke-WPFFixesWinget.ps1 b/functions/public/Invoke-WPFFixesWinget.ps1 index 5dd53a6b..96b5bb7f 100644 --- a/functions/public/Invoke-WPFFixesWinget.ps1 +++ b/functions/public/Invoke-WPFFixesWinget.ps1 @@ -7,7 +7,8 @@ function Invoke-WPFFixesWinget { .DESCRIPTION BravoNorris for the fantastic idea of a button to reinstall winget #> - + # Install Choco if not already present + Install-WinUtilChoco Start-Process -FilePath "choco" -ArgumentList "install winget -y --force" -NoNewWindow -Wait } \ No newline at end of file diff --git a/functions/public/Invoke-WPFGetIso.ps1 b/functions/public/Invoke-WPFGetIso.ps1 index 1b448a4f..483c494a 100644 --- a/functions/public/Invoke-WPFGetIso.ps1 +++ b/functions/public/Invoke-WPFGetIso.ps1 @@ -41,6 +41,8 @@ function Invoke-WPFGetIso { # you consent to downloading it, no need to show extra dialogs [System.Windows.MessageBox]::Show("oscdimge.exe is not found on the system, winutil will now attempt do download and install it using choco. This might take a long time.") # the step below needs choco to download oscdimg + # Install Choco if not already present + Install-WinUtilChoco $chocoFound = [bool] (Get-Command -ErrorAction Ignore -Type Application choco) Write-Host "choco on system: $chocoFound" if (!$chocoFound) diff --git a/functions/public/Invoke-WPFMicrowin.ps1 b/functions/public/Invoke-WPFMicrowin.ps1 index 89d15872..564a836a 100644 --- a/functions/public/Invoke-WPFMicrowin.ps1 +++ b/functions/public/Invoke-WPFMicrowin.ps1 @@ -53,6 +53,7 @@ public class PowerManagement { $keepEdge = $sync.WPFMicrowinKeepEdge.IsChecked $copyToUSB = $sync.WPFMicrowinCopyToUsb.IsChecked $injectDrivers = $sync.MicrowinInjectDrivers.IsChecked + $importDrivers = $sync.MicrowinImportDrivers.IsChecked $mountDir = $sync.MicrowinMountDir.Text $scratchDir = $sync.MicrowinScratchDir.Text @@ -111,13 +112,54 @@ public class PowerManagement { return } + if ($importDrivers) + { + Write-Host "Exporting drivers from active installation..." + if (Test-Path "$env:TEMP\DRV_EXPORT") + { + Remove-Item "$env:TEMP\DRV_EXPORT" -Recurse -Force + } + if (($injectDrivers -and (Test-Path $sync.MicrowinDriverLocation.Text))) + { + Write-Host "Using specified driver source..." + dism /english /online /export-driver /destination="$($sync.MicrowinDriverLocation.Text)" | Out-Host + if ($?) + { + # Don't add exported drivers yet, that is run later + Write-Host "Drivers have been exported successfully." + } + else + { + Write-Host "Failed to export drivers." + } + } + else + { + New-Item -Path "$env:TEMP\DRV_EXPORT" -ItemType Directory -Force + dism /english /online /export-driver /destination="$env:TEMP\DRV_EXPORT" | Out-Host + if ($?) + { + Write-Host "Adding exported drivers..." + dism /english /image="$scratchDir" /add-driver /driver="$env:TEMP\DRV_EXPORT" /recurse | Out-Host + } + else + { + Write-Host "Failed to export drivers. Continuing without importing them..." + } + if (Test-Path "$env:TEMP\DRV_EXPORT") + { + Remove-Item "$env:TEMP\DRV_EXPORT" -Recurse -Force + } + } + } + if ($injectDrivers) { $driverPath = $sync.MicrowinDriverLocation.Text if (Test-Path $driverPath) { Write-Host "Adding Windows Drivers image($scratchDir) drivers($driverPath) " - Add-WindowsDriver -Path "$scratchDir" -Recurse -Driver "$driverPath" + dism /English /image:$scratchDir /add-driver /driver:$driverPath /recurse | Out-Host } else { @@ -335,7 +377,7 @@ public class PowerManagement { if (Test-Path $driverPath) { Write-Host "Adding Windows Drivers image($scratchDir) drivers($driverPath) " - Add-WindowsDriver -Path "$scratchDir" -Driver "$driverPath" -Recurse + dism /English /image:$scratchDir /add-driver /driver:$driverPath /recurse | Out-Host } else { diff --git a/functions/public/Invoke-WPFOOSU b/functions/public/Invoke-WPFOOSU index d30ea3a8..d244acf2 100644 --- a/functions/public/Invoke-WPFOOSU +++ b/functions/public/Invoke-WPFOOSU @@ -27,14 +27,12 @@ function Invoke-WPFOOSU { Start-Process $OOSU_filepath } "recommended"{ - $oosu_config = "$ENV:temp\ooshutup10_recommended.cfg" - Invoke-WebRequest -Uri "https://raw.githubusercontent.com/ChrisTitusTech/winutil/main/config/ooshutup10_recommended.cfg" -OutFile $oosu_config + New-Item -Path $ENV:temp\ooshutup10_recommended.cfg -ItemType File -Value $sync.configs.ooshutup10_recommended -Force Write-Host "Applying recommended OO Shutup 10 Policies" Start-Process $OOSU_filepath -ArgumentList "$oosu_config /quiet" -Wait } "undo"{ - $oosu_config = "$ENV:temp\ooshutup10_factory.cfg" - Invoke-WebRequest -Uri "https://raw.githubusercontent.com/ChrisTitusTech/winutil/main/config/ooshutup10_factory.cfg" -OutFile $oosu_config + New-Item -Path $ENV:temp\ooshutup10_factory.cfg -ItemType File -Value $sync.configs.ooshutup10_factory -Force Write-Host "Resetting all OO Shutup 10 Policies" Start-Process $OOSU_filepath -ArgumentList "$oosu_config /quiet" -Wait } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 38007969..5507d641 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -145,8 +145,8 @@ Invoke-WPFRunspace -ScriptBlock { # Print the logo Invoke-WPFFormVariables -# Check if Chocolatey is installed -Install-WinUtilChoco +# Install Winget if not already present +Install-WinUtilWinget # Set the titlebar $sync["Form"].title = $sync["Form"].title + " " + $sync.version @@ -271,10 +271,14 @@ Add-Type @" "@ } - foreach ($proc in (Get-Process | Where-Object { $_.MainWindowTitle -and $_.MainWindowTitle -like "*titus*" })) { - if ($proc.Id -ne [System.IntPtr]::Zero) { + foreach ($proc in (Get-Process | Where-Object { $_.MainWindowTitle -and $_.MainWindowTitle -like "*titus*" })) { + # Check if the process's MainWindowHandle is valid + if ($proc.MainWindowHandle -ne [System.IntPtr]::Zero) { Write-Debug "MainWindowHandle: $($proc.Id) $($proc.MainWindowTitle) $($proc.MainWindowHandle)" $windowHandle = $proc.MainWindowHandle + } else { + Write-Warning "Process found, but no MainWindowHandle: $($proc.Id) $($proc.MainWindowTitle)" + } } diff --git a/scripts/start.ps1 b/scripts/start.ps1 index a2b65b01..4f68920a 100644 --- a/scripts/start.ps1 +++ b/scripts/start.ps1 @@ -44,21 +44,16 @@ $sync.version = "#{replaceme}" $sync.configs = @{} $sync.ProcessRunning = $false -$currentPid = [System.Security.Principal.WindowsIdentity]::GetCurrent() -$principal = new-object System.Security.Principal.WindowsPrincipal($currentPid) -$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator - - -if ($principal.IsInRole($adminRole)) -{ - $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Admin)" - clear-host -} -else +# If script isn't running as admin, show error message and quit +If (([Security.Principal.WindowsIdentity]::GetCurrent()).Owner.Value -ne "S-1-5-32-544") { Write-Host "===========================================" -Foregroundcolor Red Write-Host "-- Scripts must be run as Administrator ---" -Foregroundcolor Red Write-Host "-- Right-Click Start -> Terminal(Admin) ---" -Foregroundcolor Red Write-Host "===========================================" -Foregroundcolor Red break -} \ No newline at end of file +} + +# Set PowerShell window title +$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Admin)" +clear-host diff --git a/winutil.ps1 b/winutil.ps1 index 73b70c6f..66f21eb2 100644 --- a/winutil.ps1 +++ b/winutil.ps1 @@ -10,7 +10,7 @@ Author : Chris Titus @christitustech Runspace Author: @DeveloperDurp GitHub : https://github.com/ChrisTitusTech - Version : 24.05.01 + Version : 24.05.11 #> param ( [switch]$Debug, @@ -47,21 +47,12 @@ Add-Type -AssemblyName System.Windows.Forms # Variable to sync between runspaces $sync = [Hashtable]::Synchronized(@{}) $sync.PSScriptRoot = $PSScriptRoot -$sync.version = "24.05.01" +$sync.version = "24.05.11" $sync.configs = @{} $sync.ProcessRunning = $false -$currentPid = [System.Security.Principal.WindowsIdentity]::GetCurrent() -$principal = new-object System.Security.Principal.WindowsPrincipal($currentPid) -$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator - - -if ($principal.IsInRole($adminRole)) -{ - $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Admin)" - clear-host -} -else +# If script isn't running as admin, show error message and quit +If (([Security.Principal.WindowsIdentity]::GetCurrent()).Owner.Value -ne "S-1-5-32-544") { Write-Host "===========================================" -Foregroundcolor Red Write-Host "-- Scripts must be run as Administrator ---" -Foregroundcolor Red @@ -69,6 +60,10 @@ else Write-Host "===========================================" -Foregroundcolor Red break } + +# Set PowerShell window title +$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Admin)" +clear-host function ConvertTo-Icon { <# @@ -624,14 +619,17 @@ function Get-WinUtilWingetLatest { .DESCRIPTION This function grabs the latest version of Winget and returns the download path to Install-WinUtilWinget for installation. #> - + # Invoke-WebRequest is notoriously slow when the byte progress is displayed. The following lines disable the progress bar and reset them at the end of the function + $PreviousProgressPreference = $ProgressPreference + $ProgressPreference = "silentlyContinue" Try{ # Grabs the latest release of Winget from the Github API for the install process. $response = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/Winget-cli/releases/latest" -Method Get -ErrorAction Stop $latestVersion = $response.tag_name #Stores version number of latest release. - $licenseWingetUrl = $response.assets.browser_download_url[0] #Index value for License file. + $licenseWingetUrl = $response.assets.browser_download_url | Where-Object {$_ -like "*License1.xml"} #Index value for License file. Write-Host "Latest Version:`t$($latestVersion)`n" - $assetUrl = $response.assets.browser_download_url[2] #Index value for download URL. + Write-Host "Downloading..." + $assetUrl = $response.assets.browser_download_url | Where-Object {$_ -like "*Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"} Invoke-WebRequest -Uri $licenseWingetUrl -OutFile $ENV:TEMP\License1.xml # The only pain is that the msixbundle for winget-cli is 246MB. In some situations this can take a bit, with slower connections. Invoke-WebRequest -Uri $assetUrl -OutFile $ENV:TEMP\Microsoft.DesktopAppInstaller.msixbundle @@ -639,6 +637,7 @@ function Get-WinUtilWingetLatest { Catch{ throw [WingetFailedInstall]::new('Failed to get latest Winget release and license') } + $ProgressPreference = $PreviousProgressPreference } function Get-WinUtilWingetPrerequisites { <# @@ -733,26 +732,41 @@ Function Install-WinUtilProgramWinget { # This is up to the individual package maintainers to enable these options. Aka. not as clean as Linux Package Managers. try { $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $Program --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru).ExitCode - if($status -ne 0){ - Write-Host "Attempt with User scope" - $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $Program --scope user --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru).ExitCode - if($status -ne 0){ - Write-Host "Attempt with Unelevated prompt" - $status = $(Start-Process -FilePath "powershell" -ArgumentList "-Command Start-Process winget -ArgumentList 'install --id $Program --silent --accept-source-agreements --accept-package-agreements' -Verb runAsUser" -Wait -PassThru).ExitCode - if($status -ne 0){ - Write-Host "Failed to install $Program." - } else { - Write-Host "$Program installed successfully with Unelevated prompt." - } - } else { - Write-Host "$Program installed successfully with User scope." - } - } else { + if($status -eq 0){ Write-Host "$Program installed successfully." + continue } - } catch { + Write-Host "Attempt with User scope" + $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $Program --scope user --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru).ExitCode + if($status -eq 0){ + Write-Host "$Program installed successfully with User scope." + continue + } + Write-Host "Attempt with User prompt" + $userChoice = [System.Windows.MessageBox]::Show("Do you want to attempt $Program installation with specific user credentials? Select 'Yes' to proceed or 'No' to skip.", "User Credential Prompt", [System.Windows.MessageBoxButton]::YesNo) + if ($userChoice -eq 'Yes') { + $getcreds = Get-Credential + $process = Start-Process -FilePath "winget" -ArgumentList "install --id $Program --silent --accept-source-agreements --accept-package-agreements" -Credential $getcreds -PassThru + Wait-Process -Id $process.Id + $status = $process.ExitCode + } else { + Write-Host "Skipping installation with specific user credentials." + } + if($status -eq 0){ + Write-Host "$Program installed successfully with User prompt." + continue + } + Write-Host "Attempting installation with Chocolatey as a fallback method" + Install-WinUtilChoco + $status = $(Start-Process -FilePath "choco" -ArgumentList "install $Program -y" -Wait -PassThru).ExitCode + if($status -eq 0){ + Write-Host "$Program installed successfully using Chocolatey." + continue + } + Write-Host "Failed to install $Program. You need to install it manually... Sorry!" + } catch { Write-Host "Failed to install $Program due to an error: $_" - } + } } if($manage -eq "Uninstalling"){ # Uninstall package via ID using winget directly. @@ -827,6 +841,8 @@ function Install-WinUtilWinget { Write-Host "Failure detected while installing via GitHub method. Continuing with Chocolatey method as fallback." -ForegroundColor Red # In case install fails via GitHub method. Try { + # Install Choco if not already present + Install-WinUtilChoco Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install winget-cli" Write-Host "Winget Installed" -ForegroundColor Green Write-Output "Refreshing Environment Variables...`n" @@ -3210,7 +3226,8 @@ function Invoke-WPFFixesWinget { .DESCRIPTION BravoNorris for the fantastic idea of a button to reinstall winget #> - + # Install Choco if not already present + Install-WinUtilChoco Start-Process -FilePath "choco" -ArgumentList "install winget -y --force" -NoNewWindow -Wait } @@ -3339,6 +3356,8 @@ function Invoke-WPFGetIso { # you consent to downloading it, no need to show extra dialogs [System.Windows.MessageBox]::Show("oscdimge.exe is not found on the system, winutil will now attempt do download and install it using choco. This might take a long time.") # the step below needs choco to download oscdimg + # Install Choco if not already present + Install-WinUtilChoco $chocoFound = [bool] (Get-Command -ErrorAction Ignore -Type Application choco) Write-Host "choco on system: $chocoFound" if (!$chocoFound) @@ -3726,6 +3745,7 @@ public class PowerManagement { $keepEdge = $sync.WPFMicrowinKeepEdge.IsChecked $copyToUSB = $sync.WPFMicrowinCopyToUsb.IsChecked $injectDrivers = $sync.MicrowinInjectDrivers.IsChecked + $importDrivers = $sync.MicrowinImportDrivers.IsChecked $mountDir = $sync.MicrowinMountDir.Text $scratchDir = $sync.MicrowinScratchDir.Text @@ -3784,13 +3804,54 @@ public class PowerManagement { return } + if ($importDrivers) + { + Write-Host "Exporting drivers from active installation..." + if (Test-Path "$env:TEMP\DRV_EXPORT") + { + Remove-Item "$env:TEMP\DRV_EXPORT" -Recurse -Force + } + if (($injectDrivers -and (Test-Path $sync.MicrowinDriverLocation.Text))) + { + Write-Host "Using specified driver source..." + dism /english /online /export-driver /destination="$($sync.MicrowinDriverLocation.Text)" | Out-Host + if ($?) + { + # Don't add exported drivers yet, that is run later + Write-Host "Drivers have been exported successfully." + } + else + { + Write-Host "Failed to export drivers." + } + } + else + { + New-Item -Path "$env:TEMP\DRV_EXPORT" -ItemType Directory -Force + dism /english /online /export-driver /destination="$env:TEMP\DRV_EXPORT" | Out-Host + if ($?) + { + Write-Host "Adding exported drivers..." + dism /english /image="$scratchDir" /add-driver /driver="$env:TEMP\DRV_EXPORT" /recurse | Out-Host + } + else + { + Write-Host "Failed to export drivers. Continuing without importing them..." + } + if (Test-Path "$env:TEMP\DRV_EXPORT") + { + Remove-Item "$env:TEMP\DRV_EXPORT" -Recurse -Force + } + } + } + if ($injectDrivers) { $driverPath = $sync.MicrowinDriverLocation.Text if (Test-Path $driverPath) { Write-Host "Adding Windows Drivers image($scratchDir) drivers($driverPath) " - Add-WindowsDriver -Path "$scratchDir" -Recurse -Driver "$driverPath" + dism /English /image:$scratchDir /add-driver /driver:$driverPath /recurse | Out-Host } else { @@ -4008,7 +4069,7 @@ public class PowerManagement { if (Test-Path $driverPath) { Write-Host "Adding Windows Drivers image($scratchDir) drivers($driverPath) " - Add-WindowsDriver -Path "$scratchDir" -Driver "$driverPath" -Recurse + dism /English /image:$scratchDir /add-driver /driver:$driverPath /recurse | Out-Host } else { @@ -4138,14 +4199,12 @@ function Invoke-WPFOOSU { Start-Process $OOSU_filepath } "recommended"{ - $oosu_config = "$ENV:temp\ooshutup10_recommended.cfg" - Invoke-WebRequest -Uri "https://raw.githubusercontent.com/ChrisTitusTech/winutil/main/config/ooshutup10_recommended.cfg" -OutFile $oosu_config + New-Item -Path $ENV:temp\ooshutup10_recommended.cfg -ItemType File -Value $sync.configs.ooshutup10_recommended -Force Write-Host "Applying recommended OO Shutup 10 Policies" Start-Process $OOSU_filepath -ArgumentList "$oosu_config /quiet" -Wait } "undo"{ - $oosu_config = "$ENV:temp\ooshutup10_factory.cfg" - Invoke-WebRequest -Uri "https://raw.githubusercontent.com/ChrisTitusTech/winutil/main/config/ooshutup10_factory.cfg" -OutFile $oosu_config + New-Item -Path $ENV:temp\ooshutup10_factory.cfg -ItemType File -Value $sync.configs.ooshutup10_factory -Force Write-Host "Resetting all OO Shutup 10 Policies" Start-Process $OOSU_filepath -ArgumentList "$oosu_config /quiet" -Wait } @@ -5715,6 +5774,14 @@ $sync.configs.applications = '{ "link": "https://desktop.github.com/", "winget": "Git.Git;GitHub.GitHubDesktop" }, + "WPFInstallgitkrakenclient": { + "category": "Development", + "choco": "gitkraken", + "content": "GitKraken Client", + "description": "GitKraken Client is a powerful visual Git client from Axosoft that works with ALL git repositories on any hosting environment.", + "link": "https://www.gitkraken.com/git-client", + "winget": "Axosoft.GitKraken" + }, "WPFInstallglaryutilities": { "category": "Utilities", "choco": "glaryutilities-free", @@ -5723,6 +5790,14 @@ $sync.configs.applications = '{ "link": "https://www.glarysoft.com/glary-utilities/", "winget": "Glarysoft.GlaryUtilities" }, + "WPFInstallgodotengine": { + "category": "Development", + "choco": "godot", + "content": "Godot Engine", + "description": "Godot Engine is a free, open-source 2D and 3D game engine with a focus on usability and flexibility.", + "link": "https://godotengine.org/", + "winget": "GodotEngine.GodotEngine" + }, "WPFInstallgog": { "category": "Games", "choco": "goggalaxy", @@ -5976,7 +6051,7 @@ $sync.configs.applications = '{ "choco": "jellyfin-media-player", "content": "Jellyfin Media Player", "description": "Jellyfin Media Player is a client application for the Jellyfin media server, providing access to your media library.", - "link": "https://github.com/jellyfin/jellyfin-media-playerf", + "link": "https://github.com/jellyfin/jellyfin-media-player", "winget": "Jellyfin.JellyfinMediaPlayer" }, "WPFInstalljellyfinserver": { @@ -6150,8 +6225,8 @@ $sync.configs.applications = '{ "WPFInstallmatrix": { "category": "Communications", "choco": "element-desktop", - "content": "Matrix", - "description": "Matrix is an open network for secure, decentralized communication with features like chat, VoIP, and collaboration tools.", + "content": "Element", + "description": "Element is a client for Matrix?an open network for secure, decentralized communication.", "link": "https://element.io/", "winget": "Element.Element" }, @@ -6219,6 +6294,46 @@ $sync.configs.applications = '{ "link": "https://www.msi.com/Landing/afterburner", "winget": "Guru3D.Afterburner" }, + "WPFInstallBorderlessGaming": { + "category": "Utilities", + "choco": "na", + "content": "Borderless Gaming", + "description": "Play your favorite games in a borderless window; no more time consuming alt-tabs.", + "link": "https://github.com/Codeusa/Borderless-Gaming", + "winget": "Codeusa.BorderlessGaming" + }, + "WPFInstallEqualizerAPO": { + "category": "Multimedia Tools", + "choco": "equalizerapo", + "content": "Equalizer APO", + "description": "Equalizer APO is a parametric / graphic equalizer for Windows.", + "link": "https://sourceforge.net/projects/equalizerapo", + "winget": "na" + }, + "WPFInstallFreeFileSync": { + "category": "Utilities", + "choco": "freefilesync", + "content": "FreeFileSync", + "description": "Synchronize Files and Folders", + "link": "https://freefilesync.org", + "winget": "na" + }, + "WPFInstallCompactGUI": { + "category": "Utilities", + "choco": "compactgui", + "content": "Compact GUI", + "description": "Transparently compress active games and programs using Windows 10/11 APIs", + "link": "https://github.com/IridiumIO/CompactGUI", + "winget": "IridiumIO.CompactGUI" + }, + "WPFInstallExifCleaner": { + "category": "Utilities", + "choco": "na", + "content": "ExifCleaner", + "description": "Desktop app to clean metadata from images, videos, PDFs, and other files.", + "link": "https://github.com/szTheory/exifcleaner", + "winget": "szTheory.exifcleaner" + }, "WPFInstallmullvadbrowser": { "category": "Browsers", "choco": "na", @@ -6627,6 +6742,14 @@ $sync.configs.applications = '{ "link": "https://bitsum.com/", "winget": "BitSum.ProcessLasso" }, + "WPFInstallspotify": { + "category": "Multimedia Tools", + "choco": "spotify", + "content": "Spotify", + "description": "Spotify is a digital music service that gives you access to millions of songs, podcasts, and videos from artists all over the world.", + "link": "https://www.spotify.com/", + "winget": "Spotify.Spotify" + }, "WPFInstallprocessmonitor": { "category": "Microsoft Tools", "choco": "procexp", @@ -7595,6 +7718,14 @@ $sync.configs.applications = '{ "link": "https://github.com/magic-wormhole/magic-wormhole", "winget": "magic-wormhole.magic-wormhole" }, + "WPFInstalglazewm": { + "category": "Utilities", + "choco": "na", + "content": "GlazeWM", + "description": "GlazeWM is a tiling window manager for Windows inspired by i3 and Polybar", + "link": "https://github.com/glzr-io/glazewm", + "winget": "glzr-io.glazewm" + }, "WPFInstallfancontrol": { "category": "Utilities", "choco": "na", @@ -7618,6 +7749,14 @@ $sync.configs.applications = '{ "description": "The customization marketplace for Windows programs", "link": "https://windhawk.net", "winget": "RamenSoftware.Windhawk" + }, + "WPFInstallForceAutoHDR": { + "category": "Utilities", + "choco": "na", + "content": "GUI That Forces Auto HDR In Unsupported Games", + "description": "ForceAutoHDR simplifies the process of adding games to the AutoHDR list in the Windows Registry", + "link": "https://github.com/7gxycn08/ForceAutoHDR", + "winget": "ForceAutoHDR.7gxycn08" } }' | convertfrom-json $sync.configs.dns = '{ @@ -9966,27 +10105,6 @@ $sync.configs.tweaks = '{ "Value": "1", "Type": "DWord" }, - { - "Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games", - "OriginalValue": "1", - "Name": "GPU Priority", - "Value": "8", - "Type": "DWord" - }, - { - "Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games", - "OriginalValue": "1", - "Name": "Priority", - "Value": "6", - "Type": "DWord" - }, - { - "Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks\\Games", - "OriginalValue": "High", - "Name": "Scheduling Category", - "Value": "High", - "Type": "String" - }, { "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\UserProfileEngagement", "OriginalValue": "1", @@ -10830,6 +10948,494 @@ $sync.configs.tweaks = '{ "Type": "300" } }' | convertfrom-json +$sync.configs.ooshutup10_factory = '############################################################################ +# This file was created with O&O ShutUp10++ V1.9.1436 +# and can be imported onto another computer. +# +# Download the application at https://www.oo-software.com/shutup10 +# You can then import the file from within the program. +# +# Alternatively you can import it automatically over a command line. +# Simply use the following parameter: +# OOSU10.exe +# +# Selecting the Option /quiet ends the app right after the import and the +# user does not get any feedback about the import. +# +# We are always happy to answer any questions you may have! +# ? 2015-2023 O&O Software GmbH, Berlin. All rights reserved. +# https://www.oo-software.com/ +############################################################################ + +P001 - +P002 - +P003 - +P004 - +P005 - +P006 - +P008 - +P026 - +P027 - +P028 - +P064 - +P065 - +P066 - +P067 - +P070 - +P069 - +P009 - +P010 - +P015 - +P068 - +P016 - +A001 - +A002 - +A003 - +A004 - +A006 - +A005 - +P007 - +P036 - +P025 - +P033 - +P023 - +P056 - +P057 - +P012 - +P034 - +P013 - +P035 - +P062 - +P063 - +P081 - +P047 - +P019 - +P048 - +P049 - +P020 - +P037 - +P011 - +P038 - +P050 - +P051 - +P018 - +P039 - +P021 - +P040 - +P022 - +P041 - +P014 - +P042 - +P052 - +P053 - +P054 - +P055 - +P029 - +P043 - +P030 - +P044 - +P031 - +P045 - +P032 - +P046 - +P058 - +P059 - +P060 - +P061 - +P071 - +P072 - +P073 - +P074 - +P075 - +P076 - +P077 - +P078 - +P079 - +P080 - +P024 - +S001 - +S002 - +S003 - +S008 - +E101 - +E201 - +E115 - +E215 - +E118 - +E218 - +E107 - +E207 - +E111 - +E211 - +E112 - +E212 - +E109 - +E209 - +E121 - +E221 - +E103 - +E203 - +E123 - +E223 - +E124 - +E224 - +E128 - +E228 - +E119 - +E219 - +E120 - +E220 - +E122 - +E222 - +E125 - +E225 - +E126 - +E226 - +E106 - +E206 - +E127 - +E227 - +E001 - +E002 - +E003 - +E008 - +E007 - +E010 - +E011 + +E012 + +E009 - +E004 - +E005 - +E013 - +E014 - +E006 - +F002 - +F014 - +F015 - +F016 - +F001 - +F003 - +F004 - +F005 - +F007 - +F008 - +F009 - +F006 - +F010 - +F011 - +F012 - +F013 - +Y001 - +Y002 - +Y003 - +Y004 - +Y005 - +Y006 - +Y007 - +C012 - +C002 - +C013 - +C007 - +C008 - +C009 - +C010 - +C011 - +C014 - +C015 - +C101 - +C201 - +C102 - +L001 - +L003 - +L004 - +L005 - +U001 - +U004 - +U005 - +U006 - +U007 - +W001 - +W011 - +W004 - +W005 - +W010 - +W009 - +P017 - +W006 - +W008 - +M006 - +M011 - +M010 - +O003 - +O001 - +S012 - +S013 - +S014 - +K001 - +K002 - +K005 - +M025 - +M003 - +M015 - +M016 - +M017 - +M018 - +M019 - +M020 - +M021 - +M022 - +M001 - +M004 - +M005 - +M024 - +M012 - +M013 - +M014 - +N001 -' +$sync.configs.ooshutup10_recommended = '############################################################################ +# This file was created with O&O ShutUp10++ V1.9.1436 +# and can be imported onto another computer. +# +# Download the application at https://www.oo-software.com/shutup10 +# You can then import the file from within the program. +# +# Alternatively you can import it automatically over a command line. +# Simply use the following parameter: +# OOSU10.exe +# +# Selecting the Option /quiet ends the app right after the import and the +# user does not get any feedback about the import. +# +# We are always happy to answer any questions you may have! +# ? 2015-2023 O&O Software GmbH, Berlin. All rights reserved. +# https://www.oo-software.com/ +############################################################################ + +P001 + +P002 + +P003 + +P004 + +P005 + +P006 + +P008 + +P026 + +P027 + +P028 + +P064 + +P065 + +P066 + +P067 + +P070 + +P069 + +P009 - +P010 - +P015 - +P068 - +P016 - +A001 + +A002 + +A003 + +A004 + +A006 + +A005 + +P007 + +P036 + +P025 + +P033 + +P023 + +P056 - +P057 - +P012 - +P034 - +P013 - +P035 - +P062 - +P063 - +P081 - +P047 - +P019 - +P048 - +P049 - +P020 - +P037 - +P011 - +P038 - +P050 - +P051 - +P018 - +P039 - +P021 - +P040 - +P022 - +P041 - +P014 - +P042 - +P052 - +P053 - +P054 - +P055 - +P029 - +P043 - +P030 - +P044 - +P031 - +P045 - +P032 - +P046 - +P058 - +P059 - +P060 - +P061 - +P071 - +P072 - +P073 - +P074 - +P075 - +P076 - +P077 - +P078 - +P079 - +P080 - +P024 - +S001 + +S002 + +S003 + +S008 - +E101 + +E201 + +E115 + +E215 + +E118 + +E218 + +E107 + +E207 + +E111 + +E211 + +E112 + +E212 + +E109 + +E209 + +E121 + +E221 + +E103 + +E203 + +E123 + +E223 + +E124 + +E224 + +E128 + +E228 + +E119 - +E219 - +E120 - +E220 - +E122 - +E222 - +E125 - +E225 - +E126 - +E226 - +E106 - +E206 - +E127 - +E227 - +E001 + +E002 + +E003 + +E008 + +E007 + +E010 + +E011 + +E012 + +E009 - +E004 - +E005 - +E013 - +E014 - +E006 - +F002 + +F014 + +F015 + +F016 + +F001 + +F003 + +F004 + +F005 + +F007 + +F008 + +F009 + +F006 - +F010 - +F011 - +F012 - +F013 - +Y001 + +Y002 + +Y003 + +Y004 + +Y005 + +Y006 + +Y007 + +C012 + +C002 + +C013 + +C007 + +C008 + +C009 + +C010 + +C011 + +C014 + +C015 + +C101 + +C201 + +C102 + +L001 + +L003 + +L004 - +L005 - +U001 + +U004 + +U005 + +U006 + +U007 + +W001 + +W011 + +W004 - +W005 - +W010 - +W009 - +P017 - +W006 - +W008 - +M006 + +M011 - +M010 - +O003 - +O001 - +S012 - +S013 - +S014 - +K001 + +K002 + +K005 + +M025 + +M003 - +M015 - +M016 - +M017 - +M018 - +M019 - +M020 - +M021 - +M022 + +M001 + +M004 + +M005 + +M024 + +M012 - +M013 - +M014 - +N001 -' $inputXML = ' + + + + + + @@ -11942,17 +12554,17 @@ $inputXML = ' - - - - - + + + + + - - - + + + + + + + - - - - - @@ -12851,6 +13487,7 @@ $inputXML = ' + @@ -13101,8 +13738,8 @@ Invoke-WPFRunspace -ScriptBlock { # Print the logo Invoke-WPFFormVariables -# Check if Chocolatey is installed -Install-WinUtilChoco +# Install Winget if not already present +Install-WinUtilWinget # Set the titlebar $sync["Form"].title = $sync["Form"].title + " " + $sync.version @@ -13227,10 +13864,14 @@ Add-Type @" "@ } - foreach ($proc in (Get-Process | Where-Object { $_.MainWindowTitle -and $_.MainWindowTitle -like "*titus*" })) { - if ($proc.Id -ne [System.IntPtr]::Zero) { + foreach ($proc in (Get-Process | Where-Object { $_.MainWindowTitle -and $_.MainWindowTitle -like "*titus*" })) { + # Check if the process's MainWindowHandle is valid + if ($proc.MainWindowHandle -ne [System.IntPtr]::Zero) { Write-Debug "MainWindowHandle: $($proc.Id) $($proc.MainWindowTitle) $($proc.MainWindowHandle)" $windowHandle = $proc.MainWindowHandle + } else { + Write-Warning "Process found, but no MainWindowHandle: $($proc.Id) $($proc.MainWindowTitle)" + } } diff --git a/xaml/inputApp.xaml b/xaml/inputApp.xaml index 9acce14d..229031f5 100644 --- a/xaml/inputApp.xaml +++ b/xaml/inputApp.xaml @@ -79,7 +79,7 @@ - + @@ -158,6 +158,12 @@ + + + + + + @@ -407,17 +413,17 @@ - - - - - + + + + + - - + + + + + + + - - - - - diff --git a/xaml/inputXML.xaml b/xaml/inputXML.xaml index 9fee01b4..ba3475fb 100644 --- a/xaml/inputXML.xaml +++ b/xaml/inputXML.xaml @@ -843,6 +843,7 @@ Foreground="{LabelboxForegroundColor}" ToolTip="Path to unpacked drivers all sys and inf files for devices that need drivers" /> +