Skip to content

Simple PowerShell script as a helper or tool to help you export WSL distro

License

Notifications You must be signed in to change notification settings

austin-lai/Export_WSL_Distro_with_Powershell_Script

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 

Repository files navigation

Export WSL Distro with Powershell Script

> Austin.Lai |
> -----------| October 26th, 2023
> -----------| Updated on November 10th, 2023

Table of Contents


Disclaimer

DISCLAIMER:

This project/repository is provided "as is" and without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.

This project/repository is for Educational purpose ONLY. Do not use it without permission. The usual disclaimer applies, especially the fact that me (Austin) is not liable for any damages caused by direct or indirect use of the information or functionality provided by these programs. The author or any Internet provider bears NO responsibility for content or misuse of these programs or any derivatives thereof. By using these programs you accept the fact that any damage (data loss, system crash, system compromise, etc.) caused by the use of these programs is not Austin responsibility.


Description

Simple PowerShell script as a helper or tool to help you export WSL distro.

Note:

  • The configurations in this project/repository are for your reference:
    • Docker Desktop is running and configured as start on boot.
    • Assuming you have installed Docker Desktop at "C:\Program Files\Docker\Docker\Docker Desktop.exe".
    • A default path of "C:\Users\$env:UserName\Desktop" is used as destination.
  • A powershell script file:
  • Please change the configuration accordingly to suits your environment.

export-wsl-distro

The export-wsl-distro.ps1 file can be found here or below:

Click here to expand and check out the powershell script !!!
function Check-IsElevated {
  $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
  $p = New-Object System.Security.Principal.WindowsPrincipal($id)
  if ($p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Write-Output $true
  }
  else {
    Write-Output $false
  }
}



# Define the function with a parameter for the process name to quit Docker Desktop
function StopProcessByName ($processName) {

  # Check if the process is running
  $process = Get-Process -Name $processName -ErrorAction SilentlyContinue

  # If the process is running, stop it and display a message
  if ($process) {

    Stop-Process -Name $processName

    Write-Host "`n [:::Information:::] The process $processName has been stopped" -ForegroundColor Blue -BackgroundColor Black 

    Start-Sleep -Seconds 10

  } else {

    # If the process is not running, display a message
    Write-Host "`n [:::Information:::] The process $processName is not running" -ForegroundColor Blue -BackgroundColor Black 

  }
}



# Define the function to check for specific errors for Shutting down "Docker Desktop" and "WSL" and retry
function CheckErrorAndRetry {
  
    # Define the command to shutdown WSL
    $ShutdownWSL = "wsl --shutdown"
  
    # Define the command to export the WSL distribution to a VHD file
    # Use string interpolation to build the WSL export command
    $wslExportCommand = "wsl --export $selectedDistro $exportPath --vhd"

    Write-Host "`n [:::Action:::] Shutting down `"Docker Desktop`" ........." -ForegroundColor Magenta -BackgroundColor Black

    # Call the function with the process name to quit Docker Desktop as an argument
    StopProcessByName "Docker Desktop"

    $StopProcessByName_Status = $?

    Write-Host "`n [:::Action:::] Shutting down WSL ........." -ForegroundColor Magenta -BackgroundColor Black

    Invoke-Expression $ShutdownWSL

    $ShutdownWSL_Status = $?

    Start-Sleep -Seconds 10

    if ($ShutdownWSL_Status -and $StopProcessByName_Status ){

        Write-Host "`n [:::Information:::] Exporting the selected WSL distro ........." -ForegroundColor Blue -BackgroundColor Black

        $output = Invoke-Expression $wslExportCommand 2>&1

        # Check for specific error conditions
        if ($output -match "cannot access the file" -or $output -match "Error code" -or $output -match "used by another process") {

            # -ForegroundColor White -BackgroundColor DarkMagenta 
            Write-Host "`n [:::Warning:::] $output" -ForegroundColor White -BackgroundColor DarkRed

            # -ForegroundColor White -BackgroundColor DarkMagenta 
            Write-Host "`n [:::Warning:::] Failed to export WSL distribution. Please check the distribution name and export path." -ForegroundColor White -BackgroundColor DarkRed

            return
        }

    }

}



