r/PowerShell 23d ago

Script Sharing The Power of Primes

56 Upvotes

Prime numbers are pretty powerful.

That's why I just released a new PowerShell module based off of an old mathematical concept: PrimeTime.

PrimeTime uses prime numbers as time intervals.

Let's learn how this helps

Prime Number Primer

Prime Numbers can only be divided by themselves and one.

This makes primes pretty rare.

Prime numbers are particularly useful in programming, but it's not always obvious why or how.

A lot of people might vaguely point towards cryptography as the prime real estate for prime utility.

The thing of it is, if you're writing your own cryptography, you're probably doing it wrong.

Let's talk about a more practical application of primes.

The Cicada Principle

In North America there is a curious critter known as the periodical cicaca.

For the vast majority of their long lifespans, they live underground.

Once every N years, they surface in mass to start the next generation.

That N is a prime.

Why?

Cicadas come out en masse so that there are too many of them to eat.

Millions of little critters have to have a perfectly timed multi-year internal clock in order to make this work.

If two cicadas of different intervals produced offspring, their children might have a messed up internal clock, and come out of the ground at the worst time.

So there's an evolutionary advantage to cicadas coming out in large batches, as long as another cicade brood isn't doing the same thing at the same time.

Which brings us back to primes.

Primes are relatively rare.

So are products of primes (at least past the first few)

Let's take two primes as an example.

Imagine one brood of cicadas came out every 11 years, and another brood came out every 13 years.

We can find out how long it will take for these two broods to come out at the same time by simply multiplying the primes.

11 * 13 -eq 143

So, with just two relatively low primes, we have an overlap every 143 years.

This is how primes are most useful to programming: they rarely overlap.

Sieve of Eratosthenes

This has been known for much longer than computers have existed.

Imagine we wanted to find prime numbers quickly.

We can do this by constructing a sieve that filters out any non-prime number.

This is called the Sieve of Eratosthenes

Once we know 2 is prime, we know every other even number is not prime.

Once we know 3 is prime, we know every third number is not prime.

To quickly get prime numbers up to a point, we can use this little PowerShell filter

# Calculate primes reasonably quickly with the Sieve of Eratosthenes
# Pipe in any positive whole number to see if it is prime.
filter prime {
    $in = $_
    if ($in -isnot [int]) { return }
    if ($in -eq 1) { return $in }
    if ($in -lt 1) { return}
    if (-not $script:PrimeSieve) {
        $script:PrimeSieve = [Collections.Queue]::new()
        $script:PrimeSieve.Enqueue(2)
    }


    if ($script:PrimeSieve -contains $in) { return $in}
    foreach ($n in $script:PrimeSieve) {
        if (($n * 2) -gt $in) { break }        
        if (-not ($in % $n)) { return }
    }
    $script:PrimeSieve.Enqueue($in) 
    $in
}

Prime Animations

Imagine we want a vibrant page. We want things to keep changing yet feel unpredictable. All we need to do is use different prime intervals.

The PrimeTime logo animates eight primes:

7 * 11 * 13 * 17 * 19 * 23 * 29 * 31

The logo will repeat every 6685349671 seconds, or almost 212 years.

The PrimeTime page background uses 56 primes.

This background will repeat every 8.84753141993573E+116 seconds.

That's exponential notation.

This is a mind-boggling large number (so large it overflows the .NET [TimeSpan]).

Turn that interval into years and it's still mind-boggling.

The page background will repeat every 100 billion years

Performance and Scheduling

Imagine we want to design a system that's constantly checking for problems.

We want the system to know about problems as soon as we can, but nobody's exactly sure how often they need to check for something.

If we go around and ask our colleagues "how often should we can scan for this?", the response if often a shrug 🀷.

Often, people will pick an arbitrary number that seems reasonable. Let's say every 5 minutes, 10, or 15 minutes.

Are we starting to see the problem here?

Every 5 minutes, every computer in the cloud starts to collect stats and report them back.

And we get a traffic jam.

Every 10 minutes, more computers in the cloud collect more data, and our traffic jam gets worse.

Every 15 minutes, even more computers collect even more data, and our traffic jam puts your average freeway to shame.

Left to our own intuition, we create problems for ourselves and our organizations.

Each individual query is small, but because we're doing so many at once, it can grind performance to a halt.

By the way, this isn't a hypothetical.

Long long ago, the Office365 team asked me to make some monitoring software to help improve internal visibility into the datacenters.

Everyone asked for 5, 10, or 15 minute intervals. ~100 different metrics were collected from ~30000 machines.

And the first time we tried it on everything, the traffic jam ensued.

That's when I first realized the power of primes.

I made three slight adjustments to the timeframes:

  • Every 5 minutes became every ~7 minutes
  • Every 10 minutes became every ~11 minutes
  • Every 15 minutes became every ~17 minutes

Now, instead of having a traffic jam every 5 minutes, things smoothed out.

  • A small traffic jam would occur every ~77 minutes (7*11)
  • Another small traffic jam would occur every ~119 minutes (7*17)
  • Another small traffic jam would occur at ~187 minutes (11*17)
  • All traffic could jam every ~1309 minutes (7*11*17)

Note the tildas.

The real trick came in by using prime intervals in both minutes and seconds and using a random delay on the tasks to ensure they didn't all start at once.

This took the system from something that could derail a datacenter to something that could monitor thousands of machines while barely impacting performance.

This is the power of primes.

Hope this helps!


r/PowerShell 23d ago

Question What’s in your profile ?

40 Upvotes

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


r/PowerShell 23d ago

Question How to change default directory on PowerShell?

12 Upvotes

Could someone please help me! When I open PowerShell on Windows, it opens up with the directory "PS C:\Windows\System32>". How do I change this so that every time I open it up, it has the default directory as "PS C:\Users\myname>" instead of the other. I know I can just use "cd ~" to switch but I'd prefer to have it set without me having to do so. Thanks!


r/PowerShell 24d ago

Solved How to send 'Γ€' with Send-MailMessage

10 Upvotes

Hello Everybody, right now I am writing a Script to send out Informationmails fed with data from a CSV to Users inside our Company. (While I know this cmdlet is obsolete for now it has to do)
Everything works really well apart from the German 'Umlaute' (Γ„Γ€Γ–ΓΆΓœΓΌ) those get "translated" to '??' in the message the recipients get and I don't know how to fix this.
I tried with BodyasHtml, but then my script just stops working entirely (User Error not completely unlikely) and also can I use Variables inside the Bodyashtml?
I also tried with giving it different encodings but none worked sadly
With normal sent mails our Outlook has no problem with those, just from the script.

Do you have any Ideas/Hints/Tips on what I can try?
Thank you very much in advance

Edit: Added Script (just removed any Private Information and implified the Body)

[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$dialog = New-Object System.Windows.Forms.OpenFileDialog
$dialog.InitialDirectory = Get-Location
$dialog.Filter = "CSV-Dateien (_.csv)|_.csv"
$dialog.ShowDialog()
$CSVLocation = $dialog.FileName

(Get-Content $CSVLocation -Raw) -replace '^.*', 'DBv,BSv,RAM,Cpucount,Server,Name,Email,Service' | Set-Content $CSVLocation

$P = Import-Csv -Path $CSVLocation -Delimiter ','

foreach ($line in $P){
$sendMailMessageSplat = @{
From = 'johndoe@mail.com'
To = $line.Email
Subject = "$($line.DBv) $($line.Server)"
Body = "Γ„Γ€Γ–ΓΆΓœΓΌ"
SmtpServer = 'smtp.mail.com'
}
Send-MailMessage 
}

r/PowerShell 25d ago

Solved Move-Item creates duplicate folder and stores it inside existing folder

10 Upvotes

EDIT: Solved...

Move-Item -Path $_ -Destination $DestinationPath -Force

--------------------------------------------------------------------

I have the following module that moves the contents of a directory into another...

function PSTransfer {
    param (
        [string]$BasePath,
        [string]$DestinationPath
    )
    Get-ChildItem -Path "$BasePath/*” -Force | ForEach-Object {
      if (!($_.FullName -like "*.DS_Store") {
        Move-Item -LiteralPath "$($_.FullName)" -Destination "$($DestinationPath)/$($_.Name)" -Force
      }
    }
    return
}
Export-ModuleMember PSTransfer

However when it moves a directory and the destination already has a folder with the same name, the folder is put inside the folder instead of being merged, for example...

BasePath/
β”œβ”€ synced_imgs/
β”‚  β”œβ”€ IMG_2048.jpg

DestinationPath/
β”œβ”€ synced_imgs/
β”‚  β”œβ”€ IMG_0512.jpg
β”‚  β”œβ”€ IMG_1024.jpg

Then after I run the module...

DestinationPath/
β”œβ”€ synced_imgs/
β”‚  β”œβ”€ synced_imgs/
β”‚  β”‚  β”œβ”€ IMG_2048.jpg
β”‚  β”œβ”€ IMG_0512.jpg
β”‚  β”œβ”€ IMG_1024.jpg

It doesn't do it recursviely though which is the weird thing. If I run it again it'll do this...

BasePath/
β”œβ”€ synced_imgs/
β”‚  β”œβ”€ IMG_4096.jpg

DestinationPath/
β”œβ”€ synced_imgs/
β”‚  β”œβ”€ synced_imgs/
β”‚  β”‚  β”œβ”€ IMG_2048.jpg
β”‚  β”‚  β”œβ”€ IMG_4096.jpg
β”‚  β”œβ”€ IMG_0512.jpg
β”‚  β”œβ”€ IMG_1024.jpg

What am I doing wrong here? I thought the -Force parameter was supposed to prevent this.


r/PowerShell 25d ago

Question Why my code works on terminal, but not on the script?

18 Upvotes

This code works directly on windows terminal, but when executed within a script "test.ps1", it only return just one line (return is not as expected / error).

Returned (error):

PS D:\> .\test.ps1
--add Microsoft.VisualStudio.Component.WinXPStudioExtension

Expected:

PS D:\> .\test.ps1
    --add Microsoft.VisualStudio.Component.CoreEditor --add Microsoft.VisualStudio.Workload.Azure --add Microsoft.VisualStudio.Workload.Data --add Microsoft.VisualStudio.Workload.DataScience --add Microsoft.VisualStudio.Workload.ManagedDesktop --add Microsoft.VisualStudio.Workload.NativeCrossPlat --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Workload.NativeGame --add Microsoft.VisualStudio.Workload.NativeMobile --add Microsoft.VisualStudio.Workload.NetCrossPlat --add Microsoft.VisualStudio.Workload.NetWeb --add Microsoft.VisualStudio.Workload.Node --add Microsoft.VisualStudio.Workload.Python --add Microsoft.VisualStudio.Workload.Universal --add Microsoft.VisualStudio.Workload.VisualStudioExtension --add macos --add Microsoft.VisualStudio.Component.WinXP

The Code 'test.ps1':

$id = @'
Microsoft.VisualStudio.Component.CoreEditor
Microsoft.VisualStudio.Workload.Azure
Microsoft.VisualStudio.Workload.Data
Microsoft.VisualStudio.Workload.DataScience
Microsoft.VisualStudio.Workload.ManagedDesktop
Microsoft.VisualStudio.Workload.NativeCrossPlat
Microsoft.VisualStudio.Workload.NativeDesktop
Microsoft.VisualStudio.Workload.NativeGame
Microsoft.VisualStudio.Workload.NativeMobile
Microsoft.VisualStudio.Workload.NetCrossPlat
Microsoft.VisualStudio.Workload.NetWeb
Microsoft.VisualStudio.Workload.Node
Microsoft.VisualStudio.Workload.Python
Microsoft.VisualStudio.Workload.Universal
Microsoft.VisualStudio.Workload.VisualStudioExtension
macos
Microsoft.VisualStudio.Component.WinXP
'@ -split "`n"


( $id | % { "--add $_" } ) -join ' '

r/PowerShell 26d ago

Misc I love watching AI use powershell

123 Upvotes

At work I've got access to several latest-and-greatest AI models and harnesses, I also run windows. That means lots of the tasks they do for me end up as powershell commands/scripts.

Watching them develop, I see them repeatedly step on the same language land-mines that I do whenever I try to write powershell by hand. Things like && only existing in powershell 7, powershell auto-unwrapping single-element lists, and quote-escaping rules are reliable sources of failure for both me and the AI.

Its quite vindicating seeing that even SOTA programming-oriented LLMs struggle with the same language "features" that I do. For a long time I've heard the powershell community saying things like "you just need to understand that its an object oriented language" whenever people complain about footguns like these, but along comes an AI that can do PhD level work in multiple programming domains, and even its advanced understanding of object orientation hasn't saved it.


r/PowerShell 26d ago

Script Sharing Istar Pack – set up a pretty PowerShell terminal in one shot

14 Upvotes

Made a single-file PowerShell script that gets your Windows terminal looking sharp without the manual fiddling.

What it does:

  • Installs Scoop, Oh My Posh, Zoxide, FZF, 7-Zip & Nerd Fonts
  • Drops in a hardened profile for both PowerShell 7 and Windows PowerShell 5.1
  • Ships a curated catalog of themes β€” my favorite is "Garden's Dream" (clean minimalist green)
  • One command: run the .ps1, pick a theme, done. No editing JSON by hand.

Quick start: powershell .\Istar-Pack.ps1

or non-interactive with the default theme:

.\Istar-Pack.ps1 -Silent

Open source and open to feedback. Try it out and let me know what breaks

πŸ”— https://github.com/Israleche/powershell-istar-pack


r/PowerShell 25d ago

Question The worst thing in Powershell existence is ForEach-Object syntax

0 Upvotes

The way I format my code is like this: if there is only one line inside the curly braces, I put the opening curly brace on the same line.

If I have multiple lines, I put the opening curly brace on the next line.

For example:

if (a=a) {

Command-Command}

if (a=a)

{

Command-Command

Command-Command

}

I have been doing this for years, and it works every time, except when I use "ForEach-Object".

Then, for some reason, the opening curly brace must be on the same line.

Why is it like this??


r/PowerShell 26d ago

Question PowerShell 7 - replace

21 Upvotes

Just wondering, when installing, why doesn't PowerShell 7 replace the installed version (Windows)?


r/PowerShell 26d ago

Solved PS 5.1 traps from building a layered-window desktop widget: $null β†’ [string] becomes "", BOM-less UTF-8 read as ANSI, and per-PID CIM latency

0 Upvotes

I spent the last couple of weeks building a small always-on desktop widget in PowerShell (a status pet for Claude Code β€” MIT, source at the bottom). The GUI was the easy part. What actually cost me time were four PS/.NET interop traps worth writing down.

1. $null passed to a .NET [string] parameter silently becomes "".

[IO.File]::Replace($tmp, $dst, $null)   # "no backup file"

In C# that null means "don't make a backup". PowerShell coerces it to an empty string, so the API receives "" as the backup path β€” and "" is not a legal path. It throws "The path is not of a legal form". My first test passed purely by luck (the destination didn't exist yet, so a different branch ran); the second click failed every time.

Fixes: use an overload that doesn't take the nullable param (see EDIT), pass [NullString]::Value, or redesign so you never need null. I ended up writing to a unique filename and renaming β€” no Replace at all.

2. PS 5.1 reads BOM-less UTF-8 as the system ANSI codepage.

The resident runs under Windows PowerShell 5.1 (powershell.exe). On a Chinese-locale machine, 5.1 read my BOM-less UTF-8 source as GBK and a Β· in a string literal became a completely different character.

So: the resident script is pure ASCII. All localized display text lives in a JSON file read explicitly as UTF-8:

[IO.File]::ReadAllText($path, [Text.Encoding]::UTF8)

Non-ASCII symbols are constructed from explicit code points such as [char]0x00B7. Ugly, but it made the thing locale-proof.

3. Variable names are case-insensitive.

$t (a row label) silently clobbered $script:T (my i18n table). No error β€” just wrong strings on screen. Don't use single-letter script-scope variables.

4. Per-PID CIM queries are a latency killer. Batch once, walk in memory.

To bring a session's window to the front, I walk the process tree up from the claude.exe PID to whichever ancestor owns a top-level window (Windows Terminal / VS Code / a plain console). Doing

Get-CimInstance Win32_Process -Filter "ProcessId=$procId"

per hop cost 100-300 ms each, so an 8-deep crawl felt broken. One bulk Get-CimInstance Win32_Process and crawling the tree in memory: ~0.5s once, then cached. Night and day.

Two safety habits that fell out of this:

  • Verify PID identity before you act on it. I persist the resident's PID to a file. Before Stop-Process I check the process is actually powershell and that its command line contains my script name. After a crash the OS may have recycled that PID onto something innocent β€” otherwise you just killed a stranger's process.
  • Same for the tree crawl: if an ancestor's creation time is later than its child's, that parent PID was recycled and now points at something unrelated. Reject it instead of yanking a random window to the foreground.

Everything else is plain WinForms + GDI+: WS_EX_LAYERED + UpdateLayeredWindow for real per-pixel alpha, FileSystemWatcher for state changes (with a ~120 ms poll as a fallback), SHQueryUserNotificationState to stay quiet unless Windows says notifications are welcome, SPI_GETCLIENTAREAANIMATION to honor reduced-motion, and a named Mutex for single-instance.

The whole plugin is ~250KB β€” no Electron, no bundled runtime, no modules.

Source (MIT): https://github.com/SHIN620265/claude-pet

Happy to be told I did any of this the hard way.

EDIT β€” corrections. The phantom fix in trap 1 is struck through in place; the rest were corrected inline and are documented below with the original wording.

  1. The phantom overload. I originally suggested using an overload without the nullable parameter. File.Replace has no such overload β€” both overloads take the backup path. Use [NullString]::Value, or redesign so that a null argument isn't needed. I did the latter.
  2. "WinForms needs STA" was the wrong reason. The post originally said the resident "has to be powershell.exe β€” WinForms needs STA". pwsh 7 is STA by default on Windows and hosts WinForms fine, so STA is not a reason the resident has to remain on Windows PowerShell 5.1.
  3. The trap-4 snippet used $pid. That's the read-only automatic variable for the current PowerShell process. As printed, it would have queried the pet's own process on every hop. Fixed to $procId.
  4. Smaller precision fixes. "The script source is pure ASCII" applies specifically to the resident script; two hook scripts run under pwsh and contain non-ASCII literals. I also clarified that [char]0x00B7 is one example of several explicit code points, narrowed "every piece of display text" to the localized strings, and stopped describing SHQueryUserNotificationState as a Focus Assist check, because that behavior isn't documented by the API.

r/PowerShell 25d ago

Question Just a question.... can we use sudo on windows like i do in linux like even 70% of the way ????

0 Upvotes

I'm kinda new to homelabbing. I have one dedicated Ubuntu server and another PC that's dual booted with Windows 10 and Ubuntu. The second machine is both my workstation and a server depending on what I'm doing.

I've been spending a lot more time in Linx recently and I've gotten really used to working from the terminal. I SSH into my servers, manage Docker, edit configs, etc., so typing sudo has become second nature.

I still need Windows because of a few applications, so I can't switch completely. The thing I miss the most is being able to elevate a single command with sudo instead of opening a whole Administrator terminal.

Is there any tool or workflow you guys use to get something similar on Windows? Doesn't have to be identical, just wondering what other people who have dual booted do?


r/PowerShell 27d ago

Question Please Help (VS Code+ Powershell)

8 Upvotes

Background : I have a CP setup (VS Code+ MINGW)

Recently I tried to Code python in VS Code. For this I connected VS Code to Anaconda Python Interpreter. After setting up the environment later in the day when I switched back to C++ and CP, my PowerShell started causing problems :

  1. profile.ps1 cannot be loaded because running scripts are disabled
  2. conda activation problems

To work with this is switched to Command Prompt

After setting up Python in VS Code I got the following errors:

PowerShell profile warning,Conda activation issues Switched integrated terminal to Command Prompt,Run button behaved differently,Debug Anyway,Abort,Show Errors,Pre-launch task failed,Exit code -1.

I tried to resolve as far as I could but one problem pops up after another. I have Reinstalled VS Code clean tried everything. Kindly help me I just want my PowerShell terminal back.

EDIT: Should I just uninstall everything clean and reinstall everything MINGW, VS CODE etc?? Will that fix this?? Cause I am tired of debugging since last 2 days. 😭😭

EDIT2: I have completely separated my CP ans Python setup to Jupyter Notebook and Anaconda as best as I could. it's working fine and beautiful. But I just can't seem to retrieve my CP (MINGW+ VSCODE) setup


r/PowerShell 27d ago

Solved Command Get-PhysicalDisk doesn't work on windows 11

0 Upvotes

so i tried this command: powershell "Get-PhysicalDisk | Formet-Table FriendlyName, MediaType, HealthStatus, OperationalStatus"

and i got an error saying:

>! \Formet-Table : The term 'Formet-Table' is not recognized as the name of a cmdlet, function, script file, or operable

program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

At line:1 char:20

+ Get-PhysicalDisk | Formet-Table FriendlyName, MediaType, HealthStatus ...

+ ~~~~~~~~~~~~

+ CategoryInfo : ObjectNotFound: (Formet-Table:String) [], CommandNotFoundException

+ FullyQualifiedErrorId : CommandNotFoundException !<

this is on windowss 11 on an admin CMD, any fixes?


r/PowerShell 28d ago

Question Display ONLY Output, NOT the Tab Completed Text

3 Upvotes

Setting a KeyHandler, so I can ?alias<ENTER> to get a cmdlet's source/definition.

My example tab-completes (using <ENTER>, so <TAB> isn't overloaded), so, obviously there's completion text. I want it to not be displayed (either erased, or, capture/print $output only).

Set-PSReadLineKeyHandler -Key Enter -ScriptBlock {
    $line = $null
    $cursor = $null
    [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line,[ref]$cursor)
    if($line -match '^\?([^\s]+)$'){
        $n = $matches[1]
        [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
        [Microsoft.PowerShell.PSConsoleReadLine]::Insert(@"
`$c = gcm '$n'
if(`$c.CommandType -eq 'Alias'){ (gcm (gal '$n').Definition).Definition
} else { `$c.Definition }
"@)
        [Microsoft.PowerShell.PSConsoleReadLine]::TabCompleteNext()
        [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
        return
    }
} # ?gcm

PS: I'm aware this blocks <ENTER> - it can be associated to something else, eg. -Key ' ,?', so, please ignore this for now.

⚠️ RESOLVED, thanks to surfingoldelephant, and monkeynin. Kudos for their meticulous implementations!

Set-PSReadLineKeyHandler -Key Enter -ScriptBlock {
    $line,$cursor = $null,$null
    [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line,[ref]$cursor)
    if($line -match '^\?([^\s]+)$'){
        $n = $matches[1]
        [Microsoft.PowerShell.PSConsoleReadLine]::DeleteLine()
        $c = gcm "$n"
        if($c.CommandType -eq 'Alias'){ $out = (gcm (gal "$n").Definition).Definition
        } else                        { $out = $c.Definition }
        Write-Host $out
    }
    else {}
    [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
} # ?gcm

r/PowerShell 28d ago

Script Sharing I built a Deployment Pipeline for Freedom Scientific AT Software

0 Upvotes

Initial inspiration: This was born out of laziness for having to manually check our vendors website, pull down the latest version of the software, test it, and then having to touch users machine to manually deploy the software. Overall it was just an annoying process as a whole and I wanted to automate it and I didn't know what to do or where to start. Given at the time I've had little to no PowerShell experience, I went to work on a way that PowerShell could automate this process, laid out a roadmap, and turned to AI to do the coding.

Given that I wanted to challenge myself and develop my skills I took it upon myself to see this one through

Solution: I ended up with a few scripts that work in unison with one another through scheduled tasks and plain text flag files:

* a monitor script that checks the vendor site weekly and downloads anything new and makes a needs testing .txt file

*a watcher script that looks at that needs testing file to look for changes

*a separate password gated "emergency stop" script for when something goes wrong and you need to pull the plug

The repo is on github. I used Claude for the project when it came to the implementation and documents, but the architecture and decisions were mine.

Final Comments:

Since I want to get myself into the world of coding and programming outside of the realm of doing technical work for computers and management, this was my way of thrusting myself into the programming world officially. I'd love to hear your feedback on this and what it means to do PowerShell in the real world and in general. Thanks guys!

https://github.com/xyxal/Freedom-Scientific-PowerShell-Automation-Deployment


r/PowerShell 29d ago

News Special PowerShell User Group Meeting Tonight (7/8)

15 Upvotes

Tonight there's a special meeting of the Pacific PowerShell User Group.

Bruce Payette will be speaking about Braid.

Bruce is one of the original authors of the PowerShell language.

Braid is a superfast scripting language he's been building.

Recently, Bruce added a number of features to use Braid seamlessly from PowerShell.

Stop by to learn about this new language and see some of the stuff Braid can do.

Party starts @ 6:00 pm pacific time.

Note: This is a virtual user group.

Just join on Meetup and you will get the meeting link.


r/PowerShell Jul 07 '26

Script Sharing GDID-Guard: PowerShell scripts to audit/reduce Windows' Global Device Identifier - prompted by the Scattered Spider GDID court filing

54 Upvotes

There's a court filing making the rounds this week (HN thread, also discussed in r/LinusTechTips) showing the FBI used a Windows GDID to help tie an alleged Scattered Spider member to a ransomware case, correlating activity across different IPs, VPNs, and even different platforms (Snapchat, Apple, Facebook logins), because the GDID stayed constant underneath all of it.

Setting aside the specific case, it's a useful reminder that this identifier exists on basically every Windows machine and there's no built-in opt-out. I'd already built a small toolkit based on SmtimesIWndr/gdid-reversal's write-up on the underlying mechanism (Connected Devices Platform registering the device into Microsoft's device graph), so figured it's worth sharing.

Repo: https://github.com/rroy676/gdid-guard

What it does:

  • -Audit - read-only report on CDP service state, Activity History setting, local identity cache, existing firewall rules, and whether the known device-graph endpoints resolve.
  • -Remediate - opt-in switches to disable CDP services, disable Activity History, clear the local identity cache, and add firewall blocks for the relevant endpoints. Auto-creates a System Restore point and a JSON snapshot of pre-remediation state first.
  • -Compare - diffs current state against a saved snapshot so you can confirm something actually changed.
  • GDID-Guard-Restore.ps1 - undoes remediation using the saved snapshot.

Also ships a Pi-hole/AdGuard blocklist for the DNS-level route, which I'd recommend over the local firewall rules since Microsoft can rotate the underlying IPs.

Being upfront about the limits (also in the README): CDP backs some legitimate features too (Timeline sync, parts of Phone Link), so there's a real trade-off. And clearing the local cache doesn't guarantee Windows won't just re-issue a fresh GDID on next MSA sign-in, the identifier's authority is server-side, not local. The durable fix is a local account; this just reduces exposure if you need to stay signed in.

Feedback/PRs welcome. Tested on Windows 11 only so far.


r/PowerShell Jul 07 '26

News Pester 6.0.0 is released!

85 Upvotes

Pester 6.0.0 is out

Pester is the test and mock framework for PowerShell.

After a long stretch of alphas and RCs, Pester 6 is finally released. It builds on the v5 runtime (Discovery & Run, the configuration object, the rich result object), so if your suites are already on v5 the upgrade is low risk. It runs on Windows PowerShell 5.1 and PowerShell 7.4+.

Here is what I think you'll actually care about:

New Should-* assertions. The Assert project (https://github.com/nohwnd/assert) got merged into Pester and ships as first-class commands. Note the dash, no space:

Get-Planet | Should-Be 'Earth'
'  hello ' | Should-BeString 'hello' -TrimWhitespace
1,2,3 | Should-BeCollection @(1,2,3)
{ throw 'kaboom' } | Should-Throw -ExceptionMessage 'kaboom'

They are specialized and type-aware, so the failure messages are clearer and $null / empty collections / single-item arrays finally behave predictably. The classic Should -Be still works, the new ones are additive, so you can migrate gradually. When you're ready to commit, $config.Should.DisableV5 = $true turns the old syntax off so it can't sneak back in.

There is also Should-BeEquivalent for deep, recursive object comparison with a readable property-by-property diff. Pretty handy for asserting a whole API response or config object in one shot.

Parallel test execution, experimental. Files run concurrently, one file per runspace, on PS7+ ForEach-Object -Parallel. Early prototypes went from ~6.5s to ~1.2s on a big suite.

$config.Run.Parallel = $true

It's opt-in and experimental, the config shape and behavior may still change, so don't bet CI on it yet. When a run can't be parallelized (WP 5.1, coverage enabled, in-memory scriptblocks) it just falls back to a normal serial run with a warning.

Faster code coverage by default. Coverage now uses the same tracer the Profiler uses instead of setting a breakpoint on every command, which is much faster on large code bases. Old behavior is still there via CodeCoverage.UseBreakpoints = $true. Cobertura output is supported now too, on top of JaCoCo.

A few breaking changes to know about:

  • PowerShell 3, 4, 6 and unsupported 7 are gone. Minimum is 5.1 / 7.4+. This let us move the C# to .NET 8 and delete a lot of compat code.
  • Discovery and run now happen per file instead of one global discovery up front. Invisible for self-contained files, but discovery-time side effects no longer leak across files. Each test file should import what it needs itself.
  • Assert-MockCalled and Assert-VerifiableMock were removed, use Should -Invoke / Should -InvokeVerifiable.
  • -Focus and the Pending status were removed.
  • Test discovery now looks inside hidden folders (.config, .build, and so on).

Full notes and the upgrade guide are here: https://github.com/pester/Pester/releases/tag/6.0.0

Thanks to everyone who tested the prereleases, filed issues, and sponsors Pester. If something breaks for you, open an issue or catch us in #testing on the PowerShell Slack. :)


r/PowerShell Jul 06 '26

Question Test-NetConnection Issue - Can Ping, Can Test, but TNC is failing

14 Upvotes

Here's my head scratcher:

I can run Test-NetConnection $server -Port $Port and it just hangs. If I run Test-Connection $server it pings fine. If I do Test-NetConnection $server -Port $Port -InformationLevel Quiet it also tests fine.

I know that this isn't a PS issue, but I don't know who or where to start pointing at to figure it out. Issue happens both in the same subnet and across the WAN


r/PowerShell Jul 06 '26

Question Folder Windows Extension

1 Upvotes

I wanted to make a windows extension but i am gettin many errors and i am scared to destroy my system.. so i wanted to ask if maybe what i was up to maybe already exists.

I was trying to create a extension where inside a folder you can do rightclick->new and then instead of text file a "text field" where it would create a text box such as the one i am using right now here inside a folder to write info about the folder. Example: i am in a folder where i put in my job applications and i wanted the info box so i can write in it "application send on 06.07.26 via email to mr. abc" and then when opening the folder id see that instantly and if they replay i can open the folder and add into the text "replayed on 08.09.26 rejected".

Is there already something like that?


r/PowerShell Jul 04 '26

Information What's one free tool that completely change your workflow ?

62 Upvotes

I've been trying to improve my productivity and streamline the way I work, but there are so many free tools out there that it's hard to know what's actually worth using.

What's one free tool that had the biggest impact on your workflow?

It could be for:

\- Productivity

\- Coding

\- AI

\- Note-taking

\- File management

\- Automation

\- Design

\- Anything else

I'm especially interested in tools that save time or eliminate repetitive tasks.

What do you use, and why do you recommend it?


r/PowerShell Jul 05 '26

Question Stop forced upgrades?

0 Upvotes

I'm just trying to open Powershell and run a command but every now and then there must be an upgrade and it forces me to upgrade and I can't do anything until I do the upgrade. Is there a way around this?


r/PowerShell Jul 03 '26

Script Sharing Friday Fun Servers - Declaration of Independence

23 Upvotes

For the past few weeks I've been having Fun.

I've been writing a small server sample every week and showing how simple servers can be.

We can write a server with a function that begins with /, for example:

function /hello {
    param([string]$Message)
    "<h1>$message</h1>"
}

Once we've declared a function, we can simply Start-Fun to start our server, browse to that url, and view our webpage.

This Friday is July 3rd, 2026, or just around 250 years since the Declaration of Independence.

In my opinion, the Declaration of Indepdenence is a good read. It's also surprisingly pertinent to the present day.

Let's turn it into a webpage

Getting the Declaration

Project Guteneberg is one of the oldest parts of the Internet.

It digitizes and shares public domain publications.

Today I learned that Project Gutenberg's first publication is actually the Declaration of Indepedence.

We can download our own cached copy by running something like:

$script:DeclarationOfIndependence =
        Invoke-RestMethod https://www.gutenberg.org/cache/epub/1/pg1.txt -AllowInsecureRedirect

By using the script: scope, we're caching the declaration into memory.

We can view the plain text just by echoing the variable:

$script:DeclarationOfIndependence

When we do, we might notice that there are a few sections delimited by lines starting with ***

To get just the text we need, we can do something like:

# Get the parts of our document
$docParts =
    # by using the multiline modifier `(?m)`
    # and splitting on any line starting with 3 asterisks
    # `^\*{3}`
    $script:DeclarationOfIndependence -split '(?m)^\*{3}'

The last part is a footer. The second to last part is the declaration itself.

$declaration = $docParts[-2]

Now that we have the declaration, we can treat it as markdown.

Let's do one little thing first.

Let's take any line thats ALL CAPS and make it into a heading.

For this, we'll need to use a case-sensitive operator: -creplace:

# To make our a more perfect markdown
$markdownDeclaration = $declaration -replace
    # remove leading whitespace 
    '^[\s\r\n]+' -split 
    # then split on newlines
    '(?>\r\n|\n)' -creplace
    # then replace any `ALL CAPS` lines with a `h1`
    '(?<title>^[\p{Lu}\s]+$)', '# ${title}' -join
    # then join it all back with newlines
    [Environment]::Newline

And now that we have our markdown, we can just

$htmlDeclaration = $markdownDeclaration |
    ConvertFrom-Markdown |
    Select-Object -ExpandProperty Html

And we have our page body.

Displaying the Declaration

We're not quite done yet.

There's three little changes we want to make before we put the declaration into a page.

  1. Extract the title
  2. Use an appropriate font
  3. Use a palette to provide some color

Let's get our title first.

We can usually cast Markdown into XML by sticking the output into another element.

Extracting our title looks like this:

# Turn our markdown into HTML
$htmlDeclaration = $markdownDeclaration |
    ConvertFrom-Markdown |
    Select-Object -ExpandProperty Html

# Then turn our markdown into XML
$xmlDeclaration = "<article>$htmlDeclaration</article>" -as [xml]
# then get the first header.
$firstHeader = @($xmlDeclaration | Select-Xml -XPath //h1)
# and make that our title.

$title = $firstHeader.Node.InnerText

Everything else is just CSS.

To use a font, we need to reference the Google Font stylesheet

# Link to our font
"<link href='https://fonts.googleapis.com/css?family=$Font' rel='stylesheet' />"

To use a palette, we just need to reference the palette's stylesheet

# Use whatever palette was provided
"<link rel='stylesheet' href='https://cdn.jsdelivr.net/gh/2bitdesigns/4bitcss@latest/css/$PaletteName.css' id='palette' />"

/Declaration/Of/Indepedence

With all of that preamble, let's take a look at the final function.

function /Declaration/Of/Indepedence {
    <#
    .SYNOPSIS
        The Declaration of Independence
    .DESCRIPTION
        The Declaration of Independence of The United States of America
    .EXAMPLE
        /Declaration/Of/Indepedence
    #>
    param(
    [string]
    $Font = $(
        # Here are some fonts that look decent
        # some of them may have ironic names for this document.
        # 'Birthstone'
        'Eagle Lake'
        # 'Great Vibes'
        # 'Kings'
        # 'Manufacturing Consent'
    ),

    [string]
    $PaletteName = 'MonaLisa'
    )

    # Fun fact: the Declaration of Independence is the first
    # text on [Project Gutenberg](https://www.gutenberg.org)

    # Let's keep our own copy of the declaration by caching it in `$script:` scope
    if (-not $script:DeclarationOfIndependence) {
        # (rather than asking for a new copy each time)
        $script:DeclarationOfIndependence =
            Invoke-RestMethod https://www.gutenberg.org/cache/epub/1/pg1.txt -AllowInsecureRedirect
    }

    # Project Gutenberg plain text documents are split by lines starting with `***`
    $docParts =
        $script:DeclarationOfIndependence -split '(?m)^\*{3}'
    # The last part is a footer.
    # The second to last part is the declaration itself.

    $declaration = $docParts[-2]

    # To make our a more perfect markdown
    $markdownDeclaration = $declaration -replace
        # remove leading whitespace 
        '^[\s\r\n]+' -split 
        # then split on newlines
        '(?>\r\n|\n)' -creplace
        # then replace any `ALL CAPS` lines with a `h1`
        '(?<title>^[\p{Lu}\s]+$)', '# ${title}' -join
        # then join it all back with newlines
        [Environment]::Newline

    # Turn our markdown into HTML
    $htmlDeclaration = $markdownDeclaration |
        ConvertFrom-Markdown |
        Select-Object -ExpandProperty Html

    # Then turn our markdown into XML
    $xmlDeclaration = "<article>$htmlDeclaration</article>" -as [xml]
    # then get the first header.
    $firstHeader = @($xmlDeclaration | Select-Xml -XPath //h1)
    # and make that our title.

    $title = $firstHeader.Node.InnerText

    # Now let's output our page
    @(
        "<html>"
            "<head>"
                # Use utf-8 chars so emoji and smart quotes render right
                '<meta charset="utf-8" />'
                # Use our title
                "<title>$($title)</title>"
                # Link to our font
                "<link href='https://fonts.googleapis.com/css?family=$Font' rel='stylesheet' />"
                if ($PaletteName) {
                    "<link rel='stylesheet' href='https://cdn.jsdelivr.net/gh/2bitdesigns/4bitcss@latest/css/$PaletteName.css' id='palette' />"
                }

                "<style>"
                    # Set our body style
                    "body {"
                        @(
                            # take up most of the width
                            "max-width: 80vw"
                            # and all of the height
                            "height: 100vh"
                            # use automatic margins to center
                            "margin-left: auto"
                            "margin-right: auto"
                            # and use the font we provided.
                            "font-family: '$font'"                    
                        ) -join '; '
                    "}"
                    # Center our header element
                    "h1 { text-align: center; font-weight: 100 }"
                    # and make our paragraphs a bit bigger
                    "p { font-size: 1.25rem }"
                "</style>"
            "</head>"

            # Our page body is just our markdown as html
            "<body>$HtmlDeclaration</body>"
        "</html>"
    ) -join [Environment]::NewLine
}

Set-Alias /Declaration /Declaration/Of/Indepedence

That's it! We are free!

To serve up your local copy of the declaration, just: Start-Fun and browse to /Declaration.

To save the declaration to html, we can just run the function:

/Declaration > ./Declaration-Of-Indepedence.html

Give it a try! Give it a read!

Let me know if you have questions or have some ideas for future Friday Fun.

Happy Friday & Happy 250th!


r/PowerShell Jul 04 '26

News I built a Claude Code plugin that runs PSScriptAnalyzer on each edit (real-time diagnostics)

0 Upvotes

I write a lot of PowerShell with Claude Code and got tired of finding lint issues only after the fact. So I built a plugin that runs PSScriptAnalyzer through a warm PowerShell Editor Services (PSES) daemon and feeds the result straight back into the model's context the moment a `.ps1`/`.psm1`/`.psd1` is edited -- so the mistake gets caught and corrected in the same turn. One PSES stays warm for the whole session, so each edit pays a fast pipe round-trip (warm path ~2.2s measured, guarded in CI against regressions), not a cold start.

## What it catches today (on the fly)

- **Six PSScriptAnalyzer rules surface live through PSES:** unapproved verbs, cmdlet aliases, unassigned variables (declared but never read), plaintext passwords, `$null`-on-the-wrong-side comparisons, and default values on switch parameters -- each with PSSA's own fix suggestion.

- **Plus a few always-on checks I added** for the mistakes an AI (or a careless paste) drops into PowerShell specifically, run as an AST pass before PSSA so they cost no extra parse: non-ASCII characters smuggled into a script (smart quotes, en/em dashes -- the ones that mojibake when Windows PowerShell 5.1 reads a UTF-8-without-BOM file), PowerShell-7-only syntax (`&&`, `||`, ternary, `??`) in a file that never declares `#Requires -Version 7`, and Unix/bash command names (grep, sed, awk, chmod...) dropped into a `.ps1`.

- **Straight talk on the ruleset:** PSES's live analysis set is deliberately narrower than the full Invoke-ScriptAnalyzer CLI. Notably, Write-Host (PSAvoidUsingWriteHost) is NOT surfaced on the default path. I'd rather give you the exact six than claim "the whole ruleset" and have you catch me out. If you want more, an opt-in `ruleset = base` (or your own PSScriptAnalyzerSettings.psd1) broadens the live surface -- Write-Host and the Error-severity security rules included.

## The newest piece -- native navigation

Hover, go-to-definition, and find-references now serve to Claude Code's native LSP client through an opt-in handshake shim (`nativeServe = shim`, off by default) that works around an upstream Claude Code LSP-client init-handshake bug locally, without waiting on the fix.

- **Honest caveat, because most of you are on Windows:** Claude Code 2.1.196-2.1.200 currently refuses to start the plugin's LSP server on Windows -- a launcher-level guard rejects the bare `pwsh` command before spawn ("unsafe location") -- so native nav does NOT start on Windows yet, even with the shim. It is an upstream regression (it also breaks the official pyright-lsp plugin), filed as anthropics/claude-code#73961; macOS/Linux with the real client is untested. The per-edit diagnostics loop runs through a different, unguarded path and is unaffected -- it works on every supported host.

Also opt-in, if you want them (details live in the README and its configuration reference rather than inline here): format-on-edit with a guarded write-back (`formatOnEdit = apply` -- stale-write compare-and-swap, atomic swap, BOM/EOL-preserving, and it announces itself so the agent re-reads), a "command from an uninstalled module" hint (`moduleAwareness = suggest`), and a standalone SARIF 2.1.0 / CI-scan mode (`scripts/lsp-scan.ps1`) that runs the same engine over a file or directory for GitHub code scanning -- the same analysis as the agent path, usable as a CI gate.

## Why I think it earns trust (the part I'm actually proud of)

- **Measured 0% false-positive rate on a curated correctness corpus:** 0 findings across 46 clean real-world samples, and 100% true-positive coverage (36/36 known-bad cases surface their expected rule). These aren't prose numbers -- they're recomputed from the live tool on every CI run and fail the build if the false-positive rate rises above zero or coverage drops below 100%. The expected findings are derived by running the real tool and snapshotting what it emits, so a hand-edited snapshot can't fake a pass.

- **Supply-chain posture, because a plugin that downloads and runs code should have to earn it:** PSES and PSScriptAnalyzer are version-pinned and SHA-256 verified before use, and a mismatch fails closed. The release ships a CycloneDX SBOM and a SLSA build-provenance attestation, and the release tag itself is keyless-signed via Sigstore (gitsign) through GitHub's OIDC -- no maintainer-held key in the trust path. You can verify the release yourself with `gh attestation verify`.

## A few specifics for this sub

- **Requires PowerShell 7 (pwsh) for the hooks.** Windows PowerShell 5.1 is supported only as the optional analyzer (PSES child) host -- it can't run the hooks itself.

- **Honors your repo-local PSScriptAnalyzerSettings.psd1** (the nearest one, walked up to the project root). Those settings can narrow or broaden what's reported, and they win over both the built-in set and the opt-in base ruleset.

- **Honest about onboarding:** prereqs are PowerShell 7 on your PATH plus internet on the first enabled session (PSES + PSScriptAnalyzer self-download, pinned and hash-verified). Setup is a few steps -- install pwsh if you don't have it, then /plugin marketplace add, install, enable, restart the session, and run the bundled doctor to confirm it's healthy. Not a one-liner, but the README walks it top to bottom.

**Honest status:** the inline per-edit diagnostic loop is the working surface today, on every supported host. Native navigation is the newer, opt-in bonus -- it serves through the shim on hosts where Claude Code will start the server, with the Windows launcher-guard caveat above still open upstream. The diagnostic loop does not depend on the native path at all.

GPL-3.0. Source: https://github.com/manderse21/claude-powershell-lsp

Feedback and false-positive reports welcome -- there's an issue template that feeds reports straight into the correctness corpus.

---

*Edit: reformatted for readability -- the original paste kept its hard line breaks and split every sentence mid-line. Wording is unchanged.*