Public/Export-WslVhdToFile.ps1
|
<#
.SYNOPSIS Exports a WSL installed distribution to a specified file. .DESCRIPTION This function exports a specified installed Windows Subsystem for Linux (WSL) distribution to a file. So that you can have a backup of your WSL distribution or move it to another machine. It allows you to specify the distribution name, destination file path, additional options, and the export format via '-FormatAs' parameter. .PARAMETER Distribution The name of the WSL distribution to export (e.g., "Ubuntu-20.04", "Debian"). .PARAMETER Destination The file path where the exported distribution will be saved. This can be a local path or a network path. Ensure that you have write permissions to the specified location. .PARAMETER FormatAs Optional. Specifies the format in which to export the WSL distribution. Valid values are "tar", "vhdx", "tar.gz", "tar.vz", and "tar.xz". The default format is "tar". .PARAMETER AdditionalOptions Optional. Additional command-line options to pass to the 'wsl.exe --export' command #> function Export-WslVhdToFile { [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) Get-WslDistribution -Distribution "$wordToComplete*" | ForEach-Object { $_.Distribution } })] [string]$Distribution, [Parameter(Mandatory = $false)] [string]$Destination, [Parameter(Mandatory = $false)] [ValidateSet("tar", "vhdx", "tar.gz", "tar.vz", "tar.xz")] [string]$FormatAs, [Parameter(Mandatory = $false)] [string]$AdditionalOptions ) process { if (-not $Distribution) { Write-Verbose "No distribution name specified. Using the default WSL distribution." $WslDefaultDistro = Get-WslDistribution -Default -ErrorAction SilentlyContinue $Distribution = $WslDefaultDistro.Distribution } if (-not $Destination) { $Destination = "$PWD\$Distribution-$(Get-Date -Format 'yyyyMMdd-HHmmss').tar" } $CurrentDistro = Get-WslDistribution -Distribution $Distribution -ErrorAction SilentlyContinue if (-not $CurrentDistro) { throw (New-WslErrorRecord @{ Message = "WSL distribution not installed." ErrorId = "PowerShellWSLDistributionNotInstalled" Distribution = $Distribution WslArgs = "--export $Distribution $Destination $AdditionalOptions --format $FormatAs" ExitCode = $null StdErr = $null WslVersion = (Get-WslStatus -ErrorAction SilentlyContinue).WSL }) } else { if ($CurrentDistro.Status -eq [WslDistributionStatus]::Running) { Write-Warning "'$Distribution' is currently running. Shutting down..." Stop-WslDistribution -Distribution $Distribution -ErrorAction Stop } } $DestExtension = [System.IO.Path]::GetExtension($Destination).TrimStart('.').ToLower() if (-not $FormatAs) { # TODO: need to be rewrites if ($DestExtension -and ($DestExtension -in @("tar", "vhdx", "tar.gz", "tar.vz", "tar.xz"))) { Write-Verbose "No export format specified. Using: '$DestExtension' from '$Destination'." $FormatAs = $DestExtension } else { Write-Verbose "No export format specified. Defaulting to 'tar' format." $FormatAs = "tar" } } else { if ($DestExtension -ne $FormatAs) { Write-Warning "Extensions '-Destination' ('$DestExtension') and -FormatAs ('$FormatAs') mismatch. Using '-FormatAs' value instead." $Destination = [System.IO.Path]::ChangeExtension($Destination, $FormatAs) } } Write-Information "Exporting WSL distribution '$Distribution' to file '$Destination'..." $StdErr, $StdOut, $Res = Invoke-WslCmdWrapper -WslArgs @('--export', $Distribution, $Destination, $AdditionalOptions, '--format', $FormatAs) -ErrorAction Stop if ($Res -ne 0) { throw (New-WslErrorRecord @{ Message = "Failed to export WSL distribution with message: '$StdErr'" ErrorId = "PowerShellWSLExportFailed" Distribution = $Distribution WslArgs = @('--export', $Distribution, $Destination, $AdditionalOptions, '--format', $FormatAs) -join ' ' ExitCode = $Res StdErr = ($StdErr | Out-String).Trim() WslVersion = (Get-WslStatus -ErrorAction SilentlyContinue).WSL }) } else { Write-Information "Successfully exported WSL distribution '$Distribution' to file '$Destination'." } } } |