Stop Manual Tenant Cleanup—PowerShell Does It Better
22 Minuten
Podcast
Podcaster
M365 Show brings you expert insights, news, and strategies across Power Platform, Azure, Security, Data, and Collaboration in the Microsoft ecosystem.
Beschreibung
vor 4 Monaten
Too many admins spend Friday afternoons hunting for outdated
users and misconfigured settings. Here’s the kicker—each missed
account is a new risk, just waiting to happen. Today, you’ll see
how a smart set of PowerShell scripts can automate your tenant
governance, lock down compliance, and actually save your
weekends.
The Hidden Mess: What Admins Miss in Manual Reviews
If you’ve ever peeked behind the curtain of your Microsoft 365
tenant, you probably know that feeling—like looking at a
half-organized junk drawer that keeps collecting random odds and
ends. On the surface, everything appears manageable. You’re
logging in, scanning user accounts, tweaking a setting here or
there. Maybe you’re running that same PowerShell snippet you
grabbed off TechNet three years ago. It feels organized enough.
But the second you start digging into the details, odd little
gaps start cropping up. There’s always a handful of accounts
where you’re not sure why they’re enabled, a few security groups
with names nobody recognizes, and SharePoint sites that haven’t
seen activity since the last re-org.Let’s talk about the myth of
“manual governance.” You know the drill—log in, page through the
admin center, check the last sign-in dates, maybe send a couple
of emails asking managers if these accounts are still in use. The
idea is simple but deceptive. You can only look at what’s already
on your mind, or what the interface puts in front of you. The
really sneaky problems rarely show up in dashboards or
notifications. One day you’re convinced you’ve nailed it. The
next day, a compliance audit turns up two dozen shadow guest
accounts and a stack of unassigned licenses quietly racking up
costs.That brings up a scenario I see all the time. Take one
admin—let’s call her Claire. Claire does her quarterly review by
the book. She combs through every list she can find, checks the
Exchange mailboxes, prunes out a few guest users, and thinks
she’s done. A month later, an auditor uncovers that nobody
offboarded several project contractors from the previous year.
Those accounts are still active, assigned critical permissions,
and, as a bonus, sitting on a few expensive licenses. Then there
are SharePoint links from the last marketing campaign, wide open
for external users because nobody set expiration dates on guest
sharing.This isn’t unique to Claire, and it’s not about a lack of
effort. Most admins do a reasonable job—at least, as far as
checklists and spot checks go. But according to Gartner and a
handful of other IT studies, up to 30% of Microsoft 365 licenses
often sit unused across organizations. Orphaned accounts—in other
words, user objects left behind after someone leaves or changes
roles—can linger in the system for months. These zombie accounts
tend to accumulate more in environments where offboarding is a
separate process, HR and IT don’t always talk, and ownership for
guest access is a passing conversation, not a tracked
workflow.Think about it like cleaning your house. It’s easy to
vacuum the living room and wipe the kitchen counters. It looks
clean enough when people visit. But if you never open the closets
or check under the bed, all sorts of clutter piles up right out
of sight. With your tenant, it’s groups and users and sharing
links shoved into forgotten corners. Everything looks good—until
the day someone on the security team decides to “look closer,”
and suddenly you’re spending your weekend closing doors you
didn’t even know were open.And here’s the catch: the Microsoft
365 portal and security center make it really simple to feel
productive. The interfaces show you the most recent sign-ins,
flag obvious alerts, and give you pie charts that look
reassuring. But risky settings—like guest sharing with no
expiration, app passwords still enabled for accounts with MFA, or
directories overflowing with stale teams—hide behind extra menus
or need cross-referencing with multiple reports. It’s easy to
miss the big picture.Microsoft MVPs who live in this space see it
all the time. When admins rely on spot checks or dashboard data,
they end up missing more than half the risky configurations. Not
because they’re careless, but because the system isn’t designed
for holistic visibility. The manual review leaves blind spots
everywhere.If manual efforts are missing so much, the question
becomes obvious. How do you make sure you’re not just cleaning
the living room while the basement floods with old access and
unused resources? We’ve seen what happens when things get missed.
Those dormant accounts aren’t just wasting budget—they’re a weak
point in your security posture. Stale external links look
harmless until someone finds that “confidential” doc with a
six-month-old guest link floating around a vendor’s inbox. It’s a
compliance nightmare waiting to happen.This is why it pays to
think beyond just reacting to alerts or spot-checking once a
quarter. True tenant hygiene asks for a system that doesn’t trust
your memory, habits, or even the built-in admin reports. Because,
let’s be honest, most tenants grow more complex and messy over
time—not less. Without a real way to track, audit, and clean
things up, your manual process is basically a game of
whack-a-mole, and the moles always get faster.So, the bigger pain
isn’t just about the time you spend clicking through endless
menus or tracking down last login dates. The real cost lives in
the growing shadow of unchecked risk—security, compliance, and
even reputation. But there actually is a more reliable answer.
The question is: what does true tenant hygiene really look like,
and what does it take to get there? Let’s shift gears and move
from theory to real-world solutions.
PowerShell: The Admin’s Secret Weapon
If you walk into most offices and say “PowerShell,” you’ll either
get a knowing nod or a panicked look—sometimes both from the same
person. For a long time, it had the reputation of being a tool
for the datacenter crowd, the people who live knee-deep in server
racks, not your average Microsoft 365 admin. But Microsoft has a
habit of putting PowerShell at the center of everything new in
their cloud stack, and there’s a reason for that. It quietly
bridges all those annoying gaps you find between shiny admin
portals and real-world needs. The PowerShell window isn’t flashy,
but it’s the only reliable way to see below the dashboards and
actually keep pace with what’s happening across your tenant.Most
of us started with PowerShell just trying to fix something the UI
wouldn’t let us do. Maybe it was unlocking a mailbox, or
mass-removing licenses after a department shutdown. Those one-off
fixes are fine, but there’s way more on the table. What changes
everything is automation. When you start letting PowerShell do
these checks for you—on a schedule, across all the places the
admin portals don’t reach—you move past chasing your tail in the
GUI. Suddenly, the job is less about reactively hunting for
issues and more about having risks surface themselves in a neat
report, right when you need it.Here’s where most admins get
stuck: they treat PowerShell like a copy-paste tool. Google up a
script, slap it in, press enter, hope for the best, and then jump
back into the interface for anything that looks complicated. It’s
the shortcut mentality—and sometimes it works. But automation
isn’t about grabbing two lines of code and hoping nothing breaks.
It’s about getting the results you need, consistently, without
crossing your fingers every time. Reliability is the name of the
game. If you don’t know exactly what a script is about to touch,
you’re one typo away from a very long night.Let’s get concrete
for a moment. There’s a mid-size non-profit I worked with that
used to block off every Thursday afternoon just for user and
license audits. It sounds excessive, but three or four people
would pour over Excel exports, compare sign-in logs to HR
spreadsheets, and send out “Is this account still in use?”
emails. All in, four hours a week just keeping up with churn.
When they finally set up a scheduled PowerShell script, that
whole review shrank to a ten-minute task. The script pulled fresh
data every week, flagged accounts with no activity, and compiled
license usage into a single file that required maybe two
follow-up questions instead of forty. They didn’t just save
time—they stopped missing the little rogue accounts that caused
past audit headaches.That’s the thing: every PowerShell module
brings a different set of superpowers to your tenant cleanup. The
classic MSOnline module helps you slice through those sprawling
license lists and spot unassigned or orphaned subscriptions
practically instantly. With AzureAD, you can finally see the
forest and the trees—dumping lists of inactive users, auditing
who has passwordless auth enabled, and tracking group memberships
in seconds. If you’re wrangling shared mailboxes or checking who
still has permissions after a re-org, ExchangeOnline brings all
those user objects and mailbox properties into focus, not just
the handful visible in Outlook on the web. Then SharePointPnP
steps in for the land of hidden team sites and stale files,
letting you find which sites haven’t seen a legitimate login in
months, and who’s left as an owner after most of the project team
walked out.Want a taste of what these modules can do, right out
of the box? Try this: with just a few lines, you can have
PowerShell return every user who hasn’t logged in for ninety
days—no pivot tables, no manual data merges, just the real list,
ready to go. For external sharing, you can generate a report of
every single guest account with active permissions, or run a
script that sweeps through SharePoint and flags sites with no
recent edits, so you’re not chasing phantom projects or leftover
teams. Once you have visibility, things that used to need hours
of cross-checking get mapped out in five minutes.If your biggest
pain is unused licenses stacking up, you can automate the hunt
for those too. Picture a scheduled script that grabs every user,
checks their sign-in status, filters out service accounts, and
spits out a CSV of assigned but untouched licenses. That goes
straight to the person who needs to act—no more waiting for
someone else to notice a spike on the billing report. PowerShell
doesn’t make these calls for you, but it lines up all the key
questions so you’re never caught off guard when someone asks,
“Why are we paying for that?”Of course, once you begin to
automate, there’s a new layer of responsibility. Logging isn’t a
“nice to have”—it’s non-negotiable. Without it, you’re running
scripts in the dark, hoping nothing goes sideways. Error handling
is just as crucial. Miss a try-catch, and one little glitch could
mean skipped accounts or, worse, changes where you didn’t expect
them. If you want these scripts to replace manual reviews, you
need an audit trail. Think—every change and every failure,
written to a log you can actually read.The payoff goes beyond
saving time: these scripts catch problems before your auditors
do. No more racing to clean up the mess the night before someone
shows up with a checklist. But, let’s not pretend automation is
magic. Even the best script can do damage if it’s rushed or
untested. That’s why next, it’s worth unpacking how to make sure
your automation is built to last—and doesn’t wreck your tenant
while trying to clean it.
From Reactive to Proactive: Automating and Scheduling Governance
Imagine starting your Monday morning and finding out your tenant
has already flagged guest accounts with risky access, listed out
inactive users, and alerted you about sites with no recent
logins. You didn’t log in over the weekend. You didn’t run a
thing. This is where true automation takes over, and it’s what
separates constant firefighting from a smooth, self-monitoring
environment. Manually launching scripts is better than nothing,
but it’s still the digital version of mowing your own lawn when
you could have someone do it while you’re asleep. Scheduled,
proactive governance doesn’t just free up time—it shifts the
whole mindset from “fixing problems” to letting risks bubble up
automatically so you can work on actual projects, not just
unclogging the pipes every week.But before you start dreaming
about all the work you’ll never have to do again, there’s the
uncomfortable truth that automation can absolutely go wrong. It
doesn’t take long to find a story about a script with a missing
parameter that managed to wipe out a dozen legitimate accounts.
The power that makes PowerShell so effective also makes it
risky—one wrong variable, and you’re not cleaning up anymore,
you’re breaking things. Unsupervised automation is the nightmare
scenario that keeps everyone hovering over “Confirm” dialogs
before letting scripts make changes unattended. Staying in
control is about more than just pressing “Go”—it’s about building
in the training wheels that prevent accidents even if someone
else maintains the scripts six months from now.Let’s look at a
situation that’s more common than you’d think. A marketing agency
thought they had a handle on external user access. Every quarter,
IT would scan through guest users by hand, disable the really old
ones, and trust that project managers remembered to update
permissions. Eventually, they set up a scheduled PowerShell job
to generate a weekly report breaking down every guest’s last
activity and every site shared externally. First week, nothing
seemed strange. But by the second report, the admin noticed an
entire project site, quietly left open for guest access because a
single group email was used for sharing. Nobody had caught it
before—the sharing had started months ago, and nobody got an
alert. The automated report turned it up immediately. The team
locked it down and did a quick review of similar sites that,
until then, had never been on their radar. Without that
automation, the exposure could have lasted until the next audit,
or longer.That’s the point—manual reviews show you what you look
for, but automation finds what you weren’t expecting. To get
there, though, you need more than just a good script. Scheduling
scripts reliably is where tools like Windows Task Scheduler,
Azure Automation, and Power Automate step in. Task Scheduler is
the classic—it runs scripts on a set schedule from a server or
admin PC, quietly outputting logs or reports. It works for
on-prem scripts, but it won’t cut it for everything—if you lock
your laptop or it reboots for updates, the process can stall.
Azure Automation is purpose-built for cloud environments. You
drop your scripts into a runbook, use managed identities for
secure authentication, and let it run whether anyone’s online or
not. Power Automate is broader—better for hybrid workflows that
trigger scripts based on events, not just the clock.However you
run them, the basics don’t change: credentials are as much a risk
as stale accounts. Hardcoding usernames and passwords into
scripts is asking for trouble—anyone who stumbles on those files
suddenly has the keys to your tenant. The fix is to leverage
secure credential storage. Windows Credential Manager works for
local scheduling, while Azure Automation lets you store secrets
and connect automatically using role-based access, so the script
only does what it’s built to do—nothing more. Secure logging is
next. A script that runs quietly but logs nothing is as bad as a
manual process with no notes. You never want to wonder whether an
alert actually fired or if an action was skipped due to a silent
error. Send errors and key results to a shared mailbox or
Teams—not just to your own inbox—so someone else can pick up the
trail if you’re out.Nobody should trust scripts to make
irreversible changes without a second check. A good automation
process includes logic that flags issues, maybe even disables
accounts or changes permissions, but then awaits explicit admin
approval before deleting or modifying anything critical. Some
admins use a “pending actions” list—sort of like a quarantine—for
scripts to park their findings until someone reviews and
greenlights the action. You stay in control, automation just does
the heavy lifting ahead of time.Testing is where you see who’s
disciplined and who’s winging it. Running scripts on a production
tenant, sight unseen, is asking for chaos. Start in a test tenant
whenever possible or—if you really have no other way—run scripts
in read-only mode first, outputting everything to logs and
reports. Only when you’re confident everything’s mapped right do
you turn on actions that actually change anything.This approach
pays off beyond just saving time. Instead of waking up to a
surprise audit finding, you get regular, actionable reports
pushed to you, and the only major surprises are the ones you
actually want—a sudden drop in dormant accounts, license use
finally matching your real headcount, and project sites no longer
drifting with open doors. But, with all this power, automation
itself can become a new risk vector unless you build for
flexibility and oversight from the start. That leads right into
the next issue: just because you found a great script or template
doesn’t mean it fits your tenant out of the box.
Making Automation Stick: Adapting Scripts for Your Environment
If you’ve been in the Microsoft 365 admin world for longer than a
week, you’ve seen this play out: someone posts a clever script on
Github, or there’s a shared link on a tech blog with the promise
of “full tenant cleanup in five minutes.” You grab it, run it
against your environment, and almost immediately hit a wall—red
error messages you don’t recognize or, worse, changes you can’t
easily undo. One-size-fits-all automation hardly ever fits
anything well. What works perfectly in one tenant ends up missing
the mark—or outright breaking things—in another. It’s easy to
think, “Maybe there’s just something weird about my tenant,” but
the reality is every organization grows its own blend of custom
domains, shadow business units, legacy policies, bureaucracy, and
random user account quirks. Nobody’s setup matches the sanitized
demo from the blog post.Now you’ve got a decision. You found a
script that almost does what you need, but not quite. You tweak
one or two variables, and it sort of runs—but it keeps skipping
half your objects, or worse, doesn’t follow your organization’s
actual compliance rules. This is where the real heavy lifting
starts. If you take the quick route and let that generic script
straight into production, you’re crossing your fingers with every
line it executes. We’ve all seen the nightmare scenario: back
when license cleanup first started trending, a well-meaning admin
at a multi-division company copied a community script to free up
unused licenses. It sorted for accounts with no activity in
ninety days. Looked fine at first glance. But it didn’t account
for service accounts or high-privilege roles that intentionally
have blocked sign-ins. By Monday morning, two key automation
accounts were deactivated mid-workflow, breaking integrations and
quietly halting parts of payroll. No one realized until the
finance team’s batch jobs failed. Suddenly, the cleanup save
turned into a support fire drill.Blindly applying someone else’s
automation rarely goes well because tenant architecture is always
local. Custom domains, extra address book policies, different
business units—these are all variables a generic script can’t
know by default. A proper analysis means mapping out how your
user accounts are linked to departments, which guest users belong
to long-term partners versus one-off vendors, and where legacy
domains might exist solely for authentication or compliance
compatibility. Sometimes, the details are as subtle as filter
syntax: a script that checks for “LastSignInDate” might miss
accounts set up for app-based authentication that never log in
the normal way. Or maybe your organization has custom attributes
for tracking external partners, which never show up in basic
exports unless you explicitly add fields. There’s no universal
template for mapping these quirks without some upfront effort.To
sidestep this misery, flexibility becomes non-negotiable. When
you start building out or adapting scripts, think in terms of
variables and configuration rather than hard-coding anything.
Setting up a config file, even just a simple JSON or CSV, gives
you a central place to manage sensitive inputs—like scoping to
certain departments, user types, or domains—without editing code
every time you make an exception. Modular functions are your
friend here. For example, if your tenant assigns licenses
differently based on region or business unit, break that logic
into small, re-usable blocks. This makes it easy to add
exceptions without breaking the rest of the automation. It also
helps you run dry-runs or “read-only” audits, where the script
compiles a list of findings but makes no actual changes. You see
where the hammer would hit—without risking broken
glass.Microsoft’s best practice advice is straightforward, even
if it’s not always thrilling: start with monitoring and read-only
scripts. “Don’t let your first automated script be the one that
disables users,” as more than one Microsoft MVP likes to say.
Review logs and reports for at least a few cycles—see what would
have tripped or been flagged. Then, once you’re confident nothing
critical lands in the crosshairs, start enabling remediation in
baby steps. Incremental rollouts save careers, not just
downtime.If you want your automation to last—and not become next
year’s legacy mess—treat scripts like real software. That means
version control is not optional; store everything in a central
repo, whether that’s GitHub, Azure DevOps, or even SharePoint
with versioning enabled. Good documentation is more than a
comment at the top with your initials and the date. Outline what
the script does, its required parameters, and note any quirks or
business rules it encodes. Collaboration is the wildcard that
elevates your scripts; sharing draft scripts in a controlled team
review catches both logic flaws and odd one-off exceptions that
would have otherwise gone unnoticed.Over time, this method pays
off in fewer false alarms and safer remediations. There’s nothing
quite like the confidence that comes with automation you
trust—knowing it’s not going to decommission the CFO’s mailbox or
reset the Conference Room’s calendar the day before audit season.
No more guessing if the cleanup actually ran, or if it silently
skipped users you didn’t think to test. Adapted and well-managed
scripts catch the issues that matter, while gracefully
sidestepping everything else.And at the end of the day, all those
adjustments mean automated governance that fits your world, not
just someone else’s. That translates into fewer admin headaches
and a tenant that behaves the way you want it to—so you can get
back to your actual job, or even enjoy a weekend without that
sinking “what did I miss?” feeling. Speaking of benefits, it’s
worth looking at what this all means for your sanity, your time,
and your organization when everything just works.
Conclusion
If you automate governance, you aren’t just clawing back a few
hours—you’re finally fixing the gap between surviving a
compliance audit and running a tenant that doesn’t keep you up at
night. PowerShell scripts don’t care about your vacation plans,
but they do catch what slips through day-to-day checks. When you
build a toolkit that fits your world, you don’t just save
effort—you give yourself more room to breathe during busy weeks.
Start with read-only audits, share what works, and don’t hoard
your scripts. A boring, quiet tenant is the goal—and that’s the
simplest proof your automation is working.
Get full access to M365 Show - Microsoft 365 Digital Workplace
Daily at m365.show/subscribe
Weitere Episoden
22 Minuten
vor 3 Monaten
22 Minuten
vor 3 Monaten
21 Minuten
vor 3 Monaten
22 Minuten
vor 3 Monaten
22 Minuten
vor 3 Monaten
In Podcasts werben
Kommentare (0)