Commands/Web/Eigenverft.Manifested.Package.Cmd.OpenUrlInBrowser.ps1
|
function Open-UrlInBrowser { <# .SYNOPSIS Opens local files or web URLs in the default or a selected browser. .DESCRIPTION Resolves each input as an existing local file or an absolute HTTP, HTTPS, or file URI. Supports Windows, macOS, and Linux in Windows PowerShell 5.1 and PowerShell 7+. .PARAMETER Browser Uses the operating-system default browser unless Edge, Chrome, Firefox, or Safari is selected. .PARAMETER BrowserPath Uses an explicit browser executable, command, or macOS application name/path. .EXAMPLE Open-UrlInBrowser -Path 'https://example.org' .EXAMPLE Open-UrlInBrowser -Path '.\report.html' .EXAMPLE Open-UrlInBrowser -Path 'https://example.org' -Browser Edge -Wait #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [Alias('FullName', 'LiteralPath')] [ValidateNotNullOrEmpty()] [string[]]$Path, [switch]$Wait, [ValidateSet('Default', 'Edge', 'Chrome', 'Firefox', 'Safari')] [string]$Browser = 'Default', [AllowNull()] [string]$BrowserPath = $null ) function local:Get-BrowserPlatform { [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseApprovedVerbs', '')] param() $runtimeInformationType = [type]::GetType('System.Runtime.InteropServices.RuntimeInformation') if ($runtimeInformationType) { return [pscustomobject]@{ Windows = [System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Windows) MacOS = [System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::OSX) Linux = [System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Linux) } } $windows = [string]::Equals([string]$env:OS, 'Windows_NT', [System.StringComparison]::OrdinalIgnoreCase) return [pscustomobject]@{ Windows = $windows; MacOS = $false; Linux = -not $windows } } function local:Resolve-BrowserTarget { [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseApprovedVerbs', '')] param( [Parameter(Mandatory = $true)] [string]$InputPath ) $uri = $null if ([System.Uri]::TryCreate($InputPath, [System.UriKind]::Absolute, [ref]$uri)) { if ([string]::Equals($uri.Scheme, 'file', [System.StringComparison]::OrdinalIgnoreCase)) { $InputPath = $uri.LocalPath } elseif ($uri.Scheme -in @('http', 'https')) { return [pscustomobject]@{ Kind = 'Web'; Value = $InputPath } } } try { $resolvedPath = Resolve-Path -LiteralPath $InputPath -ErrorAction Stop $item = Get-Item -LiteralPath $resolvedPath.ProviderPath -ErrorAction Stop } catch { throw "File not found or invalid URL: $InputPath" } if ($item.PSIsContainer) { throw "Expected a file but got a directory: $InputPath" } return [pscustomobject]@{ Kind = 'File'; Value = $item.FullName } } function local:Resolve-BrowserCommand { [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseApprovedVerbs', '')] param( [Parameter(Mandatory = $true)] [string]$RequestedBrowser, [Parameter(Mandatory = $true)] [psobject]$Platform, [AllowNull()] [string]$RequestedBrowserPath ) if (-not [string]::IsNullOrWhiteSpace($RequestedBrowserPath)) { if ($Platform.MacOS -and ($RequestedBrowserPath -like '*.app' -or $RequestedBrowserPath -in @('Safari', 'Firefox', 'Google Chrome'))) { return [pscustomobject]@{ Mode = 'MacApp'; App = $RequestedBrowserPath } } $requestedCommand = Get-Command -Name $RequestedBrowserPath -ErrorAction SilentlyContinue if ($requestedCommand) { $commandPath = if ($requestedCommand.PSObject.Properties['Path']) { [string]$requestedCommand.Path } else { [string]$requestedCommand.Source } return [pscustomobject]@{ Mode = 'Executable'; Path = $commandPath } } if (Test-Path -LiteralPath $RequestedBrowserPath -PathType Leaf) { return [pscustomobject]@{ Mode = 'Executable'; Path = (Resolve-Path -LiteralPath $RequestedBrowserPath).Path } } throw "BrowserPath '$RequestedBrowserPath' was not found." } if ([string]::Equals($RequestedBrowser, 'Default', [System.StringComparison]::OrdinalIgnoreCase)) { return [pscustomobject]@{ Mode = 'Default' } } if ($Platform.Windows) { $programFilesX86 = [Environment]::GetEnvironmentVariable('ProgramFiles(x86)') if ([string]::IsNullOrWhiteSpace($programFilesX86)) { $programFilesX86 = $env:ProgramFiles } $candidates = switch -Exact ($RequestedBrowser) { 'Edge' { @('msedge.exe', (Join-Path $env:ProgramFiles 'Microsoft\Edge\Application\msedge.exe'), (Join-Path $programFilesX86 'Microsoft\Edge\Application\msedge.exe')) } 'Chrome' { @('chrome.exe', (Join-Path $env:ProgramFiles 'Google\Chrome\Application\chrome.exe'), (Join-Path $programFilesX86 'Google\Chrome\Application\chrome.exe')) } 'Firefox' { @('firefox.exe', (Join-Path $env:ProgramFiles 'Mozilla Firefox\firefox.exe'), (Join-Path $programFilesX86 'Mozilla Firefox\firefox.exe')) } default { @() } } foreach ($candidate in @($candidates | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) })) { $candidateCommand = Get-Command -Name $candidate -ErrorAction SilentlyContinue if ($candidateCommand) { $commandPath = if ($candidateCommand.PSObject.Properties['Path']) { [string]$candidateCommand.Path } else { [string]$candidateCommand.Source } return [pscustomobject]@{ Mode = 'Executable'; Path = $commandPath } } if ([System.IO.Path]::IsPathRooted($candidate) -and (Test-Path -LiteralPath $candidate -PathType Leaf)) { return [pscustomobject]@{ Mode = 'Executable'; Path = $candidate } } } throw "Requested browser '$RequestedBrowser' was not found on Windows. Install it or use -BrowserPath." } if ($Platform.MacOS) { $application = switch -Exact ($RequestedBrowser) { 'Safari' { 'Safari' } 'Chrome' { 'Google Chrome' } 'Firefox' { 'Firefox' } default { $null } } if (-not $application) { throw "Requested browser '$RequestedBrowser' is not available on macOS." } return [pscustomobject]@{ Mode = 'MacApp'; App = $application } } $linuxCandidates = switch -Exact ($RequestedBrowser) { 'Chrome' { @('google-chrome', 'google-chrome-stable', 'chromium-browser', 'chromium') } 'Firefox' { @('firefox') } 'Edge' { @('microsoft-edge', 'microsoft-edge-stable') } default { @() } } foreach ($candidate in $linuxCandidates) { $candidateCommand = Get-Command -Name $candidate -ErrorAction SilentlyContinue if ($candidateCommand) { $commandPath = if ($candidateCommand.PSObject.Properties['Path']) { [string]$candidateCommand.Path } else { [string]$candidateCommand.Source } return [pscustomobject]@{ Mode = 'Executable'; Path = $commandPath } } } throw "Requested browser '$RequestedBrowser' was not found on Linux. Install it or use -BrowserPath." } $platform = Get-BrowserPlatform $browserCommand = Resolve-BrowserCommand -RequestedBrowser $Browser -Platform $platform -RequestedBrowserPath $BrowserPath foreach ($inputPath in $Path) { $target = Resolve-BrowserTarget -InputPath $inputPath if ([string]::Equals([string]$browserCommand.Mode, 'Default', [System.StringComparison]::OrdinalIgnoreCase)) { if ($platform.MacOS) { if (-not (Get-Command -Name 'open' -ErrorAction SilentlyContinue)) { throw "Missing required tool 'open'." } $argumentList = @($target.Value) if ($Wait.IsPresent) { $argumentList = @('-W') + $argumentList } Start-Process -FilePath 'open' -ArgumentList $argumentList | Out-Null } elseif ($platform.Linux) { if (-not (Get-Command -Name 'xdg-open' -ErrorAction SilentlyContinue)) { throw "Missing required tool 'xdg-open'. Install package 'xdg-utils'." } Start-Process -FilePath 'xdg-open' -ArgumentList @($target.Value) -Wait:$Wait | Out-Null } else { Start-Process -FilePath $target.Value -Wait:$Wait | Out-Null } Write-Host ("Opening {0} with the default browser: {1}" -f $target.Kind, $target.Value) continue } if ($platform.MacOS -and [string]::Equals([string]$browserCommand.Mode, 'MacApp', [System.StringComparison]::OrdinalIgnoreCase)) { if (-not (Get-Command -Name 'open' -ErrorAction SilentlyContinue)) { throw "Missing required tool 'open'." } $argumentList = @('-a', [string]$browserCommand.App, $target.Value) if ($Wait.IsPresent) { $argumentList = @('-W') + $argumentList } Start-Process -FilePath 'open' -ArgumentList $argumentList | Out-Null Write-Host ("Opening {0} with {1}: {2}" -f $target.Kind, $browserCommand.App, $target.Value) continue } Start-Process -FilePath ([string]$browserCommand.Path) -ArgumentList @($target.Value) -Wait:$Wait | Out-Null Write-Host ("Opening {0} with {1}: {2}" -f $target.Kind, $browserCommand.Path, $target.Value) } } |