PsUWI.psm1
function New-UbuntuWSLInstance { <# .SYNOPSIS Create a new Ubuntu instance on WSL .DESCRIPTION Create a new Ubuntu instance on WSL. Windows 10 2004 only for now. .PARAMETER Release The Ubuntu release you want to use to create the instance. Default is focal. .PARAMETER Version The WSL version you want to use. Default is 1. .PARAMETER Force If specified, a new WSL tarball will always be downloaded even if it exists. .PARAMETER NoUpdate If specified, it will not update during the creation. .PARAMETER NoUpgrade If specified, it will only update but not upgrade during the creation. .PARAMETER RootOnly If specified, no new user will be created. .PARAMETER EnableSource If specified, all source repositories in `/etc/apt/sources.list` will be enabled. .PARAMETER EnableProposed If specified, Ubuntu Proposed repository will be enabled. By default selective is enabled. .PARAMETER DisableSelective If specified, Selective Proposed repostiory will be disabled. .PARAMETER AdditionalPPA The PPA you want to include by default. Separate each PPA by comma. .PARAMETER AptOutput If specified, apt output will be shown. .PARAMETER Silent If specified, all ouput will not be printed out. AptOutput will be ignored when using this .PARAMETER NonInteractive If specified, it will return the name of the created distro instead of going into the interactive prompt .PARAMETER AdditionalPkg The packages you want to include by default. Separate each package by comma. .EXAMPLE New-UbuntuWSLInstance -Release bionic # Create a Ubuntu Bionic instance on WSL1 .EXAMPLE New-UbuntuWSLInstance -Release xenial -Version 2 -RootOnly # Create an Ubuntu Xenial instance on WSL2 without creating a user account .EXAMPLE New-UbuntuWSLInstance -Version 2 -NoUpdate # Create an Ubuntu Focal instance on WSL2 without any update .EXAMPLE New-UbuntuWSLInstance -Release eoan -Force # Create an Ubuntu Eoan instance on WSL1 and download the WSL tarball even if it already exists .LINK https://github.com/patrick330602/PsUWI #> [cmdletbinding()] Param ( [Parameter(Mandatory = $false)] [string]$Release = 'focal', [Parameter(Mandatory = $false)] [ValidateSet('1', '2')] [string]$Version = '2', [Parameter(Mandatory = $false)] [switch]$Force, [Parameter(Mandatory = $false)] [switch]$NoUpdate, [Parameter(Mandatory = $false)] [switch]$NoUpgrade, [Parameter(Mandatory = $false)] [switch]$RootOnly, [Parameter(Mandatory = $false)] [string]$AdditionalPPA, [Parameter(Mandatory = $false)] [switch]$EnableSource, [Parameter(Mandatory = $false)] [switch]$EnableProposed, [Parameter(Mandatory = $false)] [switch]$DisableSelective, [Parameter(Mandatory = $false)] [switch]$AptOutput, [Parameter(Mandatory = $false)] [switch]$Silent, [Parameter(Mandatory = $false)] [switch]$NonInteractive, [Parameter(Mandatory = $false)] [string]$AdditionalPkg ) Process { function Write-IfNotSilent { [cmdletbinding()] Param ( [Parameter(Mandatory = $true)] [string]$Text ) if (-not $Silent) { Write-Host "# $Text" -ForegroundColor DarkYellow } } function Stop-Honking { if ($AptOutput -and (-not $Silent)) { return "" } else { return "-qq" } } Write-IfNotSilent "Let the journey begins!" $TmpName = -join ((65..90) + (97..122) | Get-Random -Count 10 | ForEach-Object { [char]$_ }) $SysArchName = ($env:PROCESSOR_ARCHITECTURE).ToLower() if ( -not ( ( $SysArchName -eq "amd64" ) -or ( $SysArchName -eq "arm64" ) ) ) { throw [System.NotSupportedException] "The architecture $SysArchName is not supported." } if ( ( $Release -eq "xenial" ) -and ( $SysArchName -eq "arm64" ) ) { throw [System.NotSupportedException] "Ubuntu Xenial does not support architecture arm64." } Write-IfNotSilent "Your system architecture is $SysArchName" $HomePath = $env:HOME if (-not $HomePath) { $HomePath = "$($env:HOMEDRIVE)$($env:HOMEPATH)" } if ( -not (Test-Path -Path "$HomePath\.mbw" -PathType Container ) ) { mkdir -Path "$HomePath\.mbw" | Out-Null } if ( -not (Test-Path -Path "$HomePath\.mbw\.tarball" -PathType Container ) ) { mkdir -Path "$HomePath\.mbw\.tarball" | Out-Null } if ( Test-Path -LiteralPath "$HomePath\.mbw\.tarball\$Release-$SysArchName.tar.gz" -PathType Leaf ) { if ( $Force ) { Write-IfNotSilent "WSL tarball for $Release($SysArchName) found but -Force passed. Redownloading..." $download_start_time = Get-Date Invoke-WebRequest -Uri "http://cloud-images.ubuntu.com/$Release/current/$Release-server-cloudimg-$SysArchName-wsl.rootfs.tar.gz" -OutFile "$HomePath\.mbw\.tarball\$Release-$SysArchName.tar.gz" Write-IfNotSilent "Download completed for the WSL tarball for $Release($SysArchName). Time taken: $((Get-Date).Subtract($download_start_time).Seconds) second(s)" } else { Write-IfNotSilent "WSL tarball for $Release ($SysArchName) found, skip downloading" } } else { Write-IfNotSilent "WSL tarball for $Release ($SysArchName) not found. Downloading..." $download_start_time = Get-Date Invoke-WebRequest -Uri "http://cloud-images.ubuntu.com/$Release/current/$Release-server-cloudimg-$SysArchName-wsl.rootfs.tar.gz" -OutFile "$HomePath\.mbw\.tarball\$Release-$SysArchName.tar.gz" Write-IfNotSilent "Download completed for the WSL tarball for $Release($SysArchName). Time taken: $((Get-Date).Subtract($download_start_time).Seconds) second(s)" } # get absolute unique TmpName Do { $tmpname_exist = $false foreach ($i in $inst_list) { if ($i.ID -eq "$TmpName") { $tmpname_exist = $true } } if ( $tmpname_exist -eq $true ) { $TmpName = -join ((65..90) + (97..122) | Get-Random -Count 10 | ForEach-Object { [char]$_ }) } } until ($tmpname_exist -eq $false) Write-IfNotSilent "Creating instance ubuntu-$TmpName (Using Ubuntu $Release and WSL$Version)...." wsl.exe --import ubuntu-$TmpName "$HomePath\.mbw\ubuntu-$TmpName" "$HomePath\.mbw\.tarball\$Release-amd64.tar.gz" if (-not (wsl.exe --set-version ubuntu-$TmpName $Version)){ Write-IfNotSilent "You are using a system that do not support WSL2, keep in WSL1" } if ($EnableSource) { Write-IfNotSilent "Enabling Ubuntu source repository...." Write-IfNotSilent "-NoUpdate will be ignored if passed" wsl.exe -d ubuntu-$TmpName sed -i `"s`|`# deb-src`|deb-src`|g`" /etc/apt/sources.list } if ($EnableProposed) { Write-IfNotSilent "Enabling Ubuntu Proposed repository...." Write-IfNotSilent "-NoUpdate will be ignored if passed" wsl.exe -d ubuntu-$TmpName echo -e `"`# Enable Ubuntu proposed archive\ndeb http`://archive.ubuntu.com/ubuntu/ `$`(lsb_release `-cs`)-proposed restricted main multiverse universe`" `> /etc/apt/sources.list.d/ubuntu-`$`(lsb_release `-cs`)-proposed.list if ( $SysArchName -eq "arm64" ) { wsl.exe -d ubuntu-$TmpName echo -e `"`# Enable Ubuntu proposed archive\ndeb http`://ports.ubuntu.com/ubuntu-ports `$`(lsb_release `-cs`)-proposed restricted main multiverse universe`" `> /etc/apt/sources.list.d/ubuntu-`$`(lsb_release `-cs`)-proposed.list } if (-not $DisableSelective) { wsl.exe -d ubuntu-$TmpName echo -e `"`# Configure apt to allow selective installs of packages `from proposed\nPackage: `*\nPin`: release a`=`$`(lsb_release `-cs`)-proposed\nPin-Priority`: 400`" `>`> /etc/apt/preferences.d/proposed-updates } } $quiet_param = Stop-Honking if ( -not $NoUpdate -or ($EnableSource -or $EnableProposed) ) { Write-IfNotSilent "Updating ubuntu-$TmpName...." wsl.exe -d ubuntu-$TmpName apt-get update $quiet_param | Out-Host if (-not $NoUpgrade){ wsl.exe -d ubuntu-$TmpName apt-get upgrade -y $quiet_param | Out-Host } } if ((-not $RootOnly) -or (-not $NonInteractive)) { Write-IfNotSilent "Creating user '$env:USERNAME' for ubuntu-$TmpName...." wsl.exe -d ubuntu-$TmpName /usr/sbin/useradd -m -s "/bin/bash" $env:USERNAME wsl.exe -d ubuntu-$TmpName passwd -q -d $env:USERNAME wsl.exe -d ubuntu-$TmpName echo `"$env:USERNAME ALL=`(ALL`:ALL`) NOPASSWD: ALL`" `| tee -a /etc/sudoers.d/$env:USERNAME `>/dev/null wsl.exe -d ubuntu-$TmpName /usr/sbin/usermod -a -G adm,dialout,cdrom,floppy,sudo,audio,dip,video,plugdev,netdev $env:USERNAME } if ($AdditionalPPA) { $ppa_array = $AdditionalPPA -split "," foreach ($appa in $ppa_array) { Write-IfNotSilent "Adding additional PPA '$appa'...." wsl.exe -d ubuntu-$TmpName /usr/bin/apt-add-repository -y "ppa:$appa" | Out-Host wsl.exe -d ubuntu-$TmpName apt-get update $quiet_param | Out-Host wsl.exe -d ubuntu-$TmpName apt-get upgrade -y $quiet_param | Out-Host } } if ($AdditionalPkg) { $pkg_array = $AdditionalPkg -split "," foreach ($apkg in $pkg_array) { Write-IfNotSilent "Adding package '$apkg'...." wsl.exe -d ubuntu-$TmpName apt-get install $quiet_param -y $apkg | Out-Host } } if ( -not $RootOnly ) { $tmp_dis_name = (Get-ChildItem HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\ | Get-ItemProperty | Where {$_.'DistributionName' -eq "ubuntu-$TmpName"})[0].PSChildName Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\$tmp_dis_name" -Name DefaultUid -Value 1000 -Force } Write-IfNotSilent "You are ready to rock!" if ($NonInteractive) { return "$TmpName" } else { wsl.exe -d ubuntu-$TmpName } } } function Remove-UbuntuWSLInstance { <# .SYNOPSIS Remove an Ubuntu instance on WSL .DESCRIPTION Remove an Ubuntu instance on WSL .PARAMETER Id The ID of the instance, after the name of distro "ubuntu-". .EXAMPLE Remove-UbuntuWSLInstance -Id AbcdEFGhiJ # Remove an instance called ubuntu-AbcdEFGhiJ .LINK https://github.com/patrick330602/PsUWI #> [cmdletbinding()] Param ( [Parameter(Mandatory = $true)] [string]$Id ) Process { $HomePath = $env:HOME if (-not $HomePath) { $HomePath = "$($env:HOMEDRIVE)$($env:HOMEPATH)" } if ( -not ( Get-ChildItem "$HomePath\.mbw" | Select-String "$Id" ) ) { throw [System.IO.FileNotFoundException] "$Id not found." } Write-Host "# Removing instance ubuntu-$Id..." -ForegroundColor DarkYellow Write-Host "# Terminating instance ubuntu-$Id..." -ForegroundColor DarkYellow wsl.exe -t ubuntu-$Id Write-Host "# Unregistering instance ubuntu-$Id..." -ForegroundColor DarkYellow wsl.exe --unregister ubuntu-$Id Write-Host "# Cleanup..." -ForegroundColor DarkYellow Remove-Item "$HomePath\.mbw\ubuntu-$Id" -Force -Recurse Remove-Item "$Env:AppData\Microsoft\Windows\Start Menu\Programs\ubuntu-$Id" -Force -Recurse Write-Host "# Removed instance ubuntu-$Id." -ForegroundColor DarkYellow } } function Remove-AllUbuntuWSLInstances { <# .SYNOPSIS Remove all Ubuntu instances on WSL .DESCRIPTION Remove all Ubuntu instances on WSL .EXAMPLE Remove-AllUbuntuWSLInstances # Remove all instances .LINK https://github.com/patrick330602/PsUWI #> $HomePath = $env:HOME if (-not $HomePath) { $HomePath = "$($env:HOMEDRIVE)$($env:HOMEPATH)" } Write-Host "# Removing all instances..." -ForegroundColor DarkYellow $UbuntuDistroList = @(Get-ChildItem "$HomePath\.mbw" -Filter ubuntu-*) Foreach ($i in $UbuntuDistroList) { Remove-UbuntuWSLInstance -Id ($i.BaseName).split('-')[1] } Write-Host "# Removed all instances." -ForegroundColor DarkYellow } |