diff --git a/InstallWSL.psm1 b/install-wsl.psm1 similarity index 54% rename from InstallWSL.psm1 rename to install-wsl.psm1 index 83afd48..842b502 100644 --- a/InstallWSL.psm1 +++ b/install-wsl.psm1 @@ -30,22 +30,13 @@ Workflow Install-WSL { ) # The task scheduler is unreliable in AME - #Write-Output 'Scheduling task' - # - #$action = New-ScheduledTaskAction -Execute 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' -Argument "-NonInteractive -WindowStyle Normal -NoLogo -NoProfile -Command `"& { Write-Output \`"Don```'t close this PowerShell window! This is your WSL installer! Just give it a minute...\`"; Get-Job -Command `'Install-WSL`' | Resume-Job | Receive-Job -Wait; pause; exit }`"" - #$logon = New-ScheduledTaskTrigger -AtLogOn - #$task = Register-ScheduledTask -TaskName 'InstallWSL' -Action $action -Trigger $logon -RunLevel Highest - - ## Where ShortcutPath is placed is honestly an implementation detail. It will - ## be run as administrator by the elevator, which is what gets run at startup - #$ShortcutPath = Join-Path $env:ProgramData 'Microsoft\Windows\Install WSL.lnk' - #$ElevatorPath = Join-Path $env:ProgramData 'Microsoft\Windows\Start Menu\Programs\Startup\Install WSL.lnk' $ShortcutPath = Join-Path $env:AppData 'Microsoft\Windows\Start Menu\Programs\Startup\Install WSL.lnk' if ($Cancel) { $Removed = Remove-Item -LiteralPath $ShortcutPath -ErrorAction SilentlyContinue $Removed = Get-Job -Command 'Install-WSL' | Where-Object {$_.State -eq 'Suspended'} | Remove-Job -Force - return Write-Output 'All pending WSL installations have been canceled.' + Write-Information 'All pending WSL installations have been canceled.' + return 'done' } # establish directory for WSL installations @@ -57,7 +48,7 @@ Workflow Install-WSL { return Write-Error 'Cannot install a distro twice! This will waste your internet data. Uninstall the existing version first.' -Category ResourceExists } - Write-Output 'Creating startup item' + Write-Information 'Creating startup item' InlineScript { $shell = New-Object -ComObject ('WScript.Shell') @@ -65,23 +56,14 @@ Workflow Install-WSL { $shortcut.TargetPath = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' $shortcut.Arguments = "-WindowStyle Normal -NoLogo -NoProfile -Command `"& { Write-Output \`"Resuming installation...\`"; Get-Job -Command `'Install-WSL`' | Resume-Job | Receive-Job -Wait; pause; exit }`"" $shortcut.Save() - - #$elevator = $shell.CreateShortcut($Using:ElevatorPath) - #$elevator.TargetPath = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' - #$elevator.Arguments = "-WindowStyle Normal -NoLogo -NoProfile -Command `"Write-Output \`"The WSL installation can now be started. Please accept the UAC prompt to proceed\`"; pause; Start-Process -FilePath '$Using:ShortcutPath' -Verb Runas`"" - #$elevator.Save() } - # This didn't work. - ## This is the exact same shortcut as above, but with 'Run As Administrator' set, encoded in Base64. - ## [Convert]::ToBase64String((Get-Content 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\Install WSL.lnk' -Encoding Byte)) - ## This is needed because that flag cannot be checked programmatically. - #$Base64 = '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' - #Set-Content -LiteralPath $ShortcutPath -Value ([Convert]::FromBase64String($Base64)) -Encoding Byte - - Write-Output 'There will be a "Windows PowerShell" shortcut in your startup items until this script is complete. Please do not be alarmed, it will remove itself once the installation is complete.' - - Write-Output 'Ensuring required features are enabled' + Write-Information '' + Write-Information 'There will be a "Windows PowerShell" shortcut in your startup items until this' + Write-Information 'script is complete. Please do not be alarmed, it will remove itself once the' + Write-Information 'installation is complete.' + Write-Information '' + Write-Information 'Ensuring required features are enabled...' # using a named pipe to communicate between elevated process and not elevated one @@ -128,20 +110,14 @@ Workflow Install-WSL { # This feels messy which is why it's disabled, and it would also detect # the currently running task - #$Job = Get-Job -Name 'Install-WSL' - # - #if ($Job) { - # Write-Output 'Already waiting for the WSL feature to be enabled' - # return - #} - # Future Logan from the future!: I think the shortcut is more easily # detected, but there are reasons you might want to run this more than # once in a row. For example if you are installing multiple distros # Should work okay... - Write-Output 'Restart your computer in 30 seconds or it will explode' + Write-Information 'Restart your computer in 30 seconds or it will explode' + 'restart-needed' Suspend-Workflow # Wait for a logon where the feature is installed. This will be after at @@ -199,7 +175,8 @@ Workflow Install-WSL { } if ($RestartNeeded) { - Write-Output 'Looks like the WSL component is still not installed.' + Write-Information 'Looks like the WSL component is still not installed.' + 'still-waiting' Suspend-Workflow } else { $waiting = $False @@ -207,12 +184,6 @@ Workflow Install-WSL { } } - # This is so that the progress indicator doesn't obstruct the text - Write-Output "`n`n`n`n`n`n`n`n`n" - Write-Output 'Warning: The PowerShell window will display the download process for longer than' - Write-Output 'usual. This is a Windows bug, and is only visual.' - Write-Output '' - $retrying = $True while ($retrying) { $tempFile = InlineScript { New-TemporaryFile } @@ -220,22 +191,52 @@ Workflow Install-WSL { $tempFile = $tempFile.FullName -replace '$','.zip' try { - Write-Output "Attempting to download distribution to $tempFile..." - Invoke-WebRequest -Uri "https://aka.ms/$LinuxDistribution" -OutFile $tempFile -ErrorAction Stop -UseBasicParsing - #InlineScript { - # (New-Object System.Net.WebClient).DownloadFile("https://aka.ms/$Using:LinuxDistribution", $tempFile.FullName) - #} - #Start-BitsTransfer -DisplayName 'WSL Package Download' -Source "https://aka.ms/$LinuxDistribution" -Destination $tempFile -ErrorAction Stop + Write-Information '' + Write-Information "Attempting to download distribution to $tempFile..." + + $data = InlineScript { + $PipeName = -join (((48..57)+(65..90)+(97..122)) * 80 |Get-Random -Count 12 |%{[char]$_}) + + Start-Process powershell -ArgumentList "` + Try {` + Invoke-WebRequest -Uri `"https://aka.ms/$Using:LinuxDistribution`" -OutFile `"$Using:tempFile`" -ErrorAction Stop -UseBasicParsing` + `$Result = 'Success'` + } Catch {` + `$Result = `"Failed to download file: `$(`$PSItem.Message)`"` + }` + ` + `$pipe = New-Object System.IO.Pipes.NamedPipeServerStream `'$PipeName`',`'Out`'` + `$pipe.WaitForConnection()` + `$sw = New-Object System.IO.StreamWriter `$pipe` + `$sw.AutoFlush = `$True` + `$sw.WriteLine([string]`$Result)` + `$sw.Dispose()` + `$pipe.Dispose()` + " -WindowStyle Hidden -ErrorAction Stop + + $pipe = New-Object System.IO.Pipes.NamedPipeClientStream '.',$PipeName,'In' + $pipe.Connect() + $sr = New-Object System.IO.StreamReader $pipe + $data = $sr.ReadLine() + $sr.Dispose() + $pipe.Dispose() + + $data + } -ErrorAction Stop + + if ($data -ne 'Success') { + Write-Error $data -ErrorAction Stop + } + $retrying = $False - Write-Output 'Done!' + Write-Information 'Done!' } catch { - #Get-BitsTransfer -Name 'WSL Package Download' | Remove-BitsTransfer -ErrorAction SilentlyContinue Remove-Item -LiteralPath $tempFile -ErrorAction SilentlyContinue # PSItem is contextual and can't be read from the InlineScript $theError = $PSItem.Message - Write-Output "Error: $theError" + Write-Information "Error: $theError" $response = InlineScript { [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') @@ -243,45 +244,31 @@ Workflow Install-WSL { } if ($response -eq 3) { # Abort - Write-Output 'Aborting' + Write-Information 'Aborting' $retrying = $False - Unregister-ScheduledTask -TaskName 'InstallWSL' -Confirm:$False - return + Write-Information 'Removing startup item...' + Remove-Item -LiteralPath $ShortcutPath -ErrorAction SilentlyContinue + return 'aborted' } elseif ($response -eq 5) { # Ignore - Write-Output 'Ignoring' + Write-Information 'Ignoring' + 'still-waiting' Suspend-Workflow # Wait for next logon } - Write-Output 'Retrying' + Write-Information 'Retrying' # If retry just loop again /shrug } } - #Write-Output 'Unscheduling task...' - # - #Unregister-ScheduledTask -TaskName 'InstallWSL' -Confirm:$False - - Write-Output 'Removing startup item...' + Write-Information 'Removing startup item...' Remove-Item -LiteralPath $ShortcutPath -ErrorAction SilentlyContinue - #Remove-Item -LiteralPath $ElevatorPath -ErrorAction SilentlyContinue $tempDir = New-TemporaryDirectory - Expand-Archive -LiteralPath $tempFile -DestinationPath $tempDir - Remove-Item -LiteralPath $tempFile + Expand-Archive -LiteralPath $tempFile -DestinationPath $tempDir -ErrorAction Stop + Remove-Item -LiteralPath $tempFile -ErrorAction SilentlyContinue - Write-Output 'Distribution bundle extracted' - - # Thought we might need to support ARM64, turns out artrons doesn't want it. - # Leaving this (and the comment) here just in case. - - ## This appx package contains inner appx packages for each architecture. - ## This information is encoded in an XML manifest file. - ## I want to use the XML manifest to find the right package, unzip that, and - ## then find the executable inside. - ## This allows compatibility with both x86 and ARM - #$RootManifest = Join-Path $tempDir 'AppxMetadata\AppxBundleManifest.xml' - #$Package = Select-Xml -Path $RootManifest -XPath '/Bundle/Packages/Package' | Where-Object {$_.Node.Type -eq 'Application' -and $_.Node.Architecture -eq 'x64'} | Select-Object -First 1 + Write-Information 'Distribution bundle extracted' $theDir = $tempDir $Executable = Get-ChildItem $tempDir | Where-Object {$_.Name -match '.exe$'} | Select-Object -First 1 @@ -294,7 +281,7 @@ Workflow Install-WSL { } $Package = Rename-Item -LiteralPath ($Package.FullName) -NewName ($Package.Name -replace '.appx$','.zip') -PassThru - Write-Output "Distribution package: $($Package.Name)" + Write-Information "Distribution package: $($Package.Name)" $InnerPackageTemp = New-TemporaryDirectory Expand-Archive -LiteralPath $Package -DestinationPath $InnerPackageTemp Remove-Item -LiteralPath $tempDir -Recurse @@ -305,30 +292,28 @@ Workflow Install-WSL { return Write-Error 'Could not find an executable inside the x64 package :(' -Category NotImplemented } } else { - Write-Output 'Root package contains the installer' + Write-Information 'Root package contains the installer' } # this is going to have to stick around forever if the wsl install is going to stay intact $theDir = Move-Item -LiteralPath $theDir -Destination $DistroFolder -PassThru $Executable = Get-ChildItem $theDir | Where-Object {$_.Name -match '.exe$'} | Select-Object -First 1 - Write-Output "Executing installer: $($Executable.Name)" + Write-Information "Executing installer: $($Executable.Name)" InlineScript { wsl --set-default-version 1 } Start-Process -FilePath ($Executable.FullName) -Wait - # ruins the WSL install - #Remove-Item -LiteralPath $theDir -Recurse -ErrorAction SilentlyContinue - Write-Output 'Everything should be in order now. Enjoy!' + Write-Information 'Everything should be in order now. Enjoy!' # We done + + return 'done' } function Install-WSLInteractive { $Distros = @( [PSCustomObject]@{Slug = 'wslubuntu2004'; Name = 'Ubuntu 20.04'; Arch = 'x64'} - #[PSCustomObject]@{Slug = 'wslubuntu2004arm'; Name = 'Ubuntu 20.04'; Arch = 'ARM64'} [PSCustomObject]@{Slug = 'wsl-ubuntu-1804'; Name = 'Ubuntu 18.04'; Arch = 'x64'} - #[PSCustomObject]@{Slug = 'wsl-ubuntu-1804-arm'; Name = 'Ubuntu 18.04'; Arch = 'ARM64'} [PSCustomObject]@{Slug = 'wsl-ubuntu-1604'; Name = 'Ubuntu 16.04'; Arch = 'x64'} [PSCustomObject]@{Slug = 'wsl-debian-gnulinux'; Name = 'Debian Stable'; Arch = 'x64'} [PSCustomObject]@{Slug = 'wsl-kali-linux-new'; Name = 'Kali Linux'; Arch = 'x64'} @@ -345,23 +330,23 @@ function Install-WSLInteractive { while ($Menu -ne 'exit') { Clear-Host # 80 chars: ' ' - Write-Output ' :: WSL INSTALL SCRIPT FOR WINDOWS 10 AME' - Write-Output '' - Write-Output ' This script will help you install Windows Subsystem for Linux on your' - Write-Output ' ameliorated installation of Windows 10' - Write-Output '' - Write-Output ' :: NOTE: Tested on Windows 10 1909, and Windows 10 AME 20H2' + Write-Host ' :: WSL INSTALL SCRIPT FOR WINDOWS 10 AME' + Write-Host '' + Write-Host ' This script will help you install Windows Subsystem for Linux on your' + Write-Host ' ameliorated installation of Windows 10' + Write-Host '' + Write-Host ' :: NOTE: Tested on Windows 10 1909, and Windows 10 AME 20H2' switch ($menu) { 'main' { - Write-Output '' - Write-Output ' :: Please enter a number from 1-3 to select an option from the list below' - Write-Output '' - Write-Output ' 1) Install a new WSL distro' - Write-Output ' 2) Cancel a pending WSL installation' - Write-Output ' 3) Exit' - Write-Output '' - Write-Host ' >> ' -NoNewLine + Write-Host '' + Write-Host ' :: Please enter a number from 1-3 to select an option from the list below' + Write-Host '' + Write-Host ' 1) Install a new WSL distro' + Write-Host ' 2) Cancel a pending WSL installation' + Write-Host ' 3) Exit' + Write-Host '' + Write-Host ' >> ' -NoNewLine $Input = $Host.UI.ReadLine() switch ($Input) { @@ -375,31 +360,30 @@ function Install-WSLInteractive { $Menu = 'exit' } default { - Write-Output '' + Write-Host '' Write-Host ' !! Invalid option selected' -ForegroundColor red - Write-Output '' + Write-Host '' Write-Host ' Press enter to continue...' -NoNewLine $Host.UI.ReadLine() } } } 'select-distro' { - Write-Output '' - Write-Output ' :: Please enter a number from the list to select a distro to install' - Write-Output '' + Write-Host '' + Write-Host ' :: Please enter a number from the list to select a distro to install' + Write-Host '' $Max = 1 $Distros | ForEach-Object { Add-Member -InputObject $_ -NotePropertyName Option -NotePropertyValue ([string]$Max) -Force - #Write-Output " $Max) $($_.Name) ($($_.Arch))" - Write-Output " $Max) $($_.Name)" + Write-Host " $Max) $($_.Name)" $Max += 1 } - Write-Output " $Max) Return to main menu" - Write-Output '' - Write-Host ' >> ' -NoNewLine + Write-Host " $Max) Return to main menu" + Write-Host '' + Write-Host ' >> ' -NoNewLine $Input = $Host.UI.ReadLine() if ($Input -eq ([string]$Max)) { @@ -408,10 +392,10 @@ function Install-WSLInteractive { $Distro = $Distros | Where-Object -Property Option -eq -Value $Input if ($Distro -eq $null) { - Write-Output '' - Write-Host ' !! Invalid option selected' -ForegroundColor Red - Write-Output '' - Write-Host ' Press enter to continue...' -NoNewLine + Write-Host '' + Write-Host ' !! Invalid option selected' -ForegroundColor Red + Write-Host '' + Write-Host ' Press enter to continue...' -NoNewLine $Host.UI.ReadLine() } else { $Menu = 'install-distro-confirm' @@ -419,9 +403,8 @@ function Install-WSLInteractive { } } 'install-distro-confirm' { - Write-Output '' - #Write-Host " :: WARNING: Are you sure you want to install $($Distro.Name) ($($Distro.Arch))? (yes/no) " -NoNewLine - Write-Host " :: WARNING: Are you sure you want to install $($Distro.Name)? (yes/no) " -NoNewLine + Write-Host '' + Write-Host " :: WARNING: Are you sure you want to install $($Distro.Name)? (yes/no) " -NoNewLine $Input = $Host.UI.ReadLine() switch ($Input) { @@ -432,60 +415,94 @@ function Install-WSLInteractive { $Menu = 'select-distro' } default { - Write-Output '' - Write-Host ' !! Invalid input' -ForegroundColor Red - Write-Output '' - Write-Host ' Press enter to continue...' -NoNewLine + Write-Host '' + Write-Host ' !! Invalid input' -ForegroundColor Red + Write-Host '' + Write-Host ' Press enter to continue...' -NoNewLine $Host.UI.ReadLine() $Menu = 'select-distro' } } } 'install-distro' { - Write-Output '' - #Write-Output "Installing $($Distro.Name) ($($Distro.Arch))..." - Write-Output "Installing $($Distro.Name)..." - Install-WSL -LinuxDistribution ($Distro.Slug) - $Menu = 'exit' + Write-Host '' + Write-Host "Installing $($Distro.Name)..." + + try { + $Menu = ('result-' + (Install-WSL -LinuxDistribution ($Distro.Slug) -InformationAction Continue -ErrorAction Stop | Select-Object -First 1 -Wait)) + } catch { + Write-Host '' + Write-Host ' !! An error occurred during the installation' -ForegroundColor Red + Write-Host " !! The error is: $PSItem" -ForegroundColor Red + Write-Host '' + Write-Host ' Your chosen distro could not be installed.' + Write-Host '' + Write-Host ' Press enter to continue...' -NoNewLine + $Host.UI.ReadLine() + $Menu = 'select-distro' + } } 'cancel' { - Write-Output '' - Write-Host ' :: WARNING: Are you sure you want to cancel all pending installs? (yes/no) ' -NoNewLine + Write-Host '' + Write-Host ' :: WARNING: Are you sure you want to cancel all pending installs? (yes/no) ' -NoNewLine $Input = $Host.UI.ReadLine() switch ($Input) { 'yes' { - Write-Output '' + Write-Host '' Install-WSL -Cancel } 'no' { - Write-Output '' - Write-Output ' Returning to main menu.' + Write-Host '' + Write-Host ' Returning to main menu.' } default { - Write-Output '' - Write-Host ' !! Invalid input' -ForegroundColor Red + Write-Host '' + Write-Host ' !! Invalid input' -ForegroundColor Red } } - Write-Output '' - Write-Host ' Press enter to continue...' -NoNewLine + Write-Host '' + Write-Host ' Press enter to continue...' -NoNewLine $Host.UI.ReadLine() $Menu = 'main' } 'admin' { - Write-Output '' - Write-Host ' !! This script should NOT be run as Administrator' -ForegroundColor Red - Write-Host ' !! Please close this window and run the script normally' -ForegroundColor Red - Write-Output '' - Write-Host ' Press enter to continue...' -NoNewLine + Write-Host '' + Write-Host ' !! This script should NOT be run as Administrator' -ForegroundColor Red + Write-Host ' !! Please close this window and run the script normally' -ForegroundColor Red + Write-Host '' + Write-Host ' Press enter to continue...' -NoNewLine + $Host.UI.ReadLine() + $Menu = 'exit' + } + 'result-restart-needed' { + Write-Host '' + Write-Host ' !! WSL installation will resume once you restart Windows' + Write-Host '' + Write-Host ' Please ensure you stay connected to the Internet.' + Write-Host '' + Write-Host ' Press enter to continue...' -NoNewLine + $Host.UI.ReadLine() + $Menu = 'exit' + } + 'result-done' { + Write-Host '' + Write-Host ' :: Installation done!' + Write-Host '' + Write-Host ' The WSL feature was already installed and enabled on your system, so we were' + Write-Host ' able to install your distro right away.' + Write-Host '' + Write-Host ' Enjoy!' + Write-Host '' + Write-Host ' Press enter to continue...' -NoNewLine $Host.UI.ReadLine() $Menu = 'exit' } default { - Write-Output '' - Write-Host " !! Invalid menu encountered ($Menu). Exiting" -ForegroundColor Red - Write-Host ' !! THIS IS A BUG, PLEASE REPORT IT TO THE AME DEVS' -ForegroundColor Red + Write-Host '' + Write-Host " !! Invalid menu encountered ($Menu). Exiting" -ForegroundColor Red + Write-Host ' !! THIS IS A BUG, PLEASE REPORT IT TO THE AME DEVS' -ForegroundColor Red $Menu = 'exit' } }