[CmdletBinding()] param() Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $root = $PSScriptRoot $binPath = Join-Path $root 'bin' $shellScript = Join-Path $root 'shell\MS.Open.ps1' if (-not (Test-Path -LiteralPath $binPath -PathType Container)) { throw "Missing bin directory: $binPath" } if (-not (Test-Path -LiteralPath $shellScript -PathType Leaf)) { throw "Missing shell integration script: $shellScript" } function Normalize-PathEntry { param([string]$Value) if ([string]::IsNullOrWhiteSpace($Value)) { return '' } return $Value.Trim().TrimEnd('\') } function Add-UserPath { param([string]$PathToAdd) $current = [Environment]::GetEnvironmentVariable('Path', 'User') $entries = @( $current -split ';' | ForEach-Object { Normalize-PathEntry $_ } | Where-Object { $_ } ) $normalizedTarget = Normalize-PathEntry $PathToAdd $alreadyPresent = $entries | Where-Object { $_.Equals($normalizedTarget, [StringComparison]::OrdinalIgnoreCase) } if (-not $alreadyPresent) { $newPath = (@($entries) + $normalizedTarget) -join ';' [Environment]::SetEnvironmentVariable('Path', $newPath, 'User') Write-Host "Added to user PATH: $PathToAdd" } else { Write-Host "Already in user PATH: $PathToAdd" } $processEntries = @($env:Path -split ';') $inCurrentProcess = $processEntries | Where-Object { (Normalize-PathEntry $_).Equals($normalizedTarget, [StringComparison]::OrdinalIgnoreCase) } if (-not $inCurrentProcess) { $env:Path = "$env:Path;$PathToAdd" } } function Update-PowerShellProfile { param( [Parameter(Mandatory)] [string]$ProfilePath, [Parameter(Mandatory)] [string]$IntegrationScript ) $directory = Split-Path -Parent $ProfilePath New-Item -ItemType Directory -Path $directory -Force | Out-Null $beginMarker = '# >>> MS.Open >>>' $endMarker = '# <<< MS.Open <<<' $escapedScript = $IntegrationScript.Replace("'", "''") $block = @" $beginMarker `$msOpenShell = '$escapedScript' if (Test-Path -LiteralPath `$msOpenShell) { . `$msOpenShell } $endMarker "@ $content = '' if (Test-Path -LiteralPath $ProfilePath) { $content = Get-Content -LiteralPath $ProfilePath -Raw $timestamp = Get-Date -Format 'yyyyMMdd-HHmmss' Copy-Item -LiteralPath $ProfilePath -Destination "$ProfilePath.msopen-backup-$timestamp" } $pattern = "(?ms)^$([regex]::Escape($beginMarker)).*?^$([regex]::Escape($endMarker))\s*" $cleaned = [regex]::Replace($content, $pattern, '').TrimEnd() if ($cleaned) { $newContent = "$cleaned`r`n`r`n$block`r`n" } else { $newContent = "$block`r`n" } Set-Content -LiteralPath $ProfilePath -Value $newContent -Encoding UTF8 Write-Host "Configured PowerShell profile: $ProfilePath" } Add-UserPath -PathToAdd $binPath $documents = [Environment]::GetFolderPath('MyDocuments') $profiles = @( (Join-Path $documents 'WindowsPowerShell\Microsoft.PowerShell_profile.ps1'), (Join-Path $documents 'PowerShell\Microsoft.PowerShell_profile.ps1') ) | Select-Object -Unique foreach ($profilePath in $profiles) { Update-PowerShellProfile -ProfilePath $profilePath -IntegrationScript $shellScript } Write-Host '' Write-Host 'MS.Open is installed.' Write-Host 'Restart your terminal, then try:' Write-Host ' open .' Write-Host ' mkcd test-folder' Write-Host ' paths'