Skip to main content

powershell-safe-invocation

Use when writing or running PowerShell on Windows, especially native programs, quoted paths, escaping, pwsh, Start-Process, file operations, or shell troubleshooting.

Zur Installation springen

Quellinformationen

Repository
ToddModica/upstream-skills
Letzte Quellaktivität
12. September 2026 um 02:06
Erkannte Sprache von SKILL.md
Englisch
Sterne
1
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
3 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
powershell-safe-invocation
description
Use when writing or running PowerShell on Windows, especially native programs, quoted paths, escaping, pwsh, Start-Process, file operations, or shell troubleshooting.
# PowerShell Safe Invocation ## Shell Use PowerShell 7 through `pwsh.exe` unless Windows PowerShell 5.1 is explicitly required. When the active shell is uncertain, verify: ```powershell $PSVersionTable.PSVersion $PSNativeCommandArgumentPassing ``` Do not assume installing PowerShell 7 makes `powershell.exe` use PowerShell 7: - `pwsh.exe` = PowerShell 7 - `powershell.exe` = Windows PowerShell 5.1 ## Native Programs Never construct one large command string when arguments can be passed separately. Use: ```powershell $exe = 'C:\Path With Spaces\tool.exe' $argList = @( '--input' 'C:\Data Folder\input.json' '--flag' ) & $exe @argList $exitCode = $LASTEXITCODE if ($exitCode -ne 0) { throw "$exe failed with exit code $exitCode" } ``` Rules: - Treat every native argument as one array item. - Invoke executable paths stored in variables with `&`. - Capture `$LASTEXITCODE` immediately. - Avoid using `$args` as your own argument array name; it is a PowerShell automatic variable. Use names like `$argList` or `$nativeArgs`. - Do not use `Invoke-Expression`. - Do not add a `cmd.exe /c` layer merely to launch an executable. - Do not use Bash-style `\"` escaping in PowerShell. ## Cmdlets Use hashtable splatting for PowerShell cmdlets: ```powershell $params = @{ LiteralPath = 'C:\Data[1]\input.txt' Destination = 'C:\Output' Force = $true ErrorAction = 'Stop' } Copy-Item @params ``` Use `-LiteralPath` for concrete paths when the cmdlet supports it. For cmdlets that expose only `-Path`, such as `New-Item`, use `-Path`; when unsure, check `Get-Command <cmdlet> -Syntax`. Do not use `$LASTEXITCODE` to test a PowerShell cmdlet. Use terminating errors: ```powershell $ErrorActionPreference = 'Stop' ``` Wrap expressions passed as parameter values in parentheses or assign them first: use `Select-Object -Index (100..120)`, not `-Index 100..120`. Do not pipe directly from statement syntax such as `foreach (...) { ... } | ...`; assign the statement output first or use the pipeline cmdlet `ForEach-Object`. ## Complex Commands Avoid deeply quoted commands such as: ```text cmd.exe /c pwsh.exe -Command "..." ``` For multiline code, nested quotes, JSON, XML, regular expressions, pipelines, redirection, or non-ASCII paths: 1. Write a temporary `.ps1` file. 2. Execute it with: ```text pwsh.exe -NoLogo -NoProfile -NonInteractive -File script.ps1 ``` Prefer `-File` over `-Command` for anything beyond a short, simple expression. Do not add `-ExecutionPolicy Bypass` unless execution policy is actually blocking a trusted script. When you must pass a script through `-Command` from an outer PowerShell process, remember that the outer shell expands `$variables` first. Use an outer single-quoted script string when the inner script contains `$p`, `$env:...`, `$PSVersionTable`, or similar: ```powershell pwsh.exe -NoLogo -NoProfile -Command '$p = "C:\Data Folder\input.txt"; Test-Path -LiteralPath $p' ``` If the command has to cross multiple interpreters or wrappers, stop and write a `.ps1` file instead of stacking more quoting. ## Strings And Multiline Code - Use single quotes for literal strings and paths. - Use double quotes only when PowerShell expansion is needed. - Avoid backtick line continuation; use arrays, hashtables, splatting, parentheses, or script blocks. - Do not use Bash heredocs such as `python - <<'PY'`; PowerShell parses `<` differently. Use a temporary script file or a PowerShell here-string piped to the program. - For JSON, create objects and use `ConvertTo-Json`; do not hand-escape JSON. - Use single-quoted here-strings for literal multiline text: put no characters after opening `@'`, and close with `'@` alone at the start of a line. ## Encoding PowerShell 7 defaults to UTF-8 without BOM for text output; Windows PowerShell 5.1 defaults vary by cmdlet. - For a new text file consumed by another tool, specify its required encoding explicitly (usually `utf8`). - Before changing an existing text file, identify and preserve its existing encoding. Do not silently convert GBK, UTF-16, or BOM-sensitive files; if the encoding is unclear, inspect or ask. - Do not set `Console.InputEncoding` or `Console.OutputEncoding` by default. Set them only for a confirmed terminal or native-program encoding mismatch; `$OutputEncoding` instead controls PowerShell text sent to native programs. - Do not apply text encoding options to binary files. Use byte APIs for binary data. ## Start-Process For normal foreground execution, use: ```powershell & $exe @argList ``` Use `Start-Process` only for elevation, new/hidden windows, detached launch, or shell behavior. `Start-Process -ArgumentList` joins values into a command-line string and is not a reliable structured-argument API. Prefer `ProcessStartInfo.ArgumentList` when exact argument boundaries matter. When a separate process is required and arguments are complex, use: ```powershell $psi = [System.Diagnostics.ProcessStartInfo]::new() $psi.FileName = $exe $psi.UseShellExecute = $false foreach ($arg in $argList) { $psi.ArgumentList.Add($arg) } $process = [System.Diagnostics.Process]::Start($psi) $process.WaitForExit() if ($process.ExitCode -ne 0) { throw "Process failed with exit code $($process.ExitCode)" } ``` ## File Operations Before recursive delete, move, or overwrite: - Resolve the absolute root and target paths. - Verify the target is inside the intended root. - Reject empty, root-level, or unexpected paths. - Keep filesystem mutations in PowerShell instead of passing paths to another shell. Mapped drives are per user/session. If `Test-Path X:\...` fails under an automation or sandbox account but works interactively, check the current identity with `whoami` and inspect `Get-PSDrive`. If the mapping is not visible, ask the user for the UNC path, establish the mapping for the same account, or switch the task to a current-user/full-access execution mode when the platform supports it. ## Version And Module Differences PowerShell 5.1 and PowerShell 7 can expose the same command with different parameters or command types. Verify syntax in the active shell before relying on version-specific parameters: ```powershell $PSVersionTable.PSVersion Get-Command Format-Hex -Syntax Get-Command Get-FileHash -Syntax ``` For example, `Format-Hex -Count` is available in PowerShell 7 but not in Windows PowerShell 5.1. In 5.1, use pipeline limiting instead: ```powershell Format-Hex -LiteralPath 'C:\Data\buffer.bin' | Select-Object -First 2 ``` If command discovery behaves strangely, inspect `$env:PSModulePath` and `Get-Module -ListAvailable <ModuleName>` before assuming the cmdlet is missing. ## Decision Order Choose the simplest safe option: 1. PowerShell cmdlet. 2. `& $exe @argList`. 3. Temporary `.ps1` file with `pwsh.exe -File`. 4. `ProcessStartInfo.ArgumentList`. 5. `Start-Process` when its special behavior is required. 6. `cmd.exe /c` only when cmd semantics are required. 7. `Invoke-Expression` only as a tightly controlled last resort. For uncommon cases and complete examples, read `reference.md`.
Auf GitHub ansehen