# Define the function to start "Docker Desktop" process or service
function StartDockerDesktop {

    Start-Process -FilePath "C:\Program Files\Docker\Docker\Docker Desktop.exe" -WindowStyle Normal

    if ($?){
            Write-Host "`n [:::Information:::]  `"Docker Desktop`" start and run correctly." -ForegroundColor Blue -BackgroundColor Black

    } else {

        Write-Host "`n [:::Warning:::] `"Docker Desktop`" does not start and run correctly. Re-run starting `"Docker Desktop`" process." -ForegroundColor White -BackgroundColor DarkRed

        StartDockerDesktop

        Start-Sleep -Seconds 10

    }

}



if (Check-IsElevated) {

    ################################################
    # Preperation to export wsl distro to vhdx
    ################################################

    # List down available WSL distros
    $WSL_Distro_List = wsl -l -q | Where-Object { $_ -ne "" }

    # Write-Host "`nAvailable WSL Distros:"
    Write-Host "`n Available WSL Distros: `n" -ForegroundColor Yellow -BackgroundColor Black 

    $WSL_Distro_List | ForEach-Object { Write-Host " * $_ " -ForegroundColor Yellow -BackgroundColor Black }

    $validDistro = $false

    do {

        $default_selectedDistro = "kali-linux"

        # Prompt the user to choose a WSL distro
        $selectedDistro = Read-Host "`n Enter the name of the distro you want to export or press `"Enter`" to use the default selected disro ( $default_selectedDistro )"

        if ($selectedDistro -eq "") {

          $selectedDistro = $default_selectedDistro
          
        }
        
        # Validate user input, must be from the list
        if ($WSL_Distro_List -contains $selectedDistro) {

            # Valid input, set $validDistro = $true and exit the loop
            $validDistro = $true

            break
        }
        else {
          
            $validDistro = $false

            # Invalid input, display an error message and repeat the loop
            Write-Host "`n [:::Warning:::] Invalid distro choice. Please select a valid distro from the list." -ForegroundColor White -BackgroundColor DarkRed

        }
    }
    while ($true)

    # Display the selected distro to user
    Write-Host "`n [:::Information:::] You have selected `"$selectedDistro`" WSL distro !" -ForegroundColor Blue -BackgroundColor Black 

    # Add Date variable with DDMMYYYY format
    $Date = Get-Date -Format "ddMMyyyy-HHmm"

    # Define the default path to be used to save the VHDX file
    $defaultPath = "C:\Users\$env:UserName\Desktop"


    # Prompt user to enter the path where the VHDX file will be saved
    $exportPath = Read-Host -Prompt "`n Enter the path where you want to save the VHDX file or press `"Enter`" to use the default path ( $defaultPath )"

    if ($exportPath -eq "") {
        $exportPath = $defaultPath
    }

    Write-Host "`n [:::Information:::] The VHDX file will be saved at: `"$exportPath\$selectedDistro-$Date.vhdx`" " -ForegroundColor Blue -BackgroundColor Black 

    # Combine all the variable for exported path with the format of "exportPath\$selectedDistro-$Date.vhdx"
    $exportPath = [System.IO.Path]::Combine($exportPath, "$selectedDistro-$Date.vhdx")

    # Define the command to shutdown WSL
    $ShutdownWSL = "wsl --shutdown"

    # Define the command to export the WSL distribution to a VHD file
    # Use string interpolation to build the WSL export command
    $wslExportCommand = "wsl --export $selectedDistro $exportPath --vhd"

    # Check if the chosen distro is in the list, if yes then run the function of CheckErrorAndRetry
    if ($validDistro -eq $true) {

        # Initial run of the command
        CheckErrorAndRetry

        $CheckErrorAndRetry_Status = $?

    } else {

        Write-Host "" -ForegroundColor White -BackgroundColor DarkRed

    }

    # Check if the function of CheckErrorAndRetry is running correctly, if not re-run it
    $export_status = $false
    # if ($CheckErrorAndRetry_Status = $?){
    if ($CheckErrorAndRetry_Status -eq $true){

        Start-Sleep -Seconds 10
            
        if (Test-Path $exportPath) {

            Write-Host "`n [:::Information:::] $exportPath exists." -ForegroundColor Blue -BackgroundColor Black

            Write-Host "`n [:::Information:::] Exported $selectedDistro to $exportPath" -ForegroundColor Blue -BackgroundColor Black 

            Write-Host "`n [:::Information:::] Set `$export_status to `$true" -ForegroundColor Blue -BackgroundColor Black 

            $export_status = $true

        } else {

            Write-Host "`n [:::Warning:::] $exportPath does not exist." -ForegroundColor White -BackgroundColor DarkRed

            Write-Host "`n [:::Warning:::] Re-run CheckErrorAndRetry." -ForegroundColor White -BackgroundColor DarkRed

            $export_status = $false

            CheckErrorAndRetry
        }

    } else {

        Write-Host "`n [:::Warning:::] CheckErrorAndRetry_Status return failed and Re-run CheckErrorAndRetry." -ForegroundColor White -BackgroundColor DarkRed

        Write-Host "`n [:::Information:::] Set `$export_status to `$false" -ForegroundColor Blue -BackgroundColor Black

        $export_status = $false

        CheckErrorAndRetry
    }

    # Check if the function of CheckErrorAndRetry is running correctly and the $export_status is set to $true
    # Clean-up
    if ($export_status = $true){
        
        Start-Sleep -Seconds 10

        Write-Host "`n [:::Information:::] Starting `"Docker Desktop`" process." -ForegroundColor Blue -BackgroundColor Black

        StartDockerDesktop

    }

}
else {

  # prompt the user to use elevated powershell and exit the script
  Write-Host "`n [:::Warning:::] Please run this script as Administrator.`n" -ForegroundColor Blue -BackgroundColor Black

  exit

}

About

Simple PowerShell script as a helper or tool to help you export WSL distro

Topics

Resources

License

Stars

Watchers

Forks