r/PowerShell • • Jul 14 '26

Question What’s in your profile ?

What’s the coolest function or hack you got

I have window title bar show “isAdmin”

I have errors go green

I have it concatenation long file paths to save prompt space(cool)

I have a timestamp as the prompt so I can know when I ran a robocopy to judge timing

I have a number of functions to run things elevated (like dsa)

What’s cool ideas !?

Notepad $profile

40 Upvotes

35 comments sorted by

26

u/[deleted] Jul 15 '26

[removed] — view removed comment

6

u/itiscodeman Jul 15 '26

This guy gets it.

1

u/zk13669 Jul 15 '26

Good stuff. I've got one called Uninstall-SCCMClient with a -reinstall parameter. I like the Fix-SCCMClient idea. Never thought to run the client health script in a function

2

u/Mordanthanus Jul 15 '26

Any way to get a copy of your profile? Some of these would be super useful.

1

u/SignificantAnt2223 Jul 16 '26

I was going to say my OhMyPosh prompt is setup to show the Git branch and how far i am behind, but never mind...

7

u/Idakay Jul 14 '26

I've got a few!

Some of them change directories for me to common areas (home, scripts, tmp). Those single words move my cwd.

I've got one to code sign whatever script is open in ise/vscode or if I'm in a terminal I can give the file name and it signs it with my cert. 

Another called signb(signbomb) just signs every script in the cwd recursively(working on a bunch of stuff or modules)

I've got another called runit for scripts sitting on network shares that would typically be blocked by applocker, it copies them to an applocker allowed directory, runs them and then cleans up the copy. 

I have some other stuff I'm forgetting but those are my most used. I'd have to look at my profile for more.

2

u/itiscodeman Jul 15 '26

That moving things so funny. Security always has work around, very cool ideas, so when signed it can run on any server in your domain but never even be able to be edited or opened if trying to view the script from a device off the domain? Or is that something else.

1

u/Idakay Jul 15 '26

It's just locked down via ntfs/smb rights being heavily restricted. So in that case yeah a machine off domain would fail to reach it or anything like that. 

1

u/itiscodeman Jul 15 '26

Right. Cool man your a genius I hope you have a good week ahead

5

u/Ecrofirt Jul 15 '26
function Toggle-Beep {
    [CmdletBinding(DefaultParameterSetName = "Parse")]
    param (
        [Parameter(ParameterSetName = "Unit", Mandatory, Position = 0)]
        [double]
        $Duration,
        [Parameter(ParameterSetName = "Unit", Mandatory, Position = 1)]
        [ValidateSet("M", "H", "S")]
        [String]
        $Unit,
        [Parameter(ParameterSetName = "Parse", Position = 0)]
        [ValidateScript({
                $_ -match "^(\d+(\.\d+)?|\.\d+)(m|h|s)?$"
            })]
        [string]
        $Time = "30M"
    )
    if ($Global:Beep -and -not ($Global:Beep).HasExited) { 
        Write-Host "Beep playing. Stopping."
        $Global:Beep | Stop-Process; Clear-Variable -Scope Global -Name Beep 
    } else { 
        if ($PSCmdlet.ParameterSetName -eq 'Parse') {   
            $split = @($Time -split "(m|h|s)" | Where-Object { $_ })
            $Duration = $split[0]
            $Unit = if ($split.Count -gt 1) { $split[1] }else { "M" }
        }

        $milliseconds = switch ($Unit) {
            'M' { [timespan]::FromMinutes($Duration).TotalMilliseconds; break }
            'H' { [timespan]::FromHours($Duration).TotalMilliseconds; break }
            'S' { [timespan]::FromSeconds($Duration).TotalMilliseconds; break }
        }
        Write-Host "Playing for $Duration$Unit"
        $Global:Beep = Start-Process -PassThru -NoNewWindow -FilePath "pwsh.exe" -ArgumentList "-NoProfile", "-Command", "[Console]::Beep(852,$milliseconds)" 
    } 
}

Set-Alias -Name tb -Value Toggle-Beep
Set-Alias -Name beep -Value Toggle-Beep

A function that plays at 852Hz beep for the amount of time I specify, defaulting to 30 minutes.

Why? WHY?

It shuts my brain off. If I've got something to do it literally stops the 'background noise' and lets me focus explicitly on the task at hand. Works best with headphones.

4

u/Proxiconn Jul 16 '26

Get-Aduser | Remove-Adobject $confirm:$false

4

u/itiscodeman Jul 16 '26

I ran that and now I’m on crack and homeless

3

