skip to content

PowerShell

PowerShell as both a shell and a .NET scripting language: cmdlets, the object pipeline, modules, remoting and error handling, across Windows, Linux and macOS. Interviewers ask because it is the automation language for anything Microsoft-shaped.

part ofCommand-line shellsoverview, primer and where to startread it →
on this pageshow

questions

page 1 of 2

In PowerShell, what actually travels between two commands joined by the pipe operator, and how does that differ from a pipeline in bash?

level: juniorimportance: must knowfreq 85%

answer

  1. objects, not bytes
  2. no re-parsing of columns
  3. properties and methods survive the pipe
  4. Get-Member shows what is flowing
  5. formatting happens last, at the console

basics

~20 s

PowerShell pipes live .NET objects rather than text. Each command hands the next typed objects with named properties and methods, so downstream commands read properties directly instead of re-parsing columns of formatted text the way bash pipelines must.

solid answer

~50 s

In bash the contract between commands is a byte stream, so the next command has to recover structure from text — that is largely why `awk`, `cut` and `sed` exist. PowerShell passes the objects themselves: `Get-Process` emits `System.Diagnostics.Process` instances, and `Where-Object CPU -gt 10` tests the real `CPU` property rather than a column position. The practical wins are that a value containing a space cannot break field splitting, types survive so a date compares as a date and a number as a number, and `Get-Member` will tell you exactly what any object in the pipe offers. The costs are real too: you pay .NET object construction on every item, native executables at the edges still emit plain strings, and the table you see on screen is produced by the formatting layer at the very end — it is not what was flowing through the pipe.

code

powershell · 5 lines
powershell
# The pipe hands over live objects, not rendered text
Get-Process | Where-Object CPU -gt 10 | Sort-Object CPU -Descending | Select-Object -First 5 Name, Id, CPU

# Ask what is actually in the pipeline
Get-Process | Get-Member -MemberType Property

go deeper

for a junior

Be able to say plainly that PowerShell pipes objects while bash pipes text, and show one filter that reads a property by name, such as Where-Object on CPU or Length.

for a middle

Explain that cmdlets emit .NET instances, that the on-screen table is produced by the formatting layer at the end, and use Get-Member to prove what type is flowing.

for a senior

Show judgment about the boundaries: native commands emit strings, formatting cmdlets end a pipeline, and data destined for a file must be serialized rather than captured as rendered text.

for a principal

Own the tradeoff. Structure removes a whole class of parsing bugs but costs per-object allocation and couples you to .NET; argue when a PowerShell pipeline is the right integration surface and when plain text is.

