PowerShell Profiles
Last active
January 31, 2024 21:09
-
-
Save chadbaldwin/2ae7373ce6eb51c1b05b291c7dee40d8 to your computer and use it in GitHub Desktop.
My personal PowerShell profile file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* | |
!Microsoft.*_profile.ps1 | |
!.gitignore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# gist - https://gist.github.com/chadbaldwin/2ae7373ce6eb51c1b05b291c7dee40d8 | |
###################################################### | |
# Prompt customization | |
###################################################### | |
oh-my-posh init pwsh | iex | |
# Commented out because it was causing errors in the terminal | |
# Set-PSReadLineOption -PredictionViewStyle ListView | |
###################################################### | |
###################################################### | |
# Script Imports | |
###################################################### | |
###################################################### | |
###################################################### | |
# Add custom paths to PATH | |
###################################################### | |
$env:Path = (( | |
@( | |
, 'C:\Program Files\Microsoft SQL Server\160\DAC\bin' # SqlPackage.exe | |
, 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\' # MSBuild + SSDT | |
, 'C:\Program Files\Rancher Desktop\resources\resources\win32\bin\' # Rancher - Docker CLI / nerdctl | |
, 'C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\' # SQLCMD | |
, 'C:\Program Files (x86)\Red Gate\SQL Compare 15\' # sqlcompare | |
) + | |
$env:Path -split ';' | | |
gi -ErrorAction SilentlyContinue | | |
select @{N='Path'; E={[System.IO.Path]::TrimEndingDirectorySeparator($_)}} | | |
% Path | |
) | select -Unique) -join ';' | |
###################################################### | |
###################################################### | |
# Module Imports | |
###################################################### | |
# Import-Module posh-git | |
Import-Module "${env:ChocolateyInstall}\helpers\chocolateyProfile.psm1" -ErrorAction SilentlyContinue | |
###################################################### | |
###################################################### | |
# Custom Git Functions | |
###################################################### | |
# Run "git pull" on all Directories in the current directory | |
function Git-PullAll { | |
Get-ChildItem -Directory | | |
ForEach-Object { | |
$_.FullName | |
Start-Job -WorkingDirectory $_ -ScriptBlock { git pull } | Receive-Job -AutoRemoveJob -Wait | |
} | |
} | |
function Test-IsInsideGitRepo { | |
param ( | |
[Parameter(Position=0)][string]$Path = '.\' | |
) | |
(git -C $Path rev-parse --is-inside-work-tree 2> $null) -EQ 'true' ? $true : $false | |
} | |
function Initialize-GitRepository { | |
git init -b 'main' | |
git add . | |
git commit -m 'init' | |
} | |
###################################################### | |
###################################################### | |
# Custom Docker Functions | |
###################################################### | |
# gist - https://gist.github.com/chadbaldwin/1a486b4fbf48e9b0cd9551cb7e16382a | |
<# Docs: | |
https://hub.docker.com/_/microsoft-mssql-server | |
https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-configure-environment-variables | |
#> | |
# Start SQL Server docker instance | |
function Start-SQLServer { | |
param ( | |
[Parameter()][string]$Tag = 'latest', | |
[Parameter()][string]$ContainerName = 'sqlserver', | |
[Parameter()][string]$Hostname, | |
[Parameter()][int]$Port = 1433, | |
[Parameter()][ValidateSet('Evaluation','Developer','Express','Web','Standard','Enterprise')] | |
[string]$Edition, | |
[Parameter()][switch]$EnableSQLServerAgent, | |
[Parameter()][string]$ContainerTimeZone | |
) | |
$sa_password = 'yourStrong(!)Password' | |
$container = docker inspect $ContainerName | ConvertFrom-Json | |
# create & start | |
if ($null -eq $container) { | |
# Build params to use for docker run call | |
$params = ( | |
'--name', $ContainerName, | |
'-e', 'ACCEPT_EULA=Y', | |
'-e', "MSSQL_SA_PASSWORD=${sa_password}", | |
'-p', "${Port}:1433" | |
) | |
# optional params | |
if ($Hostname) { $params += '-h', $Hostname } | |
if ($Edition) { $params += '-e', "MSSQL_PID=$Edition" } | |
if ($EnableSQLServerAgent) { $params += '-e', "MSSQL_AGENT_ENABLED=${EnableSQLServerAgent}" } | |
if ($ContainerTimeZone) { $params += '-e', "TZ=${ContainerTimeZone}" } | |
docker run -d @params "mcr.microsoft.com/mssql/server:${Tag}" | |
if (!$LASTEXITCODE) { write "Container '${ContainerName}' container has been created and started" } | |
} | |
else { | |
$Tag = $container.Config.Image | |
# start | |
if ($container.State.Status -eq 'exited') { | |
docker start $containerName | |
write "Container '${ContainerName}' was already created and has been started" | |
} | |
# do nothing | |
elseif ($container.State.Status -eq 'running') { | |
write "Container '${ContainerName}' is already running" | |
} | |
$sa_password = (($container.Config.Env | ? { $_ -match 'MSSQL_SA_PASSWORD' }) -split '=')[1] | |
} | |
write '','Waiting until database is available...' | |
while ($true) { | |
docker exec $ContainerName /opt/mssql-tools/bin/sqlcmd -U sa -P $sa_password -l 1 -t 1 -Q 'SELECT 1' *>&1 | Out-Null | |
# Commenting out - using docker exec instead to remove dependency on sqlcmd being installed locally | |
# sqlcmd -U sa -P $sa_password -S localhost -l 1 -t 1 -Q 'SELECT 1' *>&1 | Out-Null | |
if ($LASTEXITCODE -eq 0) { break } | |
sleep 1 | |
} | |
$container = docker inspect $ContainerName | ConvertFrom-Json | |
write '',"Image: ${Tag}",'',"SQL Server Version: $($container.Config.Labels.'com.microsoft.version')",'' | |
scb $sa_password | |
write 'Password copied to clipboard:',' Username: sa'," Password: ${sa_password}" | |
} | |
Register-ArgumentCompleter -CommandName Start-SQLServer -ParameterName Tag -ScriptBlock { | |
(irm 'https://mcr.microsoft.com/v2/mssql/server/tags/list').tags | ? { $_ -match 'latest' } | |
} | |
###################################################### | |
###################################################### | |
# Other | |
###################################################### | |
# pseudo sudo - Opens a new instance of the current shell under an admin account | |
function sudo { | |
$process = Get-Process -Id $PID | |
if ($process.Parent.Name -eq 'WindowsTerminal') { | |
<# Hard coded to use the PowerShell Core profile. | |
For some reason, Windows PowerShell doesn't seem to be aware | |
that it is running within Windows Terminal when pulling the | |
proess via Get-Process. #> | |
Start-Process 'wt' -ArgumentList "-p 'PowerShell' -d `"${PWD}`"" -Verb RunAs | |
} elseif ($process.Name -eq 'pwsh') { | |
Start-Process 'pwsh' -WorkingDirectory $PWD -Verb RunAs | |
} elseif ($process.Name -eq 'powershell') { | |
Start-Process 'powershell' -WorkingDirectory $PWD -Verb RunAs | |
} | |
} | |
# Sets the title of the current powershell window | |
function Set-Title($Title) { | |
$host.ui.RawUI.WindowTitle = $Title | |
} | |
# Removes all empty directories recursively in the current directory | |
function Remove-EmptyDirectories { | |
Get-ChildItem -Path $folder -Directory -Recurse | Where-Object { -Not $_.GetFiles('*',1) } | Remove-Item -Recurse | |
} | |
# Cleans build data and user settings from a visual studio solution folder | |
function Clean-SolutionFolder { | |
'bin','obj','.vs' | Get-ChildItem -Directory -Recurse -Force | Remove-Item -Force -Recurse | |
'*.user' | Get-ChildItem -File -Recurse | Remove-Item -Force -Recurse | |
} | |
# Shortcut for bypassing explorer...instead using Powershell and ZLocation. | |
function Invoke-QuickOpen { | |
param ([Parameter()][string]$Search) | |
z $Search | |
Invoke-Item . | |
exit | |
} | |
# Open the local .sln file. If there's multiple, bring them up in fzf | |
function Open-Solution { | |
$files = Get-ChildItem -Filter *.sln | |
if ($files.Count -eq 0) { | |
Write-Output 'No *.sln files found' | |
} elseif ($files.Count -eq 1) { | |
Invoke-Item "${files}" | |
} else { | |
$file = $files | Where-Object ToString | fzf | |
Invoke-Item "${file}" | |
} | |
} | |
# Bring window specified by process name into focus | |
function Set-ForegroundWindow { | |
[CmdletBinding()] | |
param ( | |
[Parameter(ValueFromPipeline)][string]$ProcessName, | |
[Parameter()][int]$ShowType | |
) | |
$type = ' | |
using System; | |
using System.Runtime.InteropServices; | |
public class WinAp { | |
[DllImport("user32.dll")] | |
public static extern bool SetForegroundWindow(IntPtr hWnd); | |
[DllImport("user32.dll")] | |
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); | |
}' | |
Add-Type $type | |
# Pick the first window that matches this process | |
$h = (Get-Process -Name $ProcessName | Where-Object MainWindowTitle | Select-Object -First 1).MainWindowHandle | |
# If you can't find the window, exit | |
if ($null -eq $h) { return } | |
# 2 = Minimize window | |
[WinAp]::ShowWindow($h, 2) # minimize it first...this is a hack so that we maintain snapped window positions | |
# 4 or 9 = Restore window, these are the only ones that seem to work predictably. | |
# They will restore a window to its original position if it is minimized, even if the window was snapped | |
# However, if the window is not minimized but is only out of focus, then it will unsnap the window. | |
# This is why we first minimize it, then restore it. It's hacky, but it works. It just looks a little funny. | |
[WinAp]::ShowWindow($h, 4) | |
# Bring window into focus | |
[WinAp]::SetForegroundWindow($h) | |
} | |
# Sort, dedup and overwrite clipboard contents | |
function Sort-Clipboard { | |
gcb | ? { $_.Trim() } | sort -Unique | scb | |
} | |
# Takes a pipeline input and groups it into batches of N size then returns the new arrays | |
function Get-Batches { | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory = $true)][int]$BatchSize, | |
[Parameter(ValueFromPipeline = $true)][psobject]$InputObject | |
) | |
begin { | |
$currentBatch = @() | |
} | |
process { | |
$currentBatch += $_ | |
if ($currentBatch.Count -eq $BatchSize) { | |
,$currentBatch | |
$currentBatch = @() | |
} | |
} | |
end { | |
if ($currentBatch.Count -gt 0) { | |
,$currentBatch | |
} | |
} | |
} | |
# Usage Examples: | |
# Write-Output (1..101) -NoEnumerate | Get-Batches -BatchSize 6 | % { $_ -join ',' } | |
# Get-Batches -BatchSize 6 -Array (1..101) | % { $_ -join ',' } | |
# Write-Output (1..101) -NoEnumerate | Get-Batches 6 | % { $_ -join ',' } | |
# Get-Batches 6 (1..101) | % { $_ -join ',' } | |
###################################################### | |
###################################################### | |
# Find system tools | |
###################################################### | |
# Useful for finding things like msbuild.exe, vswhere.exe, sqlpackage.exe, etc | |
function Find-SystemTool { | |
param ( | |
[Parameter(Mandatory,Position=0)][string]$Search | |
) | |
# Because we're searching a lot of system directories, we run into a lot of access denied errors. So for now | |
# it's easier to just ignore all and continue on. Maybe in the future I'll add better error handling. | |
$ErrorActionPreference = 'SilentlyContinue' | |
$list = @() | |
# Search PowerShell aware commands - this needs to be prioritized to indicate it can be called without including the full path | |
$list += Get-Command $Search -All | | |
Select-Object @{N='Path';E={$_.Source}}, | |
Version, | |
@{N='Source';E={'Get-Command'}}, @{N='Rank';E={1}} | |
if (Get-Command es) { | |
# If system has `Everything` cli installed, use that instead since it is the fastest | |
$list += es !"${env:SystemRoot}" !"${env:USERPROFILE}\Appdata" "*${Search}" | | |
Get-Item | | |
Select-Object @{N='Path';E={$_.FullName}}, | |
@{N='Version';E={$_.VersionInfo.ProductVersionRaw}}, | |
@{N='Source';E={'Everything'}}, @{N='Rank';E={2}} | |
} else { | |
# Search all path directories - redundant with Get-Command, except for non-applications (modules, scripts, etc) | |
$list += $env:Path -split ';' | | |
Get-Item | | |
Get-ChildItem -File -Filter $Search | | |
Select-Object @{N='Path';E={$_.FullName}}, | |
@{N='Version';E={$_.VersionInfo.ProductVersionRaw}}, | |
@{N='Source';E={'Path'}}, @{N='Rank';E={2}} | |
# Search all common directories - this is by far the slowest because we are recursively searching many system folders | |
$list += $env:ProgramFiles, ${env:ProgramFiles(x86)}, $env:ProgramData, | |
$env:ChocolateyToolsLocation, $env:ChocolateyInstall | | |
Get-Item | | |
Get-ChildItem -File -Recurse -Filter $Search | | |
Select-Object @{N='Path';E={$_.FullName}}, | |
@{N='Version';E={$_.VersionInfo.ProductVersionRaw}}, | |
@{N='Source';E={'Manual'}}, @{N='Rank';E={3}} | |
} | |
# Dedup by path, select first by rank | |
$list | | |
Group-Object Path | | |
ForEach-Object { $_.Group | Sort-Object Rank | Select-Object -First 1 } | | |
Sort-Object Version -Descending | | |
Select-Object Path, Version, Source | |
} | |
###################################################### | |
###################################################### | |
# Aliases | |
###################################################### | |
Set-Alias -Name zz -Value 'Invoke-QuickOpen' | |
Set-Alias -Name npp -Value "${Env:ProgramFiles(x86)}\Notepad++\notepad++.exe" | |
Set-Alias -Name w -Value 'Set-ForegroundWindow' | |
Set-Alias -Name query -Value 'Invoke-DbaQuery' | |
Set-Alias -Name sln -Value 'Open-Solution' | |
Set-Alias -Name omp -Value 'oh-my-posh.exe' | |
Set-Alias -Name igr -Value 'Initialize-GitRepository' | |
Set-Alias -Name ginit -Value 'Initialize-GitRepository' | |
###################################################### | |
###################################################### | |
###################################################### |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
write "Profile: $($MyInvocation.MyCommand.Name)" | |
write "Loading: Microsoft.PowerShell_profile.ps1" | |
$userprofile = Join-Path ([Environment]::GetFolderPath("MyDocuments")) 'PowerShell\Microsoft.PowerShell_profile.ps1' | gi | |
. $userprofile |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
[reserving first comment]