Public/Invoke-WslCommand.ps1
|
<#
.SYNOPSIS Executes a command in a specified WSL distribution. .DESCRIPTION This function executes a specified command in a given Windows Subsystem for Linux (WSL) distribution. It allows you to specify the distribution, user, and whether to run the command as an administrator. .PARAMETER Command The command to execute in the WSL distribution. .PARAMETER Distro The name of the WSL distribution in which to execute the command (e.g., "Ubuntu-20.04", "Debian"). .PARAMETER User Optional. The user under which to execute the command in the WSL distribution. If not specified, the default user for the distribution will be used. .PARAMETER Password Optional. A secure string representing the password for the specified user. This is required if you want to run the command as a different user and the distribution requires authentication. .PARAMETER AsAdmin Optional. A switch to indicate that the command should be executed with administrative privileges in the WSL distribution. .PARAMETER Shell Optional. The shell to use for executing the command. Default is "/bin/sh". You can specify other shells like "/bin/bash", "/bin/zsh", etc., if they are available in the distribution. .PARAMETER ShellType Optional. Specifies the type of shell to use. Valid values are "Login", "Standard", or "None". This parameter affects how the shell initializes the environment. .EXAMPLE # Execute a command in the Ubuntu-20.04 distribution Invoke-WslCommand -Command "ls -la" -Distro "Ubuntu-20.04" # Execute a command as a specific user in the Debian distribution Invoke-WslCommand -Command "whoami" -Distro "Debian" -User "myuser" -Password (ConvertTo-SecureString "mypassword" -AsPlainText -Force) .NOTES Requires WSL to be installed and the specified distribution to be available. Ensure you have the necessary permissions to perform this operation. .COMPONENT Windows Subsystem for Linux (WSL) #> function Invoke-WslCommand { param ( [Parameter(Mandatory = $false, Position = 0)] [string]$Command, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) Get-WslDistribution -Distribution "$wordToComplete*" | ForEach-Object { $_.Distribution } })] [Alias("Distro", "Name")] [string]$Distribution, [Parameter(Mandatory = $false)] [string]$User, [Parameter(Mandatory = $false)] [SecureString]$Password, [Parameter(Mandatory = $false)] [switch]$AsAdmin, [Parameter(Mandatory = $false)] # Get available shell directly from WSL [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 $AvavilableDisk = (Invoke-WslCommand -System -Command "awk '/^\// {print}' /etc/shells") -split "`n" | ForEach-Object { $_.Trim() } $AvavilableDisk | Where-Object { $_ -like "$wordToComplete*" } })] [string]$Shell = "/bin/sh", [Parameter(Mandatory = $false)] [ValidateSet("Login", "Standard", "None")] [string]$ShellType, [Parameter(Mandatory = $false)] [switch]$System ) process { $PsStandardArgs = @($PSBoundParameters.GetEnumerator()) $WslArgs = $PsStandardArgs | Remove-StdPsArgsFromWslArgs -ErrorAction Stop -ArgToRemove @('Command', 'Shell', 'Distribution') | Convert-PsArgsToWsl -ErrorAction Stop $WslDistro = if ((-not $System) -and (-not $Distribution)) { Write-Verbose "No distribution specified. Using the default WSL distribution." $Elem = Get-WslDistribution -Default $Distribution = $Elem.Distribution $Elem } else { Get-WslDistribution -Distribution $Distribution -ErrorAction SilentlyContinue } if (-not $WslDistro) { 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 }) } $StdErr, $StdOut, $Res = Invoke-WslCmdWrapper -WslArgs $WslArgs -Command $Command -Shell $Shell if ($Res -ne 0) { $DistributionDisplay = if ($Distribution) { $Distribution } else { "(default)" } throw (New-WslErrorRecord @{ Message = "WSL command execution failed" ErrorId = "PowerShellWSLCommandFailed" Distribution = $DistributionDisplay WslArgs = ($WslArgs -join ' ') ExitCode = $Res StdErr = ($StdErr | Out-String).Trim() WslVersion = (Get-WslStatus -ErrorAction SilentlyContinue).WSL }) } ($StdOut -split "`n" | ConvertTo-CleanedWslString) -join "`n" } } |