## Two different contracts A Unix shell pipeline is defined by one contract: a process writes bytes to standard output and the next process reads bytes from standard input. Nothing else crosses the boundary. Every program therefore renders its internal data into text for display, and every consumer must parse that text back into fields. That round trip is where `awk '{print $2}'`, `cut -d: -f1` and a lot of fragile quoting come from: structure the producer already had is thrown away at the pipe and guessed at on the other side. PowerShell changes the contract. A cmdlet is a .NET class that *emits objects*, and the pipe hands those object references straight to the next command in the same process. `Get-Process` does not print a table; it emits `System.Diagnostics.Process` instances. `Get-ChildItem` emits `System.IO.FileInfo` and `System.IO.DirectoryInfo`. The rendering you see happens only when nothing else consumes the objects and they fall out of the end of the pipeline into the default output path. ## What objects remove ```powershell Get-Process | Where-Object CPU -gt 10 | Sort-Object CPU -Descending | Select-Object -First 5 Name, Id, CPU ``` Nothing in that pipeline parses anything. `Where-Object` evaluates a comparison against the `CPU` property, `Sort-Object` sorts on the property's real numeric value, and `Select-Object` projects three named properties. In a text shell each of those steps needs to know a column index or a delimiter, and each breaks the day a value contains the delimiter. Three concrete consequences follow: - **No field-splitting bugs.** A file named `My Report.txt` is one property value, not two fields. - **Types survive.** A `DateTime` property compares chronologically, not lexically; a size compares as a number, so `Where-Object Length -gt 1MB` is meaningful. (`1MB` is real PowerShell numeric-literal syntax.) - **The data is discoverable at runtime.** `Get-Process | Get-Member` prints the type name plus every property and method. There is no equivalent for a text stream — you can only look at it and guess. ## What you see is not what flows The most common beginner error is believing the console table *is* the data. It is not. When objects reach the end of the pipeline they are passed to the formatting layer, which consults per-type formatting rules to decide which properties to show and whether to use a table or a list. `Get-Process` displays a handful of columns while the object carries dozens of properties; `Select-Object *` or `Format-List *` reveals the rest. This is also why `Format-Table` and its siblings must be last: they replace your objects with internal formatting-instruction objects (types in the `Microsoft.PowerShell.Commands.Internal.Format` namespace) that only the output cmdlets understand. If you want data in a file, serialize the objects — `Export-Csv`, `ConvertTo-Json`, `Export-Clixml` — rather than capturing the rendered text. ## Where the object model leaks PowerShell still lives in a world of ordinary executables. When you run `git status` or `ping` inside PowerShell, that program writes text, and PowerShell wraps it as `System.String` objects — one per output line. So this works: ```powershell git status --porcelain | Where-Object { $_ -like ' M *' } ``` but `$_` there is a string, not a structured object, and you are back to matching patterns. `$_` (also spelled `$PSItem`) is the automatic variable holding the current pipeline item. Some cmdlets deliberately re-introduce structure at that boundary: `Select-String` returns `MatchInfo` objects with `Line`, `LineNumber`, `Path` and `Matches` properties rather than raw text, which is why it composes better than a bare grep-style filter. ## What it costs Objects are not free. Every item is a live .NET object, so a pipeline over a very large stream pays allocation and per-item cmdlet overhead that a tight C program reading bytes does not. PowerShell pipelines are usually slower than the equivalent text pipeline on huge inputs, and a language-level `foreach` loop over an in-memory collection is faster still than the pipeline machinery. You also inherit .NET's shape: interop with the wider Unix tool ecosystem happens through strings at the edges, and objects only travel intact between PowerShell commands. The honest summary for an interview: PowerShell trades raw throughput and universality for structure that does not have to be re-derived at every stage, and the biggest adjustment coming from bash is to stop reading the screen and start asking `Get-Member` what you actually hold.

  • If everything is an object, why does `Get-Process | Out-File procs.txt` write a table that looks exactly like the console?
    Because `Out-File` is an output cmdlet: objects that reach it are handed to the formatting layer first and rendered to text using the type's display rules. The file receives the rendering, not the data. To keep the data, serialize instead — `Export-Csv`, `ConvertTo-Json` or `Export-Clixml` write the properties themselves.
  • How do you find out what properties and methods the objects in a pipeline actually have?
    Pipe them into `Get-Member`. It reports the .NET type name plus every property, script property and method, which is the authoritative answer — the console view is filtered by formatting rules and usually shows only a few properties. `Select-Object *` or `Format-List *` is a quicker way to see all values for one item.
  • What do you get when you pipe a native executable such as `git` into a PowerShell cmdlet?
    Plain strings — PowerShell captures the program's standard output and emits one `System.String` per line. There is no structure to bind to, so downstream you are matching patterns rather than reading properties. Cmdlets like `Select-String` help by turning matches back into `MatchInfo` objects with `Line`, `LineNumber` and `Path`.

saying these in an interview costs you the question

  • Says the pipeline carries text that PowerShell parses for you
  • Believes the console table is the data itself
  • Thinks Format-Table output can be piped into Export-Csv
  • Claims you still need cut or awk to split columns
  • Assumes objects always make the pipeline faster than text

context

open as a page

PowerShell command names follow a Verb-Noun convention such as `Get-Process`. What does that convention buy you, and how would you find a command whose name you do not know?

level: juniorimportance: must knowfreq 62%

basics

~20 s

Verb-Noun names make PowerShell predictable and searchable: the verb comes from an approved list describing the action, the noun names the thing acted on. Because the shape is uniform, Get-Command can filter by verb or noun and Get-Help documents any command you find.

open as a page

In PowerShell, what is the difference between a .psm1 script module file and a .psd1 module manifest, and what does adding a manifest give you?

level: juniorimportance: must knowfreq 68%

basics

~20 s

A .psm1 file holds the module's actual code — its function definitions. A .psd1 manifest holds metadata about the module as a PowerShell hashtable: version, GUID, author, dependencies, and the exact list of commands the module exports.

open as a page

In PowerShell remoting, what is the difference between Enter-PSSession and Invoke-Command, and when would you use each?

level: juniorimportance: must knowfreq 70%

basics

~20 s

Enter-PSSession opens an interactive prompt on one remote machine, so you type commands there and see results immediately. Invoke-Command sends a script block to one or many machines, runs it there, and returns the results into your local session.

open as a page

In PowerShell, what do the `@()` and `@{}` literals each create, and how do you add an item to each afterwards?

level: juniorimportance: must knowfreq 68%

basics

~20 s

@() builds an array — an ordered list of values indexed by position. @{} builds a hashtable — unordered key/value pairs. Append to an array with $a += $item; add or update a hashtable entry with $h['key'] = $value.

open as a page

On a Windows machine, `powershell.exe` reports version 5.1 while `pwsh` reports 7.x. Are these the same PowerShell after an upgrade, and what does `$PSVersionTable.PSEdition` tell you about each?

level: middleimportance: must knowfreq 70%

basics

~20 s

They are two separate products installed side by side. Windows PowerShell 5.1 (powershell.exe) runs on .NET Framework and reports PSEdition Desktop; PowerShell 7 (pwsh) is a separate cross-platform install on modern .NET and reports Core.

open as a page

In PowerShell, a Get-Item call inside a try block fails and prints a red error, but the catch block never runs and the script keeps going. Explain the difference between terminating and non-terminating errors, and how you make that call catchable.

level: middleimportance: must knowfreq 76%

basics

~20 s

Most cmdlet failures are non-terminating errors: they write a record to the error stream and execution continues, so try/catch never fires. Adding -ErrorAction Stop turns that call's errors into terminating ones, which a catch block handles.

open as a page

A PowerShell script calls Invoke-Command against a remote server to get process objects back, but calling .Kill() on one of the returned objects fails with a method-not-found error, while the same code works locally. What is going on?

level: middleimportance: must knowfreq 55%

basics

~20 s

Objects crossing a PowerShell remoting boundary are serialized to XML and rebuilt on the other side as inert property bags. The returned object carries the remote object's property values but not its live methods or its connection to the remote process, so .Kill() does not exist.

open as a page

What does adding `[CmdletBinding()]` above the param block of a PowerShell function change about how that function behaves?

level: middleimportance: must knowfreq 60%

basics

~20 s

[CmdletBinding()] turns a simple PowerShell function into an advanced function: it inherits the common parameters (-Verbose, -Debug, -ErrorAction, -ErrorVariable, -OutVariable and friends), gains access to $PSCmdlet, and binds arguments strictly instead of dumping extras into $args.

open as a page

You need one PowerShell 7 script to run on Windows, Linux and macOS. What does the engine give you for detecting the current operating system, and how do you build file paths and read environment variables so they work on all three?

level: juniorimportance: should knowfreq 52%

basics

~20 s

PowerShell 7 defines the automatic variables $IsWindows, $IsLinux and $IsMacOS for OS detection. Build paths with Join-Path rather than hardcoded backslashes, use $HOME instead of $env:USERPROFILE, and spell environment variable names exactly, since Unix names are case-sensitive.

open as a page

In PowerShell, what is the difference between throw and Write-Error, and when would you choose each inside a function?

level: juniorimportance: should knowfreq 55%

basics

~10 s

throw raises a terminating error that unwinds to the nearest catch and stops the current scope. Write-Error emits a non-terminating error record on the error stream and execution continues with the next statement.

open as a page

In PowerShell, when should you use the `ForEach-Object` cmdlet rather than the `foreach` statement, and how do the two differ in the way they consume their input?

level: middleimportance: should knowfreq 55%

basics

~20 s

The foreach statement evaluates its whole collection into memory first, then loops over it quickly. ForEach-Object is a cmdlet that streams: it runs its script block on each item as it arrives, so it composes inside a pipeline and holds constant memory, at a higher per-item cost.

open as a page

