Replacing Commands

PowerShell comes with a couple of “secret” (better: under-documented) settings. One is PreCommandLookupAction, and it gives you great power: this action is executed whenever PowerShell is ready to execute a command.

Your event handler can now adjust, change, or manipulate both the original command and the arguments submitted to it.

Today we’ll be using this simply to secretly exchange a command with another:

$ExecutionContext.SessionState.InvokeCommand.PreCommandLookupAction = {
    # is called whenever a command is ready to execute
    param($command, $eventArgs)

    # not executed internally by PowerShell
    if ($command -eq 'Get-Service' -and $eventArgs.CommandOrigin -eq 'Runspace')
    {
        # tell PowerShell what to do instead of
        # running the original command
        $eventArgs.CommandScriptBlock = {
          # run the original command without "*", and
          # submit original arguments if there have been any
          $command = 'dir'

          $( 
          if ($args.Count -eq 0)
          { & $command }
          else
          { & $command $args }
          ) 
        }.GetNewClosure()
    }
}

This handler looks for the command “Get-Service”, and replaces it with “dir” instead. So when you run “Get-Service”, you get a folder listing instead. Of course, this makes no sense, and for legitimate reasons you could have used an alias. It simply shows the power of this approach. In the next days, we’ll show some more useful examples.

Twitter This Tip! ReTweet this Tip!

  • I was very intrigued with the PreCommandLookupAction  and PostCommandLookupAction, but not matter what I try it doesn't work. It's like they never execute.

    I'm on PowerShell 5.1 on Windows 10