You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Current »

move-wsl.ps1
Set-StrictMode -Version latest;

function Cleanup()
{
    # Remove temporary file
    Write-Host "Cleaning up ...";
    Remove-Item -ErrorAction Ignore $tempFile;
}

# function to get distros
function Get-Distros()
{
    # wsl seems to output Unicode always. When parsing results in PowerShell it will try to convert
    # to Unicode strings (again) assuming it's in the Console.OutputEncoding code page (437 in my case).
    # This causes incorrect results. We are forcing Console.OutputEncoding to be Unicode here
    # to avoid the unnecessary conversion.
    $consoleEncoding = [Console]::OutputEncoding;
    [Console]::OutputEncoding = [System.Text.Encoding]::Unicode;
    $result = wsl -l -v | ConvertFrom-String -PropertyNames SELECTED, NAME, STATE, VERSION | Select-Object -Skip 1;
    [Console]::OutputEncoding = $consoleEncoding;

    return $result;
}

# get and make sure there are distros
Write-Host 'Getting distros...';
$distros = @(Get-Distros);
$distroList = @($distros | ForEach-Object { $_.NAME });
if ($distroList.Length -le 0)
{
    Write-Error 'No distro found';
    Exit 1;
}

# prompt and get the distro to move
Write-Host "Select distro to move:";
$id = 0;
$distroList | ForEach-Object { Write-Host "$($id+1): $($distroList[$id])" -ForegroundColor Yellow; $id++; }
$selected = [int](Read-Host);
if (($selected -gt $distroList.Length) -or ($selected -le 0))
{
    Write-Error "Invalid selection. Select a distro from 1 to $($distroList.Length)";
    Exit 1;
}
$distro = $distroList[$selected - 1];

# get target directory
Write-Host 'Enter WSL target directory:';
$targetFolder = Read-Host;

# check if the target folder is the root of a drive
if ($targetFolder.Length -le 3 -and $targetFolder.EndsWith(':\'))
{
    Write-Error 'Target folder cannot be root of a drive';
    Exit 1;
}

$targetFolder = $targetFolder.trimend('\');

# confirm
$confirm = Read-Host "Move $($distro) to `"$($targetFolder)`"? (Y|n)";
if ($confirm -ne 'Y')
{
    Write-Error 'User canceled';
    Exit 1;
}

# Create target dir if non existent
if (-not(Test-Path $targetFolder))
{
    New-Item -Path $targetFolder -ItemType 'directory' | Out-Null;
    if (-not($?))
    {
        Write-Error "Failed to create target folder `"$($targetFolder)`"";
        Exit 1;
    }
} elseif (Test-Path (-join($targetFolder, "\ext4.vhdx")))
{
    Write-Error "Target folder already contains an ext4.vhdx file that will get overwritten. Aborting.";
    Exit 1;
}

# Export WSL image to tar file
$tempFile = Join-Path $targetFolder "$($distro).tar";
Write-Host "Exporting VHDX to `"$($tempFile)`" ...";
& cmd /c wsl --export $distro "`"$tempFile`"";
if (-not($? -and (Test-Path $tempFile -PathType Leaf)))
{
    Write-Error "ERROR: Export failed";
    Cleanup;
    Exit 2;
}

# Unregister WSL so we can register it again at new location
Write-Host "Unregistering WSL ..."
& cmd /c wsl --unregister $distro | Out-Null

# Importing WSL at new location
Write-Host "Importing $distro from $targetFolder..."
& cmd /c wsl --import $distro $targetFolder "`"$tempFile`"" --version $distros[$selected -1].VERSION;

# Validating
$newDistros = @(Get-Distros);
$newDistroList = @($newDistros | ForEach-Object { $_.NAME });
if ($newDistroList -notcontains $distro)
{
    Write-Error "Import failed. Distro not found. Export file at $tempFile";
    Exit 3;
}

if (-not(Test-Path "$($targetFolder)\ext4.vhdx") -And -not(Test-Path "$($targetFolder)\rootfs"))
{
    Write-Error "ERROR: Import failed. Target file/folder not found. Export file at $tempFile";
    Exit 4;
}

Cleanup;

Write-Host "Done!" -ForegroundColor Green;



  • Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
  • No labels