Public/Add-WslLocalDisk.ps1
|
<#
.SYNOPSIS Mounts a local device in a WSL distribution. .DESCRIPTION This function mounts a specified local device (e.g., a physical disk or a VHD file) in a given Windows Subsystem for Linux (WSL) distribution. It allows you to specify the distribution, the device to mount, the filesystem type, mount options, and whether to mount a specific partition or the entire device. .PARAMETER Disk The path to the local device to mount (e.g., "\\.\PHYSICALDRIVE1" for a physical disk or "C:\path\to\disk.vhdx" for a VHD file). .PARAMETER FsType Optional. The filesystem type to use for mounting the device (e.g., "ext4", "ntfs"). If not specified, WSL will attempt to auto-detect the filesystem type. .PARAMETER Options Optional. Additional mount options to pass to the mount command (e.g., "ro" for read-only). This can be a comma-separated list of options. .PARAMETER PartitionIdx Optional. The index of the partition to mount on the device. If not specified, the entire device will be mounted. .PARAMETER Bare Optional. A switch to indicate that the device should be mounted without any additional options or configurations .PARAMETER Vhd Optional. A switch to indicate that the device being mounted is a VHD file. This will ensure that WSL treats the device as a virtual disk and handles it accordingly. .COMPONENT Windows Subsystem for Linux (WSL) .NOTES Requires WSL to be installed and the specified distribution to be running. Ensure you have the necessary permissions to perform this operation, especially when mounting physical disks or VHD files. #> function Add-WslLocalDisk { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipelineByPropertyName = $true)] [ValidateScript({ (Get-CimInstance Win32_DiskDrive | Where-Object { $_.DeviceID -eq $_ }).Count -lt 1 })] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) # Get the list of disk drives from the system and filter based on the user's input Get-CimInstance Win32_DiskDrive | Where-Object { $_.DeviceID -like "$wordToComplete*" } | ForEach-Object { $_.DeviceID } })] $Disk, [Parameter(Mandatory = $true, Position = 1, ValueFromPipelineByPropertyName = $true)] # Custom completion logic for filesystem types based on WSL output [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $DistributionName = $fakeBoundParameters['Distribution'] if (-not $DistributionName) { $DistributionName = Get-WslDistribution -Default | Select-Object -ExpandProperty Distribution } # Get the list of supported filesystem types from the specified WSL distribution $SupportedFsTypes = (Invoke-WslCommand -System -Command "cat /proc/filesystems | awk '!/nodev/ {print `$1}'") -split "`n" | ForEach-Object { $_.Trim() } $SupportedFsTypes | Where-Object { $_ -like "$wordToComplete*" } })] [string]$FsType, [Parameter(Mandatory = $false)] [string]$Options, [Parameter(Mandatory = $false)] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $CurrentDisk = $fakeBoundParameters['Disk'] if (-not $CurrentDisk) { return } # Get the list of partitions for the specified disk Get-Partition -DiskNumber ($CurrentDisk -replace "\\\\\.\\PHYSICALDRIVE", "") -ErrorAction SilentlyContinue | Select-Object -ExpandProperty PartitionNumber | Where-Object { $_ -like "$wordToComplete*" } })] [int]$PartitionIdx, [Parameter(Mandatory = $false)] [switch]$Bare, [Parameter(Mandatory = $false)] [switch]$Vhd ) process { $LegacyArgs = $PSBoundParameters.GetEnumerator() | ForEach-Object { if ($_.Key -eq "FsType") { @{ Key = "Type"; Value = $_.Value.ToString() } } elseif ($_.Key -eq "PartitionIdx") { @{ Key = "Partition"; Value = $_.Value } } else { $_ } } # get argsoument normalized to WSL command line format $WslArgs = $LegacyArgs | Remove-StdPsArgsFromWslArgs -ArgToRemove @("Distribution", "Disk") | Convert-PsArgsToWsl # Check if the distribution is running $CurrentDistro = Get-WslDistribution -Distribution $Distribution -ErrorAction SilentlyContinue if (-not $CurrentDistro) { throw (New-WslErrorRecord @{ Message = "WSL distribution not found." ErrorId = "PowerShellWSLDistributionNotFound" Distribution = $Distribution WslArgs = ($WslArgs -join ' ') ExitCode = $null StdErr = $null WslVersion = (Get-WslStatus -ErrorAction SilentlyContinue).WSL }) } # Mount the virtual file system Write-Information "Mounting WSL virtual file system for distribution '$Distribution' at '$MountPoint'..." $StdErr, $StdOut, $Res = Invoke-WslCmdWrapper -WslArgs @('--mount', $Disk, $WslArgs) -ErrorAction Stop if ($Res -ne 0) { throw (New-WslErrorRecord @{ Message = "Failed to mount local disk in WSL with message: '$StdErr'" ErrorId = "PowerShellWSLMountDiskFailed" Distribution = $Distribution WslArgs = @('--mount', $Disk, $WslArgs) -join ' ' ExitCode = $Res StdErr = ($StdErr | Out-String).Trim() WslVersion = (Get-WslStatus -ErrorAction SilentlyContinue).WSL }) } else { Write-Information "Successfully mounted WSL for distribution '$Distribution'." } } } |