Problem Space

Three ostensibly similar commands behave radically differently when you invoke them in PowerShell:

where az           # Returns nothing
Get-Command az     # Returns a path (misleading)
where.exe az       # Returns the actual precedence chain

This divergence arises from PowerShell’s command precedence model and Windows’ PATH resolution, which do not operate identically.

PowerShell Command Precedence

PowerShell resolves commands in this order: Alias → Function → Cmdlet → Application (external executable). Critically, aliases take absolute precedence—they mask everything downstream, regardless of whether an external executable exists.

The where Alias Collision

The where command is aliased to Where-Object, a pipeline-filtering cmdlet:

Get-Alias where
# Output: where -> Where-Object

When you type where az, PowerShell doesn’t search your PATH. Instead, it treats where as the Where-Object cmdlet and az as its first argument, which makes no sense in that context. Result: nothing, or a cryptic error.

Get-Command Behavior

Get-Command returns matching commands in descending order of precedence when using the -All switch, but without -All, returns only the first match. This is deceptive: Get-Command az might return az.cmd, but that doesn’t mean az.cmd is what your shell will actually execute when you invoke az.

Example:

Get-Command az
# Returns: az.cmd
 
where.exe az
# Returns: (multiple paths)
#   C:\Program Files\Microsoft SDKs\Azure\CLI2\wbin\az
#   C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin\az.cmd

Get-Command shows one result; where.exe reveals that two binaries exist, and the bare az (without .cmd) appears first in PATH precedence.

where.exe as Ground Truth

The where.exe command performs the actual Windows PATH resolution that the shell uses. It:

  • Searches $env:PATH in order
  • Reports all matches (not just the first)
  • Respects file extensions (.exe, .cmd, .bat)
  • Doesn’t interact with PowerShell’s alias/function/cmdlet layers

Why where.exe Matters for Debugging

When troubleshooting environment issues (like the Azure CLI win32file problem), you need to see what your shell will actually execute, not what PowerShell’s object model thinks exists.

Scenario: You have both az and az.cmd in your PATH (stale installation left crud behind). Get-Command optimistically returns az.cmd. But Windows PATH precedence found az first. When you invoke az, the wrong binary runs.

where.exe az immediately reveals this mismatch. Get-Command az obscures it.

Practical Guidance

TaskCommandWhy
Find all PATH matches in orderwhere.exe <name>Reflects actual shell behavior
Inspect a specific command’s propertiesGet-Command <name>Returns rich metadata (module, parameters, etc.)
Filter pipeline objects| where <condition>The intended use of the alias
Avoid the alias collisionwhere.exe <name> or Get-Command -Type Application <name>Explicit about your intent

Important

When debugging executable precedence issues, always use where.exe or Get-Command -Type Application. Don’t rely on Get-Command alone.

Potential Workarounds

In theory, you could reclaim where for the Windows command by aliasing it explicitly in your PowerShell profile:

Set-Alias where where.exe # Not recommended

This shadows PowerShell’s built-in where → Where-Object alias with the executable. Important Caveat: you’d then need Where-Object (its full name) to filter pipelines.

Alternatively, adopt which (Unix convention) as an alias:

Set-Alias which where.exe

Add to $PROFILE to persist across sessions.