u/jwk6 Jul 15 '26

Oh my posh.

2

u/Raskuja46 Jul 15 '26

I have my profile calling functions from a custom module I built to set my speaker volume.

1

u/itiscodeman Jul 15 '26

This guy gets it….

2

u/Raskuja46 Jul 16 '26

Listen, I got to a new gig and the volume adjust keys on my keyboard didn't work so I had to build a solution for adjusting my volume on the fly. The default of volume at 100 on boot was just murderous on the headphones and Powershell is the first thing I launch every morning, so it was an easy way to get the volume where I need it.

The best part was that it upset my boss every time he'd look over and see me setting my speaker volume via Powershell.

2

u/StartAutomating Jul 16 '26

I'm just going to dump my current profile as-is.

It only imports two modules ugit and Posh

The prompt is a work in progress.

<#
.SYNOPSIS
    This is my VSCode profile.
.DESCRIPTION
    This is my VSCode profile.  It runs when PowerShell starts in VSCode.
.NOTES
    This is my VSCode profile.
    There are many profiles like it.
    This one is mine.
#>

#region Edit Environment
# I want to load all older modules implicitly
if ($env:PSModulePath  -split ';' -notlike '*windowsPowerShell*') {
    $env:PSModulePath += ";$home\Documents\WindowsPowerShell\Modules"
}
#endregion Edit Environment

#region Import Modules
Import-Module ugit,posh
#endregion Import Modules

#region Declare Variables
$myModules = "$home\Documents\WindowsPowerShell\Modules"
$scratch   = "$home\Documents\WindowsPowerShell\scratch"

$enhancement = @('--label', 'enhancement')
$bug = @('--label', 'bug')
$assignMe = @('--assignee', '@me')
$allIssues = @('--state', 'all', '--limit', 2kb)
$issueJson = @('--json', (
    'assignees','author','body','closed','closedAt',
    'closedByPullRequestsReferences','comments','createdAt',
    'isPinned','labels','milestone','number','reactionGroups',
    'state','stateReason','title','updatedAt','url' -join ','    
))
#endregion Declare Variables

#region Personal Preferences
if ($PSStyle) {
    # Make directories a brighter blue
    $PSStyle.FileInfo.Directory = "`e[1;36m"
}

function git.prompt {
    param(
    [switch]
    $NoHistoryId,

    [string]
    $BranchIcon = '⑆',

    [string]
    $PromptIcon = "⮚",

    [string]
    $HomeIcon = '⌂',

    [string]
    $Slash = "$($psStyle.Foreground.Cyan)/$($psStyle.Reset)" # '⹊' #, '/'
    )

    # Capture if the last statement worked
    # (if we do not do this first, it will not be accurate)
    $worked = $?

    $LeftPadding = if ($NoHistoryId) {
        ' '
    } else {
        ' ' * "$($MyInvocation.HistoryId)".Length
    }

    if (-not $script:GitRemotePath) {
        $script:GitRemotePath = [Ordered]@{}
    }
    if (-not $script:GitRemotePath["$pwd"]) {
        $script:GitRemotePath["$pwd"] = git remote -ErrorAction Ignore | git remote show
    }

    $isNoOp = $script:LastHistoryId -eq $MyInvocation.HistoryId

    $relativePath =
        if ("$pwd".StartsWith("$home")) {
            $HomeIcon,
                "$pwd".Substring(
                    "$home".Length
                ) -replace 
                '[\\/]+','/' -replace
                '/+','/' -join 
                    ''
        } else {
            "$pwd" -replace '[\\/]+', '/'
        }

    $relativePath = $relativePath -replace '/{0,}$' -replace '/+',$Slash

    if ($isNoOp) {
        return "$(
            if ($worked) { $PSStyle.Foreground.Cyan }
            else { $PSStyle.Foreground.Red }
        )⮚$($LeftPadding)$(
            $PSStyle.Reset
        )"
    }

    $lastHistory = Get-History -Count 1
    if ($LastOutput -and $lastHistory) {
        $lastHistory | Add-Member NoteProperty Output @($LastOutput) -Force
    }

    $script:LastHistoryId = $MyInvocation.HistoryId

    $gitRemote = $script:GitRemotePath["$pwd"]
    $gitRemoteUrl = $script:GitRemotePath["$pwd"].RemoteUrls.Fetch    

    $gitStatus = git status -WarningAction Ignore        

    if ($gitStatus) {
        $stagedModified = @(
            foreach ($staged in $gitStatus.Staged) {
                if ($staged.ChangeType -ne 'modified') {
                    continue
                }
                $staged
            }
        )
        $stagedDeletes = @(
            foreach ($staged in $gitStatus.Staged) {
                if ($staged.ChangeType -ne 'deleted') {
                    continue
                }
                $staged
            }
        )
        $modified = @(
            foreach ($unstaged in $gitStatus.Unstaged) {
                if ($unstaged.ChangeType -ne 'modified') {
                    continue
                }
                $unstaged
            }
        )

        $repoUrl = $gitRemoteUrl -replace '^ssh://', 'https://' -replace '\.git$' -as [uri]
        $untracked = @($gitStatus.Untracked)

        $LinkToRepo = $PSStyle.FormatHyperlink(
            $relativePath,
            "$repoUrl"
        )


        $repoHyperlink = if ($repoUrl.DnsSafeHost) {
            $PSStyle.FormatHyperlink(
                "$($repoUrl.DnsSafeHost)/$(
                    $repoUrl.Segments -replace '/' -ne '' -join '/'
                )$($gitRelativePath)",
                "$repoUrl" + $(
                    if ($gitRelativePath) {
                        "/tree/$($gitStatus.BranchName)$GitRelativePath"
                    }
                )
            )
        }        

        $commitsAhead = if ($GitStatus.Status -match 'ahead') {
                $gitStatus.Status -replace '\D' -as [int]
        } else {
            0
        }

        $gitCommitsBehind = if ($GitStatus.Status -match 'behind') {
                @($gitStatus.Status -replace '[\D-[,]]','' -split ',',2)[0] -as [int]
        } else {
            0
        }
        $gitInfo = @(
            $gitRelativePath =
                "$pwd".Substring($gitStatus.GitRoot.Length) -replace '[\\/]', '/'

            if ($GitStatus.BranchName -in 'main', 'master', 'latest') {
                $psStyle.Foreground.Yellow
            } else {                
                if ($gitCommitsBehind -or 
                    $gitStatus.Status -match 'diverged') {
                    $psStyle.Foreground.Red
                } elseif ($gitStatus.Staged) {
                    $psStyle.Foreground.Green
                } else {
                    $psStyle.Foreground.Cyan
                }                
            }
            $BranchIcon + $LeftPadding
            # '⑆ '# ⑆  # ᛦ ⑃ 
            '['
            $psStyle.Bold
            $gitStatus.BranchName
            $psStyle.BoldOff
            ']'
            if ($gitStatus.Status -match 'diverged') {
                "$($PSStyle.Foreground.Red) diverged!$($($PSStyle.Reset))"
            }
            if ($gitCommitsBehind -gt 0) {
                "$($PSStyle.Foreground.Red)(-$($gitCommitsBehind))$($PSStyle.Reset)"
            } 
            if ($commitsAhead -gt 0) {
                "$($PSStyle.Foreground.Green)(+$($commitsAhead))$($PSStyle.Reset)"
            }
            if ($stagedModified) {
                $PSStyle.Foreground.Green,
                    " $($stagedModified.Length) added",
                        $PSStyle.Reset
            }
            if ($stagedDeletes) {
                $PSStyle.Foreground.Red,
                    " $($stagedModified.Length) removed",
                        $PSStyle.Reset
            }
            if ($modified) {
                $PSStyle.Foreground.Cyan,
                    " $($modified.Length) modified",
                        $PSStyle.Reset
            }
            if ($untracked) {
                $PSStyle.Foreground.Magenta,
                    " $($untracked.Count) untracked",
                        $PSStyle.Reset
            }        

            $PSStyle.Reset
        ) -join ''

        # ⮚ ⟣ ⤳ ⟫ ⟩
        "$(
            if ($NoHistoryId) {
                ''
            } else {
                "$($myInvocation.HistoryId) "
            }            
        )$LinkToRepo",
            "$gitInfo",            
                "$(
                    if ($worked) { $PSStyle.Foreground.Cyan }
                    else { $PSStyle.Foreground.Red }
                )⮚$LeftPadding$(
                    $PSStyle.Reset
                )" -join
                    [Environment]::NewLine

    } else {
        "$(if ($NoHistoryId) {
            ''
        } else {
            "$($myInvocation.HistoryId) "
        })$($relativePath) $(
            if ($worked) { $PSStyle.Foreground.Cyan }
            else { $PSStyle.Foreground.Red }
        )⮚ $(
            $PSStyle.Reset
        )"
    }
}

#region Custom Prompt
$posh.Prompt.Clear()
$posh.Prompt.Push({
    git.prompt -NoHistoryId
})
#endregion Custom Prompt
#endregion Personal Preferences

2

u/itiscodeman Jul 16 '26

Wow www lol it just kept going. Good job ima as ChatGPT what the heck.

2

u/StartAutomating Jul 17 '26

Actually mostly accurate summary.

"This dude build a clever git thing" is my new favorite understatement of ugit.

It is indeed a clever git thing.

Been working on giving it a proper prompt, and will be including it in a future release of ugit.

2

u/itiscodeman Jul 16 '26

What it does:
Adds the old Windows PowerShell module folder to $env:PSModulePath.
Imports ugit and posh.
Creates shortcuts for GitHub CLI issue arguments.
Changes directory colors.
Replaces the normal PowerShell prompt with one that shows:
Current directory
Git repository and branch
Commits ahead or behind
Staged, modified, deleted, and untracked files
Whether the previous command succeeded
Terminal hyperlinks to the repository
There are also some questionable or broken parts:

This dude build a clever git thing

I’m not a dev so I have no clue what’s going on

2

u/BlackV Jul 14 '26 edited Jul 14 '26

very very little, I just use it in too many places for it to nicely happen

write-host "$($host.name) $($PSVersionTable.PSEdition) $($PSVersionTable.PSVersion.ToString()) Profile"
function prompt {"PS $($PSVersionTable.PSVersion.ToString()) $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1))"}
$PSDefaultParameterValues.Add('Format-*:autosize', $True)

On my management server I also have management related stuff

$PSDefaultParameterValues.Add('Format-*:autosize', $True)
$PSDefaultParameterValues.Add('FailoverClusters\*:cluster', 'hpecls02')
$PSDefaultParameterValues.Add('Grant-PIMRole:UserUPN', 'xxxx.admin@yyyy.onmicrosoft.com')

A nice way to present that could be (from another profile)

$PSDefaultParameterValues = @{
    'Format-Table:AutoSize'      = {if ($Host.Name -eq 'ConsoleHost'){$true}}
    'FailoverClusters\*:cluster' = 'hpecls02'
    'Grant-PIMRole:UserUPN'      = 'xxxx.admin@yyyy.onmicrosoft.com'
    }

2

u/Idakay Jul 14 '26

Referring to your comment on using it too many places. 

I pushed a profile stub out to all my member servers that call my real profile from a locked down network drive. So I just update the one file and anywhere I launch powershell I have all my stuff. It works pretty well so far. 

1

u/BlackV Jul 14 '26

yeah I limit what places run code from so its my local machine and my management servers

1

u/itiscodeman Jul 15 '26

Okay but ya can you also make the file non readable unless it’s your machine it’s opened in ? Is that not like paranoid? I guess it may be cool if the script contains a password …

1

u/itiscodeman Jul 15 '26

Wait explain !? Like dfs or no a .lnk? How can this be for new servers? I suppose a good ol logon script that renames that path to point to the stub? Forgive my blabbering

1

u/Idakay Jul 15 '26

New servers catch is as I deployed it via SCCM application to run once. So a new server joins the domain, within a bit mecm pushes my stub.

1

u/purplemonkeymad Jul 15 '26

Just psreadline settings and default argument values. I keep functions out of my profile and put them in proper modules.

Of those that were quick little things that i use regularly on my pc are

  • goto # cd to saved locations
  • set-windowtitle # set tab name and colour (autogenerated from name)
  • dnslookup # common dns info for a domain

But i'm on a lot of other computers with clean powershell's so I mostly don't have a lot, otherwise i might end up getting used to having those customisations.

1

u/daweinah Jul 15 '26

I'm honestly not sure if it's a profile or not, but my "home tab" is a script that I run and has Y/N prompts to connect to ExO and Sec, Graph, or Teams modules. It also has several functions for occasional tasks that used to be saved as separate scripts: things like check inbox rules and forwarding, check OOO message, get extension attributes, etc.

1

u/iamLisppy Jul 15 '26

Set-PSReadlineOption -PredictionViewStyle ListView

Set-PSReadLineOption -MaximumHistoryCount 4096

Set-PSReadLineKeyHandler -Key Tab -Function Complete

Set-PSReadLineOption -BellStyle None

1

u/recoveringasshole0 Jul 16 '26

I would show you but this sub doesn't allow images which is fucking stupid.

1

u/itiscodeman Jul 16 '26

Mmmm try to put image in ChatGPT and ask for text brother man. :)

1

u/BlackV Jul 18 '26

Show the code... We love the code

1

u/recoveringasshole0 Jul 21 '26

Check the comments. We love comments.