In PowerShell, `Get-Process | Format-Table Name, CPU | Export-Csv procs.csv` writes a CSV of formatting metadata instead of process data. Why are the `Format-*` cmdlets the end of a pipeline?

level: middleimportance: should knowfreq 45%

basics

~20 s

Format-Table does not reshape your data, it replaces it with internal formatting-instruction objects that only the output cmdlets understand. Anything placed after a Format-* cmdlet therefore receives display instructions, not process objects. Format for humans last; use Select-Object or Export-Csv for data.

open as a page

In PowerShell Desired State Configuration, what does a configuration compile into, and how does the Local Configuration Manager apply it in push mode versus pull mode?

level: middleimportance: should knowfreq 35%

basics

~20 s

A DSC configuration compiles into one MOF document per target node describing desired state. The Local Configuration Manager agent on the node applies it: in push mode you send the MOF with Start-DscConfiguration; in pull mode the agent fetches it on a schedule and can re-correct drift.

open as a page

In PowerShell, how do you catch one specific failure type in a catch block rather than everything, and what does the object in $_ actually contain?

level: middleimportance: should knowfreq 44%

basics

~20 s

Put a .NET exception type in brackets after the catch keyword, such as catch [System.IO.IOException], and order blocks from most specific to most general. Inside, $_ is an ErrorRecord holding the exception, target object, category and script stack trace.

open as a page

In a fresh PowerShell session you run a cmdlet from a module you never imported and it just works. What is module auto-loading, and how does PSModulePath drive it?

level: middleimportance: should knowfreq 55%

basics

~20 s

PowerShell scans the directories listed in the PSModulePath environment variable, indexes the commands each module exports, and imports the owning module automatically the first time you invoke one of those commands. Explicit Import-Module is only needed to force a specific module or version.

open as a page

In PowerShell, what does creating a session with New-PSSession give you that calling Invoke-Command -ComputerName repeatedly does not?

level: middleimportance: should knowfreq 50%

basics

~20 s

New-PSSession creates a persistent remote runspace you reuse across calls, so connection setup and authentication happen once and state such as variables and imported modules survives between commands. Each Invoke-Command -ComputerName call instead builds a throwaway session and tears it down.

open as a page

A PowerShell function's last line is `return $result`, yet the caller receives several extra objects as well. Why does a PowerShell function emit more than the value named by `return`, and how do you stop it?

level: middleimportance: should knowfreq 50%

basics

~20 s

In PowerShell every expression whose value is not captured, assigned or redirected goes to the function's output stream. return only exits the scope and adds its argument to what was already emitted. Discard unwanted values with $null = expression, void, or | Out-Null.

open as a page

A PowerShell advanced function declares `[Parameter(ValueFromPipeline = $true)]` on `$Name` and puts all of its logic directly in the function body with no begin/process/end blocks. Piping ten names into it produces output for only the last one. Why?

level: middleimportance: should knowfreq 55%

basics

~20 s

A function body with no named blocks is treated entirely as the end block, which runs once after the pipeline is exhausted. The pipeline parameter is rebound for each incoming object, so by the time that code runs it holds only the last one. Per-item logic belongs in a process block.

open as a page

A PowerShell pipeline that reads a multi-gigabyte log, filters it and sorts the result prints nothing for minutes and consumes gigabytes of memory. Which pipeline stages stream and which must buffer the whole input, and how would you restructure it?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Sort-Object is a blocking stage: it cannot emit anything until it has received every input object, so it holds the entire filtered stream in memory. Where-Object, ForEach-Object and Select-Object -First stream one object at a time. Reduce or project before sorting, or avoid sorting.

open as a page

A PowerShell script written for Windows PowerShell 5.1 fails under PowerShell 7 with "Get-WmiObject is not recognized", and one of its modules refuses to import at all. What changed between the engines, and what does PowerShell 7 on Windows offer to keep such a module usable?

level: seniorimportance: should knowfreq 42%

basics

~20 s

PowerShell 6 removed the WMI cmdlets in favour of the CIM cmdlets, and modules whose manifest omits Core from CompatiblePSEditions refuse to load. On Windows, Import-Module -UseWindowsPowerShell proxies such a module through a background 5.1 process.

open as a page

A PowerShell script loops over hundreds of inputs calling a cmdlet for each. It must not stop at the first failure, but at the end it must report exactly which ones failed. How do you capture those errors, and why is $Error not a good enough answer?

level: seniorimportance: should knowfreq 36%

basics

~20 s

Pair -ErrorAction SilentlyContinue with -ErrorVariable on the call inside the loop, prefixing the variable name with a plus sign so each error record is appended rather than overwriting the last. $Error is session-wide, capped, and mixed with unrelated failures.

open as a page

A PowerShell automation script that worked yesterday breaks after a teammate installs a newer version of a module on the same build agent. How does PowerShell decide which version of a module to load, and how do you make that deterministic?

level: seniorimportance: should knowfreq 45%

basics

~20 s

PowerShell installs modules side by side in versioned subfolders and, when you do not ask for a version, imports the highest one it finds. Determinism comes from pinning: Import-Module -RequiredVersion, a #Requires -Modules hashtable, manifest RequiredModules, or vendoring with Save-Module.

open as a page

PowerShell 7 can remote over WS-Man/WinRM or over SSH. How do the two transports differ, and how would you choose between them?

level: seniorimportance: should knowfreq 38%

basics

~20 s

WS-Man is the Windows-native transport: SOAP over HTTP on ports 5985/5986, integrated with Windows authentication and session configurations. SSH transport tunnels PowerShell over an existing SSH connection, works uniformly on Linux and macOS, and uses SSH keys, but drops WS-Man-only features such as disconnected sessions.

open as a page

A PowerShell script builds a result set with `$results += $item` inside a loop over 100,000 records and slows to a crawl while memory climbs. What is happening, and what should it use instead?

level: seniorimportance: should knowfreq 38%

basics

~20 s

PowerShell arrays are fixed-size .NET arrays, so each += allocates a new array one element longer and copies every existing element — quadratic work plus heavy garbage. Use a List[T] with .Add(), or let the loop stream its output and assign the whole loop once.

open as a page

You need to run a PowerShell health-check script against several thousand servers and collect the results. How would you design the fan-out, and what limits shape the design?

level: principalimportance: should knowfreq 30%

basics

~20 s

Batch the fleet and let Invoke-Command fan out with a tuned -ThrottleLimit (default 32) rather than hand-rolling parallelism. Reuse sessions for multi-step work, run batches as jobs, tag every result with PSComputerName, and treat unreachable hosts as expected data rather than failures.

open as a page

In PowerShell, `$p = Get-Process -Id $PID | Select-Object Name, CPU` and then `$p.Kill()` fails with a method-not-found error, although `Get-Process -Id $PID` alone supports `.Kill()`. What did `Select-Object` do to the object?

level: middleimportance: nice to knowfreq 32%

basics

~20 s

Select-Object with a property list does not trim the original object — it builds a brand-new PSCustomObject carrying only the named properties as plain values. The original .NET type, and therefore every method on it such as Kill(), is gone.

open as a page

A PowerShell script runs an external program such as git inside a try block. The program fails and prints its error text, but the catch block never runs and the script carries on. Why do external programs behave differently from cmdlets, and how should the script detect the failure?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

An external program is a separate process that reports failure with an exit code, not with a PowerShell error record, so try/catch and $ErrorActionPreference never see it. Check $LASTEXITCODE after the call and throw yourself.

open as a page

What is implicit remoting in PowerShell — for example Import-PSSession or Import-Module -PSSession — and what actually runs locally versus on the remote machine?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

Implicit remoting imports a remote session's commands into your local session as proxy functions. The names, parameters and tab completion are local; the actual execution happens in the remote runspace, and results come back deserialized like any other remoting output.

open as a page

You are choosing how to manage machine state for a fleet that is mostly Windows with a growing Linux share. What is the honest case for PowerShell DSC today against Ansible or Terraform, and how would you decide?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

They solve different problems: Terraform provisions infrastructure, Ansible pushes configuration on demand, and DSC runs an on-node agent that can continuously correct drift on Windows. Choose by whether you need continuous convergence, how strong your Linux story must be, and whether rebuilding beats converging.

open as a page

showing 1–30 of 32