Skip to content

Instantly share code, notes, and snippets.

@a-bronx
Last active January 1, 2025 01:04
Show Gist options
  • Select an option

  • Save a-bronx/3649cffd23c01784688d345ff120584b to your computer and use it in GitHub Desktop.

Select an option

Save a-bronx/3649cffd23c01784688d345ff120584b to your computer and use it in GitHub Desktop.
PowerShell tricks

CMD vs PowerShell Analogs

Table 1. CMD special variables
CMD Variable PowerShell Analog Description

%0

$MyInvocation.MyCommand.Path

The full path to the script being executed.

%1, %2, …​

$args[0], $args[1], …​

Positional arguments passed to the script.

%*

$args

All arguments passed to the script as an array.

%~f1

$(Resolve-Path $args[0]).Path

Full path of the argument.

%~d1

$(Split-Path -Qualifier $args[0])

Drive letter of the argument.

%~p1

$(Split-Path -Parent $args[0])

Path of the argument without the file name.

%~n1

$(Split-Path $args[0] -Leaf Split-Path -LeafBase)

File name without extension.

%~x1

$(Split-Path $args[0] -Leaf Split-Path -Extension)

File extension.

%~s1

No direct analog

Short 8.3 name format (rarely needed in PS).

%~a1

(Get-Item $args[0]).Attributes

File attributes.

%~t1

(Get-Item $args[0]).LastWriteTime

File’s last modification time.

%~z1

(Get-Item $args[0]).Length

File size in bytes.

%~$PATH:1

Get-Command $args[0] or Get-Item $env:PATH

Resolves a file in the PATH environment variable.

Key Differences:

  • $args in PowerShell is an array, making it more flexible for handling arguments.

  • PowerShell uses cmdlets (e.g., Split-Path, Resolve-Path) for advanced file and path manipulations.

  • $MyInvocation provides detailed context about the script, command, or function being executed.

How to Import Early

Problem

You have a shared script/module with some function:

toolset.ps1

function Find-MsBuild() { ... }
function Find-SignTool() { ... }

In your main script you’d like to use this functin in the param() section:

build.ps1

param(
    $ProjectName,
    $MsBuild = Find-MsBuild(),    # << oops, not yet availabe
    $SignTool = Find-SignTool()   # << oops, not yet availabe
)
# Dot-source toolset functions
. .\toolset.ps1                   # << become available here

& $MsBuild $ProjectName
...

The problem is that Find-MsBuild and Find-SignTool are not yet available in the param() block, they are imported later in the script body.

Solution

Create a pseudo-parameter which will do the import inside the param block:

param(
    $ProjectName,

    [ValidateScript({ return $false; })]
    [bool]$ToolsetIsLoaded=$(. .\toolset.ps1; $true),  # << dot-sourcing here

    $MsBuild = Find-MsBuild(),    # << now can use it
    $SignTool = Find-SignTool()   # << now can use it
)

& $MsBuild $ProjectName
...
# Shows a system UI prompting a user to select a certificate from a list
$certs = ls cert:\**\**\* -ssl
if ($certs) {
Add-Type -AssemblyName System.Security
$coll = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$certs | %{ $coll.Add($_) }
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2UI]::SelectFromCollection(
$coll,
"Select a Certificate",
"Choose a certificate from the list below:",
[System.Security.Cryptography.X509Certificates.X509SelectionFlag]::SingleSelection
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment