Skip to content

Instantly share code, notes, and snippets.

@jpbruckler
Last active June 19, 2023 14:39
Show Gist options
  • Save jpbruckler/1ba47a193046115d3d14d28ee2c58f2f to your computer and use it in GitHub Desktop.
Save jpbruckler/1ba47a193046115d3d14d28ee2c58f2f to your computer and use it in GitHub Desktop.
PowerShell profile
# Set environment variables
Set-Item -Path "env:PSProfileGistID" -Value '1ba47a193046115d3d14d28ee2c58f2f'
# Profile variables
$script:documents = (Join-Path $env:USERPROFILE 'Documents')
$script:gitdir = (Join-Path $script:documents 'git')
# Extend Path
$PathExt = @(
(Join-Path $env:APPDATA 'espanso')
)
foreach ($Path in $PathExt) {
if (Test-Path $Path) {
$env:PATH = '{0};{1}' -f $env:PATH, $Path
}
}
if (Test-Path (Join-Path $env:APPDATA 'espanso'))
{
$env:ESPANSO_PATH = (Join-Path $env:APPDATA 'espanso')
}
#region Git setup
Import-Module posh-git
if (Test-Path $script:gitdir) {
# Repo path exists. Create a PS Drive if it's not mapped already
$CurrentGhMap = Get-PSDrive -Name gh -ErrorAction SilentlyContinue
# Check to see if GH is already mapped, and unmap if it does
if ($CurrentGhMap) {
$null = Remove-PSDrive -Name gh -ErrorAction SilentlyContinue
}
New-PSDrive -Name gh -PSProvider FileSystem -Root $script:gitdir
} else {
Write-Host ('{0} does not exist. Creating.' -f $script:gitdir) -BackgroundColor DarkRed -ForegroundColor White
$null = New-Item -Path $script:gitdir -ItemType Directory -Force -ErrorAction Stop
$null = New-PSDrive -Name gh -PSProvider FileSystem -Root $script:gitdir
Set-Location $script:gitdir
}
#endregion
#region OhMyPosh setup
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH\material.omp.json" | Invoke-Expression
#endregion
#region ALIASES
Set-Alias -Name 'obsidian' -Value 'C:\Users\john\AppData\Local\Obsidian\Obsidian.exe'
Set-Alias -Name 'gh' -Value "C:\Program Files (x86)\GitHub CLI\gh.exe"
#endregion
#region PSREADLINE
Set-PSReadLineOption -HistorySearchCursorMovesToEnd
Set-PSReadlineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadlineKeyHandler -Key DownArrow -Function HistorySearchForward
Set-PSReadlineOption -BellStyle None #Disable ding on typing error
Set-PSReadlineOption -EditMode Emacs #Make TAB key show parameter options
# Ctrl+e to open Edge with Google
Set-PSReadlineKeyHandler -Key Ctrl+e -ScriptBlock { Start-Process "${env:ProgramFiles(x86)}\Microsoft\Edge\Application\msedge.exe" -ArgumentList "https://www.google.com" }
# Ctrl+g to commit and push
Set-PSReadlineKeyHandler -Chord Ctrl+G -ScriptBlock {
$message = Read-Host "Please enter a commit message"
git commit -m "$message" | Write-Host
$branch = (git rev-parse --abbrev-ref HEAD)
Write-Host "Pushing ${branch} to remote"
git push origin $branch
}
#endregion PSREADLINE
#region Functions
function Initialize-NewGhRepo {
param(
[string] $Remote,
[string] $Path = $PWD.Path,
[string] $Name
)
if (Get-ChildItem -Path $Path -Filter '.git' -ErrorAction SilentlyContinue) {
Write-Error ('{0} is already a Git repository.' -f $Path)
return
}
if (-not $Name) {
$Name = (Get-Item -Path $Path).Name
}
if (-not $Remote) {
$Remote = 'https://github.com/jpbruckler/{0}.git' -f $Name
}
if ((Get-ChildItem | Measure-Object).Count -eq 0) {
('# {0}' -f $Name) | Out-File -FilePath (Join-Path -Path $Path -ChildPath 'README.md') -Encoding ascii
}
git init
git add *
git commit -m "first commit"
git branch -M main
git remote add origin $Remote
git push -u origin main
git checkout -b develop
git push --set-upstream origin develop
}
function Update-PSProfile {
<#
.SYNOPSIS
Updates the PowerShell profile with the latest version from a GitHub Gist.
.DESCRIPTION
The Update-PowerShellProfile function checks for updates to your PowerShell
profile stored in a GitHub Gist, and downloads it if there's a newer version
available. The function assumes you have a file named "Microsoft.PowerShell_profile.ps1"
in your gist.
.PARAMETER GistID
The URL of the raw GitHub Gist containing your PowerShell profile. By
default this looks for an environment variable of env:PSProfileGistID.
.EXAMPLE
Update-PowerShellProfile
This example checks for updates to the PowerShell profile and downloads
it if there's a newer version available.
.INPUTS
None
.OUTPUTS
None
.NOTES
If the PowerShell profile is updated, you will need to restart your
PowerShell session to apply the changes.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string] $GistID = $env:PSProfileGistID
)
begin {
if (-not (Test-Path $PROFILE)) {
New-Item -Path $PROFILE -ItemType File
}
}
process {
$ProfileHash = (Get-FileHash $PROFILE).Hash
$GitUrl = ('https://gist.github.com/{0}.git' -f $GistID)
$profilePath = $PROFILE
$tempFile = Join-Path -Path $env:TEMP -ChildPath $GistID
try {
# Delete the temporary folder if it exists
if (Test-Path $tempFile) {
Remove-Item -Path $tempFile -Recurse -Force
}
# Checkout the latest version of the profile from GitHub
$std0 = (Join-Path -Path $env:temp -ChildPath 'stdout.txt')
$std1 = (Join-Path -Path $env:temp -ChildPath 'stderr.txt')
Start-Process git.exe -ArgumentList "clone $GitUrl $tempFile" -Wait -NoNewWindow -RedirectStandardOutput $std0 -RedirectStandardError $std1 -ErrorAction Stop
# Compare hashes
if ($ProfileHash -ne (Get-FileHash $tempFile\Microsoft.PowerShell_profile.ps1).Hash) {
# Copy the updated profile to the PowerShell profile path
Copy-Item -Path $tempFile\Microsoft.PowerShell_profile.ps1 -Destination $profilePath -Force
Write-Host "PowerShell profile updated. Restart your PowerShell session to apply the changes."
}
else {
Write-Host "No updates found."
}
}
catch {
Write-Warning "Unable to delete temporary folder $tempFile"
}
finally {
Remove-Item $std0 -Force
Remove-Item $std1 -Force
Remove-Item $tempFile -Recurse -Force
}
}
}
function Get-DirectorySize {
<#
.SYNOPSIS
Get the total size of files within a directory.
.DESCRIPTION
The Get-DirectorySize function calculates the total size of all files
within a specified directory and its subdirectories. The result can be
displayed in bytes, kilobytes, megabytes, or gigabytes.
.PARAMETER Path
The path to the directory you want to calculate the size for. Defaults
to the current directory if not specified.
.PARAMETER InType
The unit of measurement for the directory size. Supported values are B
(bytes), KB (kilobytes), MB (megabytes), and GB (gigabytes). Default is MB.
.EXAMPLE
Get-DirectorySize -Path "C:\Temp" -In GB
This example calculates the total size of all files within the C:\Temp
directory and its subdirectories, and displays the result in gigabytes.
.INPUTS
System.String
.OUTPUTS
System.String
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false, ValueFromPipeline = $true, Position = 0)]
[string] $Path = '.',
[Parameter(Mandatory = $false, Position = 1)]
[ValidateSet('B', 'KB', 'MB', 'GB')]
[string] $In = "MB"
)
process {
$colItems = (Get-ChildItem -Path $Path -Recurse -File | Measure-Object -Property Length -Sum)
$sizeInBytes = $colItems.Sum
$formattedSize = switch ($In) {
"GB" { "{0:N2} GB" -f ($sizeInBytes / 1GB) }
"MB" { "{0:N2} MB" -f ($sizeInBytes / 1MB) }
"KB" { "{0:N2} KB" -f ($sizeInBytes / 1KB) }
"B" { "{0:N2} B" -f $sizeInBytes }
}
return $formattedSize
}
}
function ConvertTo-JsonPretty {
<#
.SYNOPSIS
Convert an object to a pretty-printed JSON string.
.DESCRIPTION
The ConvertTo-JsonPretty function takes an input object, converts it to JSON, and then formats the JSON string with proper indentation and line breaks for easier readability.
.PARAMETER InputObject
The object to be converted to a pretty-printed JSON string.
.EXAMPLE
$data = @{
Name = "John Doe"
Age = 30
City = "New York"
}
ConvertTo-JsonPretty -InputObject $data
This example converts the $data object to a pretty-printed JSON string.
.INPUTS
System.Management.Automation.PSObject
.OUTPUTS
System.String
#>
param(
[Parameter(Mandatory, ValueFromPipeline = $true)]
[PSObject] $InputObject
)
process {
$InputObject | ConvertTo-Json -Depth 100 | Set-Content -Path 'temp.json'
Get-Content -Path 'temp.json' -Raw | ConvertFrom-Json | ConvertTo-Json -Depth 100
Remove-Item -Path 'temp.json' -Force
}
}
function Split-Array {
<#
.SYNOPSIS
Splits an input array into smaller subarrays with a specified maximum number of elements.
.DESCRIPTION
The Split-Array function takes an input array and splits it into smaller subarrays, each containing a specified maximum number of elements. The function is useful when dealing with large arrays that need to be processed in smaller chunks.
.PARAMETER InputArray
The input array that you want to split into smaller subarrays. This parameter is mandatory and accepts pipeline input.
.PARAMETER MaximumElements
The maximum number of elements allowed in each smaller subarray. The default value is 10.
.EXAMPLE
$myArray = 1..20
$splitArrays = Split-Array -InputArray $myArray -MaximumElements 5
This example splits the input array $myArray (which contains numbers 1 to 20) into smaller subarrays of 5 elements each:
(1, 2, 3, 4, 5),
(6, 7, 8, 9, 10),
(11, 12, 13, 14, 15),
(16, 17, 18, 19, 20)
.INPUTS
System.Object[]
.OUTPUTS
System.Collections.ArrayList
#>
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline = $true)]
[object[]] $InputArray,
[Alias('Max','Size')]
[int] $MaximumElements = 10
)
begin {
$OutputArrayList = [System.Collections.ArrayList]::new()
}
process {
for($i = 0; $i -lt $InputArray.Length; $i += $MaximumElements) {
$slice = $InputArray[$i..($i + $MaximumElements - 1)]
$null = $OutputArrayList.Add($slice)
}
}
end {
Write-Output $OutputArrayList
}
}
function Add-GitDeleteFiles {
<#
.SYNOPSIS
Creates .gitdelete files in empty directories within a Git repository.
.DESCRIPTION
The Add-GitDeleteFiles function creates .gitdelete files in empty directories within a Git repository.
The -Cleanup switch removes .gitdelete files from directories that are no longer empty.
.PARAMETER Path
The path to the root directory of the Git repository. Defaults to the current location.
.PARAMETER Cleanup
If specified, the function will remove .gitdelete files from directories that are no longer empty.
.EXAMPLE
Add-GitDeleteFiles -Path "C:\MyGitRepo"
Creates .gitdelete files in all empty directories within the specified Git repository.
.EXAMPLE
Add-GitDeleteFiles -Path "C:\MyGitRepo" -Cleanup
Creates .gitdelete files in empty directories and removes .gitdelete files from directories that are no longer empty.
.EXAMPLE
Get-ChildItem -Path "C:\MyGitRepos" -Directory | Add-GitDeleteFiles -Cleanup
Demonstrates how to use pipeline input with Add-GitDeleteFiles to process multiple repositories.
#>
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true)]
[string[]]$Path = (Get-Location).Path,
[switch]$Cleanup
)
process {
foreach ($dirPath in $Path) {
$Directories = Get-ChildItem -Path $dirPath -Directory -Recurse -ErrorAction SilentlyContinue
foreach ($directory in $Directories) {
$ChildItems = Get-ChildItem -Path $directory -ErrorAction SilentlyContinue
$gitDeletePath = Join-Path $directory.FullName '.gitdelete'
if ($ChildItems.Count -eq 0) {
$null = New-Item -Path $gitDeletePath -ItemType File -Verbose
Write-Verbose "Created .gitdelete at $($directory.FullName)"
} elseif ($Cleanup -and ($ChildItems.Count -gt 1) -and ($ChildItems.Name -contains '.gitdelete')) {
$null = Remove-Item -Path $gitDeletePath -Force -Verbose
Write-Verbose "Removed .gitdelete from $($directory.FullName)"
}
}
}
}
}
function ConvertFrom-UnixTimestamp {
<#
.SYNOPSIS
Converts a Unix timestamp to a DateTime object.
.DESCRIPTION
The ConvertFrom-UnixTimestamp function takes a Unix timestamp as input (in seconds or milliseconds)
and converts it to a DateTime object.
.PARAMETER UnixTimestamp
The Unix timestamp to convert to a DateTime object. This can be in seconds or milliseconds.
.EXAMPLE
$unixTimestamp = 1682705422
$dateTime = ConvertFrom-UnixTimestamp -UnixTimestamp $unixTimestamp
Write-Host $dateTime
Converts the Unix timestamp 1682705422 to a DateTime object and displays it.
.EXAMPLE
$unixTimestamp = 1682705422
$dateTime = $unixTimestamp | ConvertFrom-UnixTimestamp
Write-Host $dateTime
Demonstrates how to use pipeline input with ConvertFrom-UnixTimestamp.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[double]$UnixTimestamp
)
process {
$origin = [DateTime]::new(1970, 1, 1, 0, 0, 0, 0, [DateTimeKind]::Utc)
# Check if the Unix timestamp is in milliseconds
if ($UnixTimestamp -gt [DateTime]::MaxValue.Ticks / [TimeSpan]::TicksPerSecond) {
# Convert Unix timestamp from milliseconds to seconds
$UnixTimestamp /= 1000
}
$convertedDateTime = $origin.AddSeconds($UnixTimestamp).ToLocalTime()
return $convertedDateTime
}
}
function ConvertTo-UnixTimestamp {
<#
.SYNOPSIS
Converts a DateTime object to a Unix timestamp.
.DESCRIPTION
The ConvertTo-UnixTimestamp function takes a DateTime object as input and converts it to a Unix timestamp
in seconds.
.PARAMETER DateTime
The DateTime object to convert to a Unix timestamp.
.EXAMPLE
$dateTime = Get-Date
$unixTimestamp = ConvertTo-UnixTimestamp -DateTime $dateTime
Write-Host $unixTimestamp
Converts the current date and time to a Unix timestamp and displays it.
.EXAMPLE
$dateTime = Get-Date
$unixTimestamp = $dateTime | ConvertTo-UnixTimestamp
Write-Host $unixTimestamp
Demonstrates how to use pipeline input with ConvertTo-UnixTimestamp.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[DateTime]$DateTime
)
process {
$origin = [DateTime]::new(1970, 1, 1, 0, 0, 0, 0, [DateTimeKind]::Utc)
$dateTimeUtc = $DateTime.ToUniversalTime()
$timeSpan = $dateTimeUtc - $origin
$unixTimestamp = [int64]$timeSpan.TotalSeconds
return $unixTimestamp
}
}
function ConvertFrom-ADFileTime {
<#
.SYNOPSIS
Converts an Active Directory FileTime value to a DateTime object.
.DESCRIPTION
The ConvertFrom-ADFileTime function takes an Active Directory FileTime value as input,
which represents the number of 100-nanosecond intervals since January 1, 1601 (UTC),
and converts it to a DateTime object.
.PARAMETER ADFileTime
The Active Directory FileTime value to convert to a DateTime object.
.EXAMPLE
$pwdLastSet = 133251702158073284
$dateTime = ConvertFrom-ADFileTime -ADFileTime $pwdLastSet
Write-Host $dateTime
Converts the Active Directory FileTime value 133251702158073284 to a DateTime object and displays it.
.EXAMPLE
$pwdLastSet = 133251702158073284
$dateTime = $pwdLastSet | ConvertFrom-ADFileTime
Write-Host $dateTime
Demonstrates how to use pipeline input with ConvertFrom-ADFileTime.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[int64]$ADFileTime
)
process {
$dateTime = [DateTime]::FromFileTimeUtc($ADFileTime).ToLocalTime()
return $dateTime
}
}
function New-RandomPassword {
<#
.SYNOPSIS
Generates a random password with specified requirements.
.DESCRIPTION
The New-RandomPassword function generates a random password with a given length and character set.
It ensures that the password contains at least one uppercase character, one lowercase character,
one special character, and one number. It also allows excluding specific characters from the password.
.PARAMETER Length
Specifies the length of the generated password. The default length is 24 characters.
.PARAMETER ExcludedCharacters
An array of characters that should not be included in the generated password.
The default excluded characters are: "`", "|", and "\".
.EXAMPLE
New-RandomPassword -Length 16
Generates a random password with 16 characters, containing at least one uppercase character,
one lowercase character, one special character, and one number.
.EXAMPLE
New-RandomPassword -ExcludedCharacters @("A", "1", "@")
Generates a random password that does not contain the characters "A", "1", or "@".
.NOTES
The generated password may not be cryptographically secure.
Use the function with caution when generating high-security passwords.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[int]$Length = 24,
[Parameter(Mandatory = $false)]
[string[]]$ExcludedCharacters = @('`', '|', '\'),
[switch] $AsSecureString
)
process {
$upperCase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
$lowerCase = 'abcdefghijklmnopqrstuvwxyz'
$digits = '0123456789'
$specialChars = '!@#$%^&*()-_=+[]{};:,.<>?/'
$password = @()
$password += Get-Random -InputObject $upperCase.ToCharArray()
$password += Get-Random -InputObject $lowerCase.ToCharArray()
$password += Get-Random -InputObject $digits.ToCharArray()
$password += Get-Random -InputObject $specialChars.ToCharArray()
$remainingLength = $Length - 4
$allChars = $upperCase + $lowerCase + $digits + $specialChars
# Remove excluded characters from the character set
$allowedChars = $allChars.ToCharArray() | Where-Object { $_ -notin $ExcludedCharacters }
for ($i = 0; $i -lt $remainingLength; $i++) {
$password += Get-Random -InputObject $allowedChars
}
# Shuffle the password characters
$password = $password | Get-Random -Count $password.Count
# Convert the password array to a string
if ($AsSecureString) {
$output = ConvertTo-SecureString (-join $password) -Asplaintext -Force
} else {
$output = -join $password
}
Write-Output $output
}
}
function New-DcrXPathFilter {
param(
[string[]] $EventIds,
[string] $LogName,
[ValidateSet('or', 'and')]
[string] $Operator = 'or'
)
if ($EventIds.Count -eq 0) {
throw 'No EventIds specified'
} elseif ($EventIds.Count -eq 1) {
Write-Output ('{0}!*[System[EventID={1}]]' -f ($LogName.Substring(0,1).toUpper() + $LogName.Substring(1).tolower()), $EventIds[0])
return
} elseif ($EventIds.Count -gt 20) {
$output = @()
$output += New-DcrXPathFilter -EventIds $EventIds[0..19] -LogName $LogName -Operator $Operator
$output += New-DcrXPathFilter -EventIds $EventIds[20..($EventIds.Count - 1)] -LogName $LogName -Operator $Operator
Write-Output $output
} else {
$sb = [System.Text.StringBuilder]::new()
$null = $sb.Append(('{0}!*[System[(' -f ($LogName.Substring(0,1).toUpper() + $LogName.Substring(1).tolower())))
$limit = $EventIds.Count
for ($i=0; $i -lt $limit; $i++) {
$null = $sb.Append(('EventID={0}' -f $EventIds[$i]))
if ($EventIds[$i] -ne $EventIds[-1]) {
$null = $sb.Append(' or ')
}
}
$null = $sb.Append(')]]')
Write-Output $sb.ToString()
}
}
function ConvertTo-Base64String {
<#
.SYNOPSIS
Converts a given string to a Base64 encoded string.
.DESCRIPTION
The ConvertTo-Base64String function takes an input string and converts
it to a Base64 encoded string. The function uses UTF-8 encoding for the
conversion.
.PARAMETER String
The input string to be converted to a Base64 encoded string. This
parameter is mandatory and accepts pipeline input.
.EXAMPLE
$base64String = ConvertTo-Base64String -String "Hello, world!"
This example converts the input string "Hello, world!" to a Base64 encoded string.
.INPUTS
System.String
.OUTPUTS
System.String
#>
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline = $true)]
[string] $String
)
process {
$bytes = [System.Text.Encoding]::UTF8.GetBytes($String)
$base64 = [System.Convert]::ToBase64String($bytes)
Write-Output $base64
}
}
function ConvertFrom-Base64String {
<#
.SYNOPSIS
Converts a given Base64 encoded string to its original string representation.
.DESCRIPTION
The ConvertFrom-Base64String function takes an input Base64 encoded string
and converts it back to its original string representation. The function
uses UTF-8 encoding for the conversion.
.PARAMETER Base64String
The input Base64 encoded string to be converted back to its original
tring representation. This parameter is mandatory and accepts pipeline input.
.EXAMPLE
$originalString = ConvertFrom-Base64String -Base64String "SGVsbG8sIHdvcmxkIQ=="
This example converts the input Base64 encoded string "SGVsbG8sIHdvcmxkIQ=="
back to its original string representation: "Hello, world!".
.INPUTS
System.String
.OUTPUTS
System.String
#>
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline = $true)]
[string] $Base64String
)
process {
$bytes = [System.Convert]::FromBase64String($Base64String)
$originalString = [System.Text.Encoding]::UTF8.GetString($bytes)
Write-Output $originalString
}
}
function Test-Base64String {
<#
.SYNOPSIS
Checks if a given string is in Base64 format.
.DESCRIPTION
The Test-Base64String function takes an input string and checks if it is
a valid Base64 encoded string using a regular expression pattern. The
function returns $true if the string is a valid Base64 encoded string,
and $false otherwise.
.PARAMETER InputString
The input string to be checked for Base64 format. This parameter is
mandatory and accepts pipeline input.
.EXAMPLE
$isBase64 = Test-Base64String -InputString "SGVsbG8sIHdvcmxkIQ=="
This example checks if the input string "SGVsbG8sIHdvcmxkIQ==" is a valid
Base64 encoded string. The function returns $true in this case.
.INPUTS
System.String
.OUTPUTS
System.Boolean
#>
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline = $true)]
[string] $InputString
)
process {
$base64Pattern = '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$'
return $InputString -match $base64Pattern
}
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment