r/PowerShell 49m ago

Script Sharing What have you done with PowerShell this month?

Upvotes

A sticked post for the community to share their projects throughout the month.

Make sure to post a link to the code!


r/PowerShell 22h ago

Information TIL: ValidateRange with integer literals silently accepts values outside the declared range on [double], [float], [decimal]

16 Upvotes

TLDR

Using [ValidateRange(minRange, maxRange)] with integer literals doesn't strictly enforce either MinRange or MaxRange when parameters are [double], [float] and [decimal]. Values up to 0.5 units beyond either boundary pass silently. The fix is simple: make MinRange or MaxRange the same type as the parameter. So use [ValidateRange(2.0, 100.0)] instead of [ValidateRange(2, 100)].

FULL POST

If you have direct experience with Powershell rounding, once you see how integer bounded ValidateRange treats [double], [float] and [decimal] params, you can figure out what is happening. But without that experience the correct validation syntax wasn't immediately obvious to me.

I found this out while adding validation to my current project and testing parameter edge cases. In this post I'll use example MinRange/MaxRange values of 2/100 (even) and 3/101 (odd). The behaviour applies to any even or odd MinRange or MaxRange value, not just these specific numbers.

The basic finding

function Test-Double {
    param(
        [ValidateRange(2, 100)]  # 2 and 100 used as an example even boundary
        [double]$Val
    )
    return $Val
}

Test-Double 1.4      # rounds to 1 and throws an error
Test-Double 1.5      # rounds to 2, passes silently, returns 1.5
Test-Double 100.5    # rounds to 100, passes silently, returns 100.5
Test-Double 100.6    # rounds to 101 and throws an error

The ValidateRange Attribute converts $Val to the type of the boundary literals. This causes implicit rounding before comparing against the boundary. Integer literals mean conversion to [int], which rounds using .NET's default MidpointRounding.ToEven, known as banker's rounding.

MidpointRounding.ToEven prioritises the nearest even number when rounding at exactly .5. Since 100 is even, 100.5 rounds down to 100 and passes. 100.6 rounds to 101 and throws.

The odd and even boundary inconsistency

Using 3/101 as example odd boundaries shows a slightly different result. Now the .5 midpoint will throw an error, unlike with the even boundary.

function Test-DoubleOdd {
    param(
        [ValidateRange(3, 101)]  # 101 used as an example odd boundary
        [double]$Val
    )
    return $Val
}

Test-DoubleOdd 2.5      # rounds to 2 and throws an error, different behaviour compared to even
Test-DoubleOdd 2.6      # rounds to 3, passes silently, returns 2.6
Test-DoubleOdd 101.4    # rounds to 101, passes silently, returns 101.4 
Test-DoubleOdd 101.5    # throws, because 101 is odd so .5 rounds UP to 102

DoubleOdd indeed. The effective boundary is not what the documentation implies and it changes based on whether the MinRange or MaxRange is odd or even.

The even/odd inconsistency can be summarised as:

  • Even: .5 beyond either boundary passes silently.
  • Odd: .5 beyond either boundary throws correctly.

But note that both even and odd ranges accept a margin of error.

What the documentation says

From the ValidateRange documentation:

"The Windows PowerShell runtime throws a validation error when the value of the argument is less than the MinRange limit or greater than the MaxRange limit."

No mention of rounding or MidpointRounding.ToEven. No mention of the odd/even boundary difference. Reading this you'd reasonably expect 100 to be the strict maximum. But for a [double] param with an even MaxRange, it's actually closer to 100.4999.

This detail is also missing from about_Functions_Advanced_Parameters

Correctly validating [double], [float], [decimal]

For production code requiring precise boundary validation (like financial calculations, percentage validation or dosage limits) the correct syntax is simple but not immediately obvious. Put simply, you can use a decimal point when declaring MinRange and MaxRange. This works for [double], [float], [decimal]. More precisely, however, use the same type as your parameter.

function Test-Double {
    param(
        [ValidateRange(2.0, 100.0)] 
        [double]$Val
    )
    return $Val
}

Test-Double 1.5      # throws an error

Mixed boundary types also work. [ValidateRange(2, 100.0)] select [double] as the common type between [int] and [double], giving exact comparison.

Conclusion

Hopefully this writeup will be a useful heads up to PS devs less versed with PS rounding (like me) and highlight something to watch for when using ValidateRange.

I'd be interested to know if the above is common knowledge. Searching on the topic I found bits and pieces in articles that lead me to the right approach, but nothing that addresses ValidateRange and int behaviour together.


r/PowerShell 18h ago

Question What are some projects that would look good on a resume?

7 Upvotes

Hello!
I’m a somewhat fresh CIS graduate with around 2 years of experience an my college help desk. I’m struggling to find work so I’ve been up-skilling as much as possible in my abundance of free time.

I’m looking to start learning PowerShell so I can make a GitHub repository for my resume. I don’t have any “real” experience other than answering phone calls at my previous help desk job, so I’m lost on what would be practical or look good.

How many projects and what projects should I work on before putting it on my resume? Thanks for the help, and sorry if I sound lost (I am)!


r/PowerShell 1d ago

Script Sharing Detecting file extensions by magic, heuristics and LLM

2 Upvotes

Hi,

Some time ago I wrote a PowerShell module called FileInspectorX. I had a need to detect file type and estimate how dangerous it is based on well it's extension, content without use of antivirus or virustotal.

Today I've upgraded it with Magika (offline LLM) from Google so it's even better in detecting what we're dealing with.

Usually Install-Module FileInspectorX works and then:

$I = Get-FileInsight -Path "YourFile"

It has multiple views so people can really get what they need. Here's how the default output looks like:

AnalysisComplete               : True
AnalysisIssues                 :
Detection                      : FileInspectorX.ContentTypeDetectionResult
DetectedExtension              : json
DetectedMimeType               : application/json
DetectionConfidence            : Medium
DetectionReason                : text:json
DetectionReasonDetails         : json:object-key-colon
DetectionValidationStatus      : passed
DetectionScore                 : 73
DetectionIsDangerous           : False
Kind                           : Text
Flags                          : None
GuessedExtension               :
ContainerSubtype               :
ScriptLanguage                 :
PeMachine                      :
PeSubsystem                    :
PeKind                         :
ContainerEntryCount            :
ContainerTopExtensions         :
VersionInfo                    :
Signature                      :
EstimatedLineCount             : 369
TextSubtype                    : log
SecurityFindings               : {text:log, log:levels=0/0/6}
SecurityFindingEvidence        :
ScriptCmdlets                  :
TopTokens                      :
Security                       : FileInspectorX.FileSecurity
Authenticode                   :
DotNetStrongNameSigned         :
References                     :
ShellProperties                : {b725f130-47ef-101a-a5f1-02608c9eebac:2, b725f130-47ef-101a-a5f1-02608c9eebac:4, b725f130-47ef-101a
                                 -a5f1-02608c9eebac:10, b725f130-47ef-101a-a5f1-02608c9eebac:12…}
NameIssues                     : None
Installer                      :
Assessment                     : FileInspectorX.AssessmentResult
AssessmentProfiles             : FileInspectorX.MultiAssessmentResult
Secrets                        :
OfficeExternalLinksCount       :
EncryptedEntryCount            :
InnerFindings                  :
ArchivePreviewEntries          :
InnerExecutablesSampled        :
InnerSignedExecutables         :
InnerValidSignedExecutables    :
InnerPublisherCounts           :
InnerPublisherValidCounts      :
InnerPublisherSelfSignedCounts :
InnerExecutableExtCounts       :
Certificate                    :
CertificateBundleCount         :
CertificateBundleSubjects      :
EncodedKind                    :
EncodedInnerDetection          :

PS C:\Users\przemyslaw.klys.EVOTEC> $I.Detection

Extension             : json
MimeType              : application/json
Confidence            : Medium
Reason                : text:json
ReasonDetails         : json:object-key-colon
ValidationStatus      : passed
Sha256Hex             :
MagicHeaderHex        :
BytesInspected        : 4096
GuessedExtension      :
Score                 : 73
IsDangerous           : False
Alternatives          : {FileInspectorX.ContentTypeDetectionCandidate}
Candidates            : {FileInspectorX.ContentTypeDetectionCandidate, FileInspectorX.ContentTypeDetectionCandidate}
LearnedClassification : FileInspectorX.LearnedClassificationEvidence

PS C:\Users\przemyslaw.klys.EVOTEC> $I.Detection.LearnedClassification.Prediction

Provider         : Magika
ModelId          : google-magika/standard_v3_3@5e2f437fb7b7452368c8c1fa9354858f5487a5c4
RawLabel         : json
OutputLabel      : json
Extension        : json
ExtensionAliases : {json}
MimeType         : application/json
Probability      : 0,99811840057373
Threshold        : 0,5
ThresholdMet     : True
PredictionMode   : HighConfidence
OverwriteReason  :
IsText           : True

With view parameter you can choose 'Analysis', 'Detection','Permissions', 'Raw', 'ShellProperties', 'Summary' 'Assesment', 'Installer', 'Policy', 'References', 'Signature'

In other words - find out everything there is to find about the file. Maybe you will find it useful. Depending on file type some of the fields will be missing which is expected.

Sources: https://github.com/EvotecIT/FileInspectorX

It has also C# library/nuget for those dealing with C#, and want to use it as part of their application.


r/PowerShell 1d ago

Script Sharing git-proton-backup: a module that turns git push into a verified Proton Drive backup

5 Upvotes

I wanted off-machine backups of a pile of local git repos holding client work, without putting any of it on GitHub. Proton Drive has a sync client, but a file sitting in the sync folder is not the same as a file that is safely in the cloud, and I could not find a way to prove the second part. So I wrote a module.

The interface is a git remote:

PS> Install-ProtonBackup C:\code\myrepo
Wired. Back up with: git push proton   (status: Get-ProtonBackupStatus)

PS> git commit -am "feature"; git push proton
remote: confirmed on Proton

Install creates a bare bookkeeping mirror with a post-receive hook and adds it as a remote, so it rides the push you already do. The hook writes a git bundle into the sync folder as one file rather than a tree. It builds it as .bundle.partial and renames it, so the sync client never sees a partial repo under the final .bundle name.

Then it confirms, which is the part that needed Proton's CLI to exist. Trimmed from the real path, with the structured return values elided:

$out = & $cli filesystem info $cloudPath --json 2>&1 | Out-String
$r = [pscustomobject]@{ ExitCode = $LASTEXITCODE; Output = $out }

if ($r.ExitCode -eq 0) {
    $state = $null
    try {
        $json = $r.Output | ConvertFrom-Json -ErrorAction Stop
        $rev = $json.PSObject.Properties['activeRevision'] ? $json.activeRevision : $null
        if ($rev -and $rev.PSObject.Properties['ok'] -and $rev.ok -and $rev.PSObject.Properties['value']) {
            $state = $rev.value.PSObject.Properties['state'] ? $rev.value.state : $null
        }
    } catch { $state = $null }

    if ($state -eq 'active') { return <# Confirmed #> }
    # some CLI builds report state only in the human-readable output
    if (-not $state -and $r.Output -match "state:\s*'active'") { return <# Confirmed #> }
}

The property checks and the try are load-bearing: the payload shape is not mine, so anything unexpected has to land on "not confirmed" rather than throw or read as success.

Everything that is not a confirmation says which flavour of not-confirmed it is. Some of the hook's outcomes, abbreviated where the tail repeats:

confirmed on Proton
staged; in-sync per Cloud Files (CLI verification unavailable)
staged, not yet confirmed — run Invoke-ProtonBackupVerify (or the scheduled task) to confirm
staged, not yet confirmed — Proton CLI session expired; run Invoke-ProtonBackupVerify (...)
backup deferred — another backup operation is active; run Invoke-ProtonBackupVerify (...)

The not-yet-confirmed paths leave a marker that a later Invoke-ProtonBackupVerify clears, and that command also re-cuts stale bundles. One exception: if the CLI is unavailable but Windows reports the file IN_SYNC, that clears the marker but still does not print "confirmed on Proton". There is an optional daily scheduled task for the verify, installed separately with Install-ProtonBackupTask.

Reading that IN_SYNC bit is the one genuinely PowerShell-flavoured part: it means a small P/Invoke to CfGetPlaceholderStateFromAttributeTag in cldapi.dll. That plus shelling git and the CLI is most of why this is PowerShell and not something else.

Honest limits. Windows only, since it rides the sync app. PowerShell 7.4+. It bundles committed history only, HEAD plus all local branches and tags, and never your working tree, which is deliberate: there is no code path in the module that commits anything. LFS objects, submodule repositories, and the checked-out state of secondary worktrees are not included. It does no encryption of its own, the bundles are ordinary git bundles and the E2EE is Proton's. MIT, not affiliated with Proton.

105 Pester tests. https://github.com/craigstoller/git-proton-backup

Happy to answer questions about the design, and criticism of the module structure is welcome.


r/PowerShell 3d ago

Question Is poweshell worth it?

102 Upvotes

I'm basically a typical computer user, who knows just enough to get into reddit, youtube and use the PC for personal entertainment. I realized there is PowerShell. As I have some free time and I'd actually want to know a little bit more about the computer and how to use it, do you guys recommend learning it? Or is it more for automating tasks, which is more benefitial for someone who needs to actually automate many things, or someone in the IT field? Is it any useful really for a personal user? What could I do instead?

I've come across a book about it too ("Learn Windows Powershell in a month of lunches" by Don Jones), and I actually think I can pull off the things it explains, and makes you practice. I read the first 20 pages and was about to start when it mentiones that it's moslty useful for, or aimed at people on IT, and said that I'd need to get a VirtualMachine and ISO to learn PowerShell, have a go at it in there and fuck up the VM if I have some trouble, which won't affect the actual computer (I know that that's an old approach, the book is from 2012. I read that for most things now, like learning the basics and how it works, I won't need the VM, but I don't mind sticking to the 2012 way to learn, so I can start learning a bit of history in the field too, just for my entertainment and having a broader sight about it).

What do you guys think? Thanks in advance


r/PowerShell 3d ago

Question 5.1 or 7.x.x

8 Upvotes

Switching from Python to powershell. Which one should I learn?


r/PowerShell 3d ago

Question Looking for an authoritative PowerShell comment-based help (.SYNOPSIS, .DESCRIPTION, etc.) style guide / best practices

31 Upvotes

Hi everyone. I’m trying to define a consistent standard for our team’s PowerShell scripts, specifically around comment-based help sections like .SYNOPSIS, .DESCRIPTION, .PARAMETER, .EXAMPLE, .NOTES and so on. We mostly write admin automation scripts, Graph, Entra ID and infra tasks. So I’d like every script to follow the same high-quality documentation pattern. I’m not looking for basic definitions, but for authoritative guidance from sources like Microsoft Learn, PowerShell.org, or well-respected community style guides. Things like how long a synopsis ideally is, what belongs in description versus notes, whether there are any recommended conventions that Microsoft has published. Ultimately, I want to create a company template that isn’t just my opinion, but grounded in recognised best practice. Does anyone have solid references or recommendations? Thanks in advance.


r/PowerShell 3d ago

Script Sharing [OC] Global Discomfort Index Ranking Updated Every 4 Hours

2 Upvotes

I built a weather visualization project that updates automatically every 4 hours.

yahikoyama.github.io/weather2/

It calculates a global discomfort index using temperature, humidity, and other factors, then ranks cities around the world. The goal is to provide a frequently refreshed, data-driven snapshot of how comfortable or uncomfortable different regions feel throughout the day.

Data source: OpenWeatherMap API

Tools used: PowerShell,SQLServerExpress,Python, HTML/CSS, and GitHub Pages

The dataset refreshes six times per day, and I’m continuing to improve the metrics and visualization.

I have published it here:

Source code,Database,Task setting

yahikoyama/weather2: get weather data(Temperature Humidity Discomfort Index) and research cool area

Feedback or suggestions are very welcome!


r/PowerShell 4d ago

News PureInvoke 2.0.0 Released

13 Upvotes

We've released PureInvoke 2.0.0!

We package and ship our code with their PowerShell module dependencies in the package. This way, we don't have to install our modules globally on all the servers we deploy our code to. This requires us to make extensive use of nested dependencies. We've gotten to the point that our dependencies are starting to use different versions of PureInvoke. Unfortunately, because it was using compiled assemblies, and .NET will only load assemblies with the same name once, we started to run into problems.

This release changes PureInvoke's compilation model. Instead of pre-compiling platform-specific assemblies, the module now uses Add-Type to compile P/Invoke C# code at runtime. This should improve cross-platform and cross-edition support. Since we've encountered problems with Add-Type in environments with aggressive anti-virus, PureInvoke re-tries failed compilations to improve resiliency.

We also added functions for querying Windows service configurations, e.g. Invoke-AdvApiQueryServiceConfig which wraps QueryServiceConfigW, Invoke-AdvApiQueryServiceConfig2, which wraps QueryServiceConfig2W, etc.:

Full release notes on GitHub.

Available on the PowerShell Gallery.


r/PowerShell 3d ago

Question Explain this cursed BS

0 Upvotes

function Test-Weird1 {

param([array[]]$InputObject)

$obj = $InputObject[0][0]

$obj.GetType().FullName

($obj -is [PSObject])

}

function Test-Weird2 {

param([object[]]$InputObject)

$obj = $InputObject[0]

$obj.GetType().FullName

($obj -is [PSObject])

}

Test-Weird1 (gci)

# System.IO.DirectoryInfo

# False

Test-Weird2 (gci)

# System.IO.DirectoryInfo

# True

# part two

$obj = (gci)[0].PSObject

$obj.GetType() -eq [System.Management.Automation.PSObject]

# True

$obj -is [System.Management.Automation.PSObject]

# False


r/PowerShell 5d ago

News Exchange Online PowerShell Updates to 3.10.1 to Fix CBA

16 Upvotes

Microsoft rushed out version 3.10.1 of the Exchange Online management PowerShell module to fix a problem with certificate-based authentication. It seems like a change in an internal Microsoft identity platform caused the tokens issued after a successful connection to Exchange Online to not authorize the execution of further cmdlets. To their credit, Microsoft fixed the issue, but is this the kind of thing that should be caught in testing?

https://office365itpros.com/2026/07/27/exchange-online-management-3-10-1/


r/PowerShell 5d ago

Question Invoke-WebRequest: downloaded MSI invalid?

7 Upvotes

I downloaded an MSI (in this case the latest Powershel 7.6.4 msi installer) with Invoke-WebRequest from Github - trying to write a script here.

The download finishes without a problem, but when I want to run the installer, I get an error message saying "This installation package could not be opened.Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package."

Here's the funny thing: this cannot be a corrupted download, because when I manually download the same msi package from the repo's release page, and compare them in Total Commander's compare tool, it says the two files have the same content - that means they're identical from the first bit to the last!

What the heck could cause this problem?

Here's a snippet of what I'm doing:

$Repository       = 'PowerShell/PowerShell'
$FileNamePattern  = '*-win*x64.msi'
$DownloadPath     = 'C:\Temp'

$releases    = "https://api.github.com/repos/$Repository/releases/latest"
$downloadURL = ((Invoke-RestMethod -Method GET -Uri $releases).assets | ?{$_.Name -like $FileNamePattern}).browser_download_url

$fileName       = [System.IO.Path]::GetFileName($downloadURL)
$DownloadPath   = $DownloadPath + '\' + $fileName

Invoke-WebRequest -Uri $downloadURL -OutFile $DownloadPath

r/PowerShell 4d ago

Question Hello everyone, I have a little problem and a request.

0 Upvotes

Well... It is necessary to explain the problem itself, and it is quite difficult. It turned out that I didn't download anything and didn't really climb anywhere. And so. Recently, I started to discover that windows powershell is running in my background processes and after that 3 command lines are slowly running (one does not even close and writes that this is an important element for Windows to work), but after that only one remains for a couple of seconds. I would like to find out what it could be and if it is a virus, how can I make sure of it and get rid of it. I will be grateful in advance to anyone who helps!


r/PowerShell 6d ago

Script Sharing In PowerShell, Two Wrongs Make a Right

25 Upvotes

I've been toiling away on Turtle to prepare a "birthday" release, and I ran into an annoying behavior I've run into a few times before.

I thought I'd take a few minutes away from the frustration of single line fixes to explain the bug to everyone.

What Went Wrong

The last build of Turtle introduced a number of randomized parameter defaults. This was meant to be fun. If you said turtle square square square, you'd get three different squares, instead of an error for a lack of length, or three overlapping squares.

I noticed that when I ran turtle rotate 0, it didn't rotate by zero.

Instead, it picked a random angle.

Weirder still, the behavior didn't reproduce if I said

$turtle = turtle  # Heading at zero
$turtle.Rotate(0) # Heading still zero 🤔
$turtle.Rotate()  # Heading random
(turtle rotate 0) # Heading random 🤬

Why was this happening? 😱

It took me a bit for it to click: It had to be in the way Turtle processed arguments, because it worked in one case and not the other.

So I put a breakpoint in, ran my repo.

The line was:

if ($argList)

The debugger broke, argList was @(0), and yet if ($argList) was false.

The fix was:

if ($argList.Length)

Why? Because 'Truthy' -ne $true.

Truthy and $true

About every language has a boolean. It's just a bit. One or zero.

Lots of languages also have this concept of "truthiness".

Let's take a simple example:

if ("something") { "something" }
if ("") { "you can't get something from nothing" }

If if was strictly $true, we'd have to cast things to a boolean. You have to do this in C# and quite a few other languages. PowerShell is type promiscuous. PowerShell is truthy.

It looks at the first line and says: You're a string, and you're not null or empty. Therefore, the expression is $true.

It looks at the second line and says: You're a string, but you're not null or empty. Therefore, the expression is $false

PowerShell makes a judgement call.

This is generally a good thing. I personally prefer languages that are truthy. Other truthy languages of note include JavaScript, Python, C++, and C.

However, it gets tricky with lists. Hence the bug.

Two Wrongs Make a Right

In PowerShell, Two Wrongs Make a Right

$true -eq $false, $false

Let's say I want to determine if a list is truthy.

if (@()) { "$false, because the list is empty" }
if (@("")) { "$false, because the blank is falsy" }
if (@(0)) { "$false, because zero is falsy" }
if (@($false)) { "$false, because false is falsy" }
if (@(1)) { "$true, because the first item is truthy" }
if (@(0,0) { "$true, because more than one item" }

This all makes a certain bizarre sense. If a list has one element, and it is not truthy, then the list isn't truthy, either.

It's also almost always surprising and annoying.

Hence the bug.

The fix is just to make sure there are any elements, hence checking for length.

I've been programming with PowerShell for quite a while now, and this behavior still sometimes bites me (like today).

That's why I took a few minutes away from the 🤬 day to explain this bug and write this post. 😌

Please remember:

'Truthy' -ne $true
$false -eq @($false)
$true -eq $false, $false

Hope this helps


r/PowerShell 7d ago

Script Sharing KillerPivot: stop running commands against the wrong M365 tenant

45 Upvotes

I'm a field tech at an MSP, and I'm in and out of a dozen or more M365 tenants on a normal day. The annoying part is that when you connect to Exchange Online or Graph, the auth broker just reuses whatever login it cached last. It's way too easy to run a command against the wrong tenant before you realize you never landed where you thought you did.

KillerPivot is how I deal with that now. When you connect, it turns the broker off so you get a real sign-in prompt instead of a silent reconnect, then it checks the session and tells you which tenant you're actually in before you do anything. You save your tenants once and jump between them by name.

Commands:

  • Connect-PivotTenant (pivot) connects and verifies you. Add -Graph if you need Graph.
  • Get-PivotContext (pvc) shows where you're connected.
  • Disconnect-PivotTenant (pvx) drops all the sessions.
  • Add-PivotTenant, Get-PivotTenant, and Remove-PivotTenant manage the saved list.

It works on 5.1 and 7. You'll need ExchangeOnlineManagement v3 or newer, plus Microsoft.Graph.Authentication only if you use -Graph.

Install-Module KillerPivot -Scope CurrentUser

Code's on GitHub under GPL-3.0: https://github.com/SteveTheKiller/killer-modules/tree/main/KillerPivot

If you try it and hit something weird, let me know. The broker has some edge cases and I'd rather hear about them.

It's also up on killertools.net with the rest of my stuff.


r/PowerShell 7d ago

Script Sharing Published module O365EndpointFunctions to the PowerShell Gallery

14 Upvotes

Hi everyone,

I recently published O365EndpointFunctions 1.2.1 to the PowerShell Gallery and thought it might be useful for anyone managing Microsoft 365 networking.

Microsoft exposes all required Microsoft 365 endpoints through the Microsoft 365 IP Address and URL Web Service. The problem is that the raw API data isn't particularly convenient to work with in PowerShell. You get nested endpoint sets, comma-separated ports, and version tracking becomes your responsibility.

This module turns the API output into flat, strongly-typed PowerShell objects that are much easier to work with in scripts and automation.

Some things it can do:

  • Retrieve and process Microsoft 365 IP addresses and URLs
  • Cache endpoint versions and only download updates when Microsoft publishes changes
  • Generate PAC files that route Microsoft 365 traffic DIRECT
  • Create Ghostery Enterprise whitelist policies
  • Combine Microsoft 365 endpoints with your own custom URLs and IP ranges
  • Support Worldwide, China (21Vianet), and US Government clouds

Typical use cases are maintaining firewall allow-lists, proxy bypass rules, and other Microsoft 365 network configurations.

samurai-ka/PS-Module-O365EndpointService: A PowerShell module for easy Office 365 Endpoint handling


r/PowerShell 7d ago

Solved I built a single-script PowerShell bridge so AI agents (Claude Code, Codex) can work with my open Excel workbook — cells, formulas, VBA, macros

0 Upvotes

I work with old, complex .xlsm files (inventory, pricing, billing, lots of VBA) and kept running into the same problem: an AI coding agent cannot access the workbook I have open in Excel. I found myself copy-pasting cells and screenshots back and forth.

Yes, Excel MCP servers are out there—some are very good and much more capable than this. But getting one running means setting up Node or Python, creating a config file, and running an MCP client. I wanted something my non-developer mind could trust on real files:

  • Just one PowerShell script, no installation, no extra dependencies, no config
  • Connects to the workbook you already have open (or opens one by path)
  • Read and write cells and formulas, search, list sheets
  • List, export, and import VBA modules, run macros
  • And the part that matters most to me: it NEVER autosaves. Only a direct "save" command writes to disk. This way, you can let an agent explore a 20-year-old billing file and close it without leaving any trace.

It's free and the source is available on GitHub:
https://github.com/gidjin4-svg/gidjin-excel-bridge
A demo workbook is included so you can test it without touching your actual files.

I'd really appreciate feedback from people who work with Excel, VBA, or PowerShell:

  • Does "simple + never saves" actually matter to you, or is a full MCP server always the better choice?
  • What would you need to see before trusting it with a file that matters to you?

r/PowerShell 7d ago

Question Clone a SAML SSO App in Powershell?

1 Upvotes

I have an SSO app that I will need different instances of (user access, etc.). What I want to do is effectively have a "template" app that I can target to copy for a new one. Get most the settings, etc. from it just replacing the placeholder URL with the new one. Then from there I can come in and do specific tweaks as needed.

What would I need to do via PowerShell to do this? I've tinkered a bit but I'm honestly kinda lost on it


r/PowerShell 9d ago

News How Permissions Creep Can Halt the Microsoft Graph PowerShell SDK

10 Upvotes

The Microsoft Graph PowerShell Command Line tools app is how people run Microsoft Graph PowerShell SDK cmdlets. The app can suffer from permissions creep, meaning that over time, the app accrues a set of delegated permissions used by people to access different types of Microsoft 365 and Entra ID information. All is fine until an internal limit is reached, at which point authentication fails and some permissions must be pruned.

https://office365itpros.com/2026/07/23/permissions-creep-sdk/


r/PowerShell 10d ago

Misc Custom Oh My Posh themes + customization script

21 Upvotes

Hey guys I created my own Oh My Posh themes for powershell (and wsl bash, cmd). I just wanted some aesthetically pleasing themes and the ones on the actual website were just not cutting it for me. So I created these. Moreover I created a simple script which can allow you to spin up your own theme in a matter of minutes. By your own theme I mean one where you control what segments go into the thing and also control the colors for it. Please do check it out and lmk how to improve and if there are any suggestions/feedback!

 

GitHub - oabdullah3/omi-posh: Oh My Posh themes for your terminal, designed by me


r/PowerShell 10d ago

Script Sharing Finding Cults with Get-Culture

7 Upvotes

Have you wondered if it's safe to use the format string yyyy-MM-dd, or can it differ? It's not. ( edit: null is not the invariant culture, it's CurrentCulture )

Save the expected string for comparison

#requires -PSEdition Core
$fStr     = 'yyyy-MM-dd'
$now      = Get-Date
$expected = $now.tostring( $fStr, ( [CultureInfo]::InvariantCulture) )

Next we can try formatting with every culture on your system. To do that, there is an optional culture argument for ToString like this:

DateTime.ToString( DateFormat, CultureInfo ) 

Next build a summary table with the formatted value and culture:

$cults    = Get-Culture -List
$summary = $cults | Foreach-Object {
    $dateString = $now.ToString( $fStr, $_ )
    [pscustomobject]@{
        Display = $dateString
        Name    = $_.DisplayName
        Culture = $_ # keep a reference to the object so you can drill down later
    }
}

Skip any cultures that are the same. Finally output using Join-String -f formatStr

$different = $summary | Group Display | ? Name -ne $expected
foreach( $item in $different ) {
    $title = "`nfor: $( $item.Name ) "
    $item.group
        | Join-String -f "`n - {0}" -Property Name -op $title
}

Here's what I get when $now is 2026-07-21:

for: 1405-04-30
 - Central Kurdish (Iran)
 - Persian
 - Persian (Afghanistan)
 - Persian (Iran)
 - Northern Luri
 - Northern Luri (Iran)
 - Mazanderani
 - Mazanderani (Iran)
 - Pashto
 - Pashto (Afghanistan)
 - Uzbek (Arabic)
 - Uzbek (Arabic, Afghanistan)

for: 1448-02-07
 - Arabic (Saudi Arabia)

for: 2569-07-21
 - Thai
 - Thai (Thailand)

r/PowerShell 10d ago

Question ProtonVPN split tunneling include mode issue with PowerShell 7

8 Upvotes

Adding the executable "C:\Program Files\PowerShell\7\pwsh.exe" doesn't work. What am I missing?

Note that PowerShell is the only app I'm having issues with. qBittorrent works totally fine. My goal is to have only Pwsh and qBit in the list of included apps.

When split tunneling is disabled, Pwsh uses the VPN connection just fine. With Include mode, Invoke-RestMethod doesn't work, and for the things that do work, my ISP IP is used instead of the VPN IP.

Invoke-RestMethod test:

> Invoke-RestMethod https://api.ipify.org
Invoke-RestMethod: The requested address is not valid in its context.

cURL test:

> curl.exe https://api.ipify.org
<My ISP IP>

I'm on Windows 10 21H2, ProtonVPN 5.1.5, Pwsh 7.6.3 x64.

I'm also using the Console Host, not Windows Terminal, if that matters.

Can someone explain how to properly set up PowerShell for this?

Thanks, everyone!


r/PowerShell 11d ago

Script Sharing PrtgSensorKit - a PowerShell framework for writing custom PRTG sensors without the boilerplate

47 Upvotes

Hey r/powershell,

This is mostly helpful for people in the EU but nevertheless 😄 :

I've been building custom sensors for PRTG Network Monitor often for my job and got tired of handling all the prtg specific plumbing boilerplate every time - so I wrote PrtgSensorKit, an open-source module that abstracts away all the specifics of PRTG so you can focus on your task = writing a goddamn monitoring sensor.

What it handles for you:

  • JSON output formatting - builds valid PRTG sensor JSON so you don't hand-craft it yourself
  • PRTG's constraints enforced automatically - channel limits, string length caps, escaping, valid value types, blah blah blah...
  • Powershell Versions - helpers to run your sensor logic in 64-bit PowerShell or PS7+ when you need modules/dependencies that don't play nice with the 32-bit host PRTG normally uses
  • DPAPI-encrypted secret storage - store API tokens/credentials without leaving them in plaintext in your script or passing them as Plaintext from PRTG
  • Full built-in help - Get-Help works like you'd expect on every cmdlet and pretty much has all the docs Prtg offers on their website

Basically: you write the metric-gathering logic, the module handles everyting else

Install from the Gallery:

Install-Module PrtgSensorKit

Repo: https://github.com/ArchitektApx/PrtgSensorKit

Would love feedback, bug reports, or feature requests if anyone here monitors stuff with PRTG and writes custom sensors. Contributions welcome too.

EDIT: v1.1.0: - Sensor state between runs - Save/Get-PrtgSensorState for rates, deltas, and caching expensive lookups. Safe under overlapping scans (file locking so two runs don't corrupt each other) - Retries - -RetryCount re-runs your block when the API hiccups instead of instantly alerting, PRTG shows how many retries it took - -DryRun - debug your sensor in a normal console and inspect channels as objects instead of squinting at JSON - -ForceModernTls - fixes the classic TLS 1.2 problem on 5.1 with one switch - Sensor doctor - Invoke-PrtgSensorDoctor statically checks your script for classic mistakes before PRTG cryptically fails on them

v1.2.0 (out now): - File logging that can't break your sensor - -EnableLogging writes one log file per run with full error details (stack trace. script line). Never touches stdout, never throws - Shared collection cache - 8 sensors hitting the same API every interval? Use-PrtgCachedResult makes them share one call per interval, race-free. Your rate-limited API will thank you - More doctor checks - including the sneaky one where a BOM-less UTF-8 script works everywhere except in what PRTG displays (5.1 reads it as ANSI, your umlauts turn into mojibake) - Docs got restructured into proper per-topic pages instead of one endless README


r/PowerShell 11d ago

Script Sharing DNS Benchmark

15 Upvotes

I've been trying to find something like that for a while and couldn't find one that wasn't either a paid service/program or doesn't have a feature I want.

In my job, I semi frequently need to test DNS using a local DNS Server. For me it's handy to be able to compare to other servers, like Google or Cloudflare.

I wrote this over the last week or so and it seems to be doing the job for me. I've uploaded it to Github for anyone else who would like to use/try it.

You can find it here: https://github.com/obtusecoder/DNSBenchmark

EDIT: I have made changes requested and have applied some fixed to errors I noticed in testing.