PIM Tray: Activate Microsoft Entra ID PIM Roles From the Windows Tray

Entra ID PIM activation - PIM Tray Windows tray app

Entra ID PIM activation is a daily ritual for anyone who operates Microsoft Entra ID. If you operate Microsoft Entra ID for a living, you know the dance. Open the portal. Sign in. PIM. My roles. Activate. Type a reason. Pick a duration. Confirm. Repeat for every role, every shift, every customer.

Honestly, I do this on most days. So does every other IT pro I know.

This week, however, I finally decided I was done with it – so I built PIM Tray, a tiny Windows tray app that activates one or more Entra ID PIM roles in a single dialog. It is free, open source under MIT, code-signed, and on GitHub at github.com/ThomasMarcussen/PIMTray.

Entra ID PIM Activation in 30 Seconds: What PIM Tray Does

  • Sits in the Windows system tray as a shield icon.
  • Left-click opens a small window listing every role you are eligible for. Right-click shows the same list as a context menu, plus sign-in / sign-out / about.
  • Tick one or more roles, hit Activate, type a reason, pick a duration, done.
  • A single Windows toast tells you which roles activated, which are pending approval, and which failed – so partial success is obvious instead of buried.

That is essentially the whole pitch. In short: no browser, no tab switching, no clicking through six blades to find the same form you used twenty minutes ago.

Why I Built an Entra ID PIM Activation Tool

First, I tried the obvious alternatives.

  • The Entra portal is the canonical UX. It is fine for one role, painful for three, exhausting for ten.
  • Microsoft.Graph PowerShell with a snippet works, but I do not want to keep a terminal open for a 3 second action, and reason prompts in a shell are friction.
  • Microsoft Authenticator and WAM do not do PIM activation.
  • A couple of community tools exist, but none were code-signed, none batched, and one of them shipped its own browser.

In the end, what I actually wanted was a tool that lived where my other always-on tools live – the notification area – and respected the fact that admins activate roles in clusters, not one at a time.

Therefore I built PIM Tray, a small tool that turns Entra ID PIM activation into a one-click workflow that lives in the Windows tray.

How Entra ID PIM Activation Works in PIM Tray

In particular, there are three moving parts: authentication, discovery, and activation.

Authentication: MSAL Interactive Sign-In

PIM Tray uses MSAL (Microsoft.Identity.Client) as a public client. The default system browser pops, you complete MFA and Conditional Access the proper way, and the token is cached encrypted to disk at %LOCALAPPDATA%\PIMTray\msal_cache.bin via DPAPI. As a result, subsequent launches go silent until the refresh token expires.

Importantly, no password is ever typed into the app, and there is no embedded browser or token-stealing surface area.

Role Discovery: One Microsoft Graph Call

After sign-in, PIM Tray queries Microsoft Graph for every PIM role you are eligible for, with the scope expanded:

GET https://graph.microsoft.com/v1.0/roleManagement/directory/roleEligibilitySchedules
    ?$filter=principalId eq '<your object id>'
    &$expand=roleDefinition

As a result, every eligible role shows up in the list automatically, with its display name and scope (Directory or a resource path). There is no config file of role IDs to maintain.

Activation: One POST Per Checked Role

Then, for each role you tick, PIM Tray posts a self-activation request:

POST https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignmentScheduleRequests
Content-Type: application/json

{
  "action": "selfActivate",
  "principalId": "<user object id>",
  "roleDefinitionId": "<role id>",
  "directoryScopeId": "/",
  "justification": "Friday change window, ticket INC0001234",
  "scheduleInfo": {
    "startDateTime": "2026-05-12T07:30:00Z",
    "expiration": { "type": "AfterDuration", "duration": "PT4H" }
  }
}

Notably, errors surface verbatim from Graph. If your role policy requires approval, the request is created in pending state and the tray balloon says so. If the policy requires ticket info that the form does not capture, the call fails clearly. No magic, no silent retries, no surprises.

Under the hood, the whole app is .NET 9 WinForms. In total, the signed exe is about 1.3 MB, while the MSI installer is under 500 KB.

Entra ID PIM Activation: The Permissions Question

PIM Tray needs three delegated Microsoft Graph scopes:

  • RoleEligibilitySchedule.Read.Directory
  • RoleAssignmentSchedule.ReadWrite.Directory
  • User.Read

Specifically, there are two practical ways to satisfy them:

  1. Use the bundled default ClientId – the public Microsoft Graph PowerShell first-party app. The first sign-in shows the standard consent prompt. A Global Administrator can pre-consent at tenant level so end users never see the prompt again. Zero setup, but tenant-wide consent to a Microsoft-published app is heavier than some security teams want.
  2. Register your own Entra ID app. New registration, mobile and desktop platform, redirect URI http://localhost, the three delegated scopes above, admin consent granted once. Paste the resulting TenantId and ClientId into appsettings.json (auto-created at %APPDATA%\PIMTray\ on first run). Cleaner long-term, especially if you ship the tool to other admins in your tenant.

In addition, both paths are documented in the README. For personal use, option 1 is two clicks away.

Install

PIMTray.msi  ->  C:\Program Files\PIM Tray\PIMTray.exe

To get started, download the signed MSI from the v1.0.0 release. The MSI is signed with our EV certificate (DigiCert, with RFC 3161 timestamp) so SmartScreen and Microsoft Defender treat it normally and Add/Remove Programs shows a real publisher instead of Unknown.

Requirements:

  • Windows 10 or 11 (x64)
  • .NET 9 Windows Desktop Runtime on the target machine
  • At least one eligible PIM role on your signed-in account

Alternatively, to build from source, clone the repo and run dotnet publish -c Release -r win-x64 --self-contained false -p:PublishSingleFile=true. The exe lands in bin\Release\net9.0-windows\win-x64\publish\.

Frequently Asked Questions

Does PIM Tray support PIM for Groups?

Not in v1.0.0. The current release covers Entra ID directory roles via roleManagement/directory. Group-membership activations (identityGovernance/privilegedAccess/group/) are on the roadmap.

Does PIM Tray support Azure resource PIM (subscriptions, resource groups)?

Not yet. Azure RBAC PIM goes through roleManagement/rbacApplications and needs a different scope ID model. Tracking it as a roadmap item.

Does PIM Tray work with Conditional Access policies that require MFA on PIM?

Yes. In fact, authentication is interactive through MSAL using the system browser, which inherits all your Conditional Access policies, MFA prompts, and even Windows Hello / passkey flows. If your policy requires reauth for PIM, you get the standard Microsoft challenge.

Where is the token stored?

%LOCALAPPDATA%\PIMTray\msal_cache.bin, encrypted with DPAPI scoped to the current Windows user. The token never leaves your machine.

Is PIM Tray code-signed?

Yes. Both PIMTray.exe and PIMTray.msi are signed with an EV code-signing certificate from DigiCert and timestamped via RFC 3161, so the signature stays valid past certificate expiry.

Is PIM Tray open source?

Yes, MIT licensed. Source, issues and pull requests at github.com/ThomasMarcussen/PIMTray.

What is Next

The roadmap on the repo is short and honest:

  • PIM for Groups (group-membership activations)
  • Azure Resource PIM (subscription / resource group scopes)
  • Approval-pending polling so you do not have to refresh manually
  • Start at logon toggle in the About dialog
  • Optional dark mode

Finally, if you use PIM Tray and it shaves five minutes off your week, that is a win for both of us. Issues and PRs welcome.

Try It

If PIM Tray fits your Entra ID PIM activation routine and you build something on top of it, ping me. I would like to hear what other patterns admins want to automate next.


Thomas Marcussen is a Microsoft MVP and Technology Architect. More notes and tools at thomasmarcussen.com.

How to Remove Classic Microsoft Teams with PowerShell and Intune Proactive Remediations

Microsoft officially retired Classic Teams on July 1, 2025, and the client is no longer functional. Despite this, many organizations still have remnants of Classic Teams scattered across their Windows device estate. This is not just a cosmetic issue. Classic Teams no longer receives security updates, the per-user installation model wastes disk space, leftover shortcuts confuse users, and end-of-life software can put you out of compliance. If you have been putting off the cleanup, now is the time to remove Classic Teams from your environment.

In this post I am sharing three PowerShell scripts that handle different scenarios, from a one-off standalone removal to a fully automated Intune Proactive Remediations approach.

Why You Need to Remove Classic Teams

Even though Classic Teams stopped working months ago, there are real reasons to actively remove it rather than just leaving it behind:

  • Security – Classic Teams no longer receives security updates, leaving a potential attack surface on your endpoints
  • Disk space – The per-user installation model means Classic Teams can consume hundreds of megabytes per user profile on a device
  • User confusion – Leftover shortcuts and autorun entries can confuse users, especially when New Teams is already deployed
  • Compliance – Many organizations have policies requiring the removal of end-of-life software from managed devices
  • Clean device state – Leftover registry entries and autorun configurations can interfere with New Teams or cause unexpected behavior

What Gets Removed

All three scripts target the same Classic Teams components:

  • Teams Machine-Wide Installer – The MSI-based installer typically deployed via SCCM, GPO, or during OS deployment
  • Per-user Teams installations – Classic Teams installed itself per-user under %LocalAppData%\Microsoft\Teams for each profile on the device
  • Autorun registry entries – Both HKLM and per-user Run keys that launch Classic Teams at logon
  • Desktop and Start Menu shortcuts – Leftover .lnk files pointing to the old Teams client
  • Teams Installer folder – The C:\Program Files (x86)\Teams Installer directory

Option 1: Remove Classic Teams with a Standalone Script

If you need to remove Classic Teams from a smaller number of devices, or want to run the cleanup through SCCM, ConfigMgr, GPO, or manually, use the standalone removal script. It handles the complete removal process in a single run: stops Teams processes, uninstalls the Machine-Wide Installer via msiexec, iterates through all user profiles to remove per-user installations, cleans up registry entries and shortcuts, and validates the result.

Script: Remove-ClassicTeams.ps1

Usage

Run the script as SYSTEM or with local administrator privileges:

powershell.exe -ExecutionPolicy Bypass -File Remove-ClassicTeams.ps1

The script creates a log file at C:\Windows\Logs\Remove-ClassicTeams.log for troubleshooting.

Option 2: Remove Classic Teams with Intune Proactive Remediations

For organizations managing devices through Microsoft Intune, the preferred approach is to use Proactive Remediations (now called Remediations in the Intune admin center). This gives you a detection script that identifies non-compliant devices and a remediation script that automatically cleans them up.

Detection Script

The detection script checks whether you still need to remove Classic Teams by scanning all common locations. If any remnant is found, it exits with code 1 (non-compliant), which triggers the remediation script. If the device is clean, it exits with code 0 (compliant).

Script: Detect-ClassicTeams.ps1

The detection checks include:

  • Teams Machine-Wide Installer in both 32-bit and 64-bit uninstall registry keys
  • Classic Teams folder, Teams.exe, and Update.exe in each user profile
  • Teams desktop shortcuts across all profiles
  • HKLM Run entry for Teams

Remediation Script

When the detection script flags a device as non-compliant, the remediation script will remove Classic Teams and perform the full cleanup. It goes further than the standalone script by also cleaning Start Menu and Startup folder shortcuts, loading offline user registry hives to remove per-user Run entries, and removing the Teams Installer folder from Program Files.

Script: Remediate-ClassicTeams.ps1

After remediation, the script runs its own validation. If all remnants are successfully removed, it exits with code 0. If anything remains, it exits with code 1, which Intune will flag for review.

Setting Up the Proactive Remediation in Intune

  1. In the Intune admin center, navigate to Devices > Remediations
  2. Click Create script package
  3. Give it a name, for example: Remove Classic Microsoft Teams
  4. Upload Detect-ClassicTeams.ps1 as the detection script
  5. Upload Remediate-ClassicTeams.ps1 as the remediation script
  6. Set Run this script using the logged-on credentials to No (runs as SYSTEM)
  7. Set Run script in 64-bit PowerShell to Yes
  8. Assign the remediation to a device group – start with a pilot group before targeting all devices
  9. Set the schedule – daily is recommended until the bulk of devices are cleaned up, then reduce to weekly

Logging

All three scripts write detailed logs to C:\Windows\Logs:

  • Remove-ClassicTeams.log
  • Detect-ClassicTeams.log
  • Remediate-ClassicTeams.log

Each log entry includes a timestamp, severity level (INFO, WARN, ERROR), and a descriptive message, making it easy to verify that the scripts successfully remove Classic Teams. This makes it straightforward to troubleshoot any issues through Intune device diagnostics or by reviewing the log files directly.

Summary: Remove Classic Teams the Right Way

Cleaning up Classic Microsoft Teams is a necessary task for any organization that has migrated to New Teams. Whether you run the standalone script through your existing deployment tools or leverage Intune Proactive Remediations for automated, ongoing compliance, these scripts give you a reliable way to get it done.

All scripts are available on my GitHub:

If you have questions or run into issues, feel free to reach out.

Fix Microsoft Teams Dial Pad Not Working

If you’ve ever had a user say:

“The dial pad is there, but I can’t click it.”
“Join meeting does nothing.”
“Teams opens, but it’s just broken.”

You already know what’s coming.

And no – it’s usually not licensing.

In many cases, it’s a corrupted local Teams client.

In this article, I’ll show you:

  • Why Microsoft Teams breaks like this
  • Which common error codes this reset resolves
  • When the issue is client-side vs policy-side
  • And a full PowerShell script to fix it properly

The Real Problem: Teams Is a Web App in Disguise

Microsoft Teams (especially New Teams) is essentially:

  • WebView2
  • Cached profile data
  • AAD token storage
  • Local state
  • MSIX container

When something corrupts:

  • WebView2 rendering
  • Authentication tokens
  • Local Teams cache
  • SSO credentials
  • Proxy configuration

The result is classic:

  • Dial pad visible but not clickable
  • Join meeting button does nothing
  • Blank white screen
  • Endless loading spinner
  • Random sign-in prompts

Common Microsoft Teams Error Codes This Script Fixes

This reset script resolves a large number of client-side errors, including:

Authentication Errors

  • CAA50021
  • CAA50024
  • CAA20002
  • 0xCAA70004
  • 0xCAA82EE2
  • 0x80048823
  • 0x800704CF

Meeting Join / UI Errors

  • Join button unresponsive
  • Dial pad not clickable
  • Blank calendar view
  • “We couldn’t connect you” error
  • “Something went wrong” generic UI errors

WebView2 / Rendering Issues

  • White screen on launch
  • UI elements missing
  • Buttons visible but not interactive
  • 0x80072EFD
  • 0x80072EE7
  • 0x801901F7

If Teams Web works but the desktop client does not -> this script is almost always the fix.

When This Script Will NOT Help

If the dial pad is greyed out, the problem is not the client.

It’s usually:

  • No Teams Phone license
  • No OnlineVoiceRoutingPolicy
  • No Calling Policy
  • Enterprise Voice not enabled

Client reset won’t fix licensing.

Clickable but broken = client
Greyed out = policy

Important distinction.

What the Script Actually Does

This is not just a “delete cache” script.

It performs a full user-context reset:

  1. Stops all Teams-related processes
  2. Removes Classic Teams folders
  3. Removes New Teams MSIX profile folders
  4. Clears WebView2 cache
  5. Optionally removes stored AAD/Office credentials
  6. Optionally resets WinHTTP proxy
  7. Relaunches Teams cleanly

It does NOT:

  • Uninstall Teams
  • Change licensing
  • Affect other users
  • Modify tenant configuration

Safe for enterprise usage.

Reset-TeamsClient.ps1 – https://github.com/ThomasMarcussen/assortedScripts/blob/master/Reset-TeamsClient.ps1

New Release: Full OneDrive Shortcut Support, Smarter Downloads, and Enhanced Reporting for Download-OD4BAccount.ps1

The Download-OD4BAccount.ps1 script just got another major update – and this one takes it to a whole new level.

Following the September refresh that added full pagination and improved reliability for large OneDrive libraries, this new release focuses on smarter downloads, better handling of OneDrive “shortcuts,” and a cleaner, dependency-free approach to working with the Microsoft Graph API.

And once again – a big thank-you to Gary Chamryk and others in the community for their real-world feedback, testing, and suggestions that made this update possible.

Why Another Update?

After the last version went live, several users (including Gary) noticed edge cases where certain file types or OneDrive “shortcut” folders didn’t export correctly.

Digging into the logs revealed that the Microsoft Graph PowerShell SDK’s @microsoft.graph.downloadUrl property can occasionally fail or behave inconsistently when handling shortcuts to remote drives or shared folders.

That’s where this new iteration comes in – with a cleaner, more reliable download engine built entirely on direct /content requests via the Graph API.
The script now uses:
Invoke-MgGraphRequest -OutputFilePath

to stream file content directly from Graph to disk – no longer relying on @microsoft.graph.downloadUrl.
This eliminates transient URL expiration issues and improves consistency across large multi-user exports.

Full OneDrive Shortcut (remoteItem) Support

OneDrive “shortcuts” (also known as remoteItems) are now fully supported.
The script automatically follows the referenced driveId and itemId, so both files and folders linked from other OneDrives or SharePoint document libraries are downloaded seamlessly.

Paths That Match the Real OneDrive View

Exported folder structures now reflect the actual visible OneDrive hierarchy, including shortcut names.
That means what you see in your OneDrive web UI is exactly what you’ll get on disk — no more confusing “shortcut_12345” placeholders.

Multi-Threaded Downloads, Inside Worker Runspaces

The existing multi-threaded model remains, but now imports the Microsoft Graph authentication module inside each worker runspace.
This ensures every parallel job runs independently with full Graph context, even in long-running sessions or constrained environments.

Original CSV Reports Intact

Reporting hasn’t changed – the familiar CSV export for file listings and results is preserved, ensuring backward compatibility for scripts or processes that rely on it.

Quick Start

The syntax remains simple and consistent:

.\Download-OD4BAccount.ps1 -Username [email protected] `
                           -Destination "D:\OD4B" `
                           -ThreadCount 3 -Verbose

he script still requires Microsoft Graph PowerShell and admin consent for:

  • Organization.Read.All
  • User.Read.All
  • Directory.Read.All
  • Files.Read.All

When to Use This Version

  • Offboarding or Archival – Export full OneDrive content (including shared shortcuts) for departing users.
  • Legal or Compliance Holds – Capture exact user views of OneDrive, including remote shared content.
  • Tenant-to-Tenant Migrations – Seamlessly move data structures between organizations without breaking links.

Community-Driven Evolution

This update wouldn’t exist without direct input from the field.
Gary Chamryk and others in the community helped identify the gaps, test fixes, and validate the new approach.

The best part of open tooling is that it keeps evolving with real-world usage — and this release is proof of that.

Get the Latest Version

🔗 Download the updated script: Download-OD4BAccount.ps1
(available on the same GitHub repository as before)

If you’re already using the script, I strongly recommend upgrading – especially if you’re exporting libraries that include OneDrive shortcuts or shared content.

As always, feedback and PRs are welcome. These scripts only get better because of the community behind them.

New and Improved: Download All OneDrive Files for a User with PowerShell – Updated Script


Back in early 2023 I published a post:
PowerShell script to download a user’s OneDrive content

That original script – Download-OD4BAccount.ps1 – quickly became one of my go-to tools for off-boarding and archiving user data. It let administrators export an entire OneDrive for Business library directly to on-premises storage without paying Microsoft to keep the data around.

Since then, the script has seen heavy real-world usage, and thanks to some great community feedback it just got a serious upgrade.

Why the Update

A reader recently reached out after running the script against a very large OneDrive.
They noticed that not every file was exported.

After some digging, we discovered the root cause:

  • The Microsoft Graph PowerShell cmdlets Get-MgUserDriveRootChild and Get-MgUserDriveItemChild now page their results by default.
  • Without explicit pagination, large folders could quietly drop files from the export.

This was a subtle but critical issue – your export might look fine at first glance, but some files would never make it to disk.

What’s New in the Updated Script

The refreshed script keeps the original simplicity and speed but addresses these limitations and more.

– Full Pagination Support

Both Get-MgUserDriveRootChild and Get-MgUserDriveItemChild now run with the -All switch, ensuring every item – even in massive libraries – is fetched.

– Reliable Folder Traversal

Recursive folder expansion now preserves the full path, so deep folder hierarchies are exported exactly as they appear in OneDrive.

– Broader Microsoft Graph Scopes

The connection now requests:

Files.Read.All, User.Read.All, Directory.Read.All

These scopes ensure cross-user OneDrive exports work reliably across tenants and admin scenarios.

– Cleaner Reports

Removed an undefined $Job field from the file report, preventing runtime errors.

– More Robust Downloads

The script now checks and creates destination directories before writing each file, so missing folder paths won’t break the download process.

– Improved Batching and Multi-Threading

Thread batching logic is more resilient when splitting large file lists, while keeping the same multi-threaded performance boost that made the original so fast.

Quick Start

The usage remains the same:

.\Download-OD4BAccount.ps1 -Username [email protected] `
                           -Destination "D:\OD4B" `
                           -ThreadCount 3 -Verbose

Prerequisites

  1. Microsoft Graph PowerShell Module (the script will auto-install if missing).
  2. Azure AD user with admin consent to approve:
    • Organization.Read.All
    • User.Read.All
    • Directory.Read.All
    • Files.Read.All (new requirement)

When to Use This Script

Off-boarding – export a departing employee’s OneDrive to a secure archive before disabling their account.

  • Legal hold or compliance – capture a one-to-one copy of a user’s OneDrive library for audit purposes.
  • Bulk migration scenarios – move large OneDrive libraries to on-prem or a different tenant without relying on paid retention.

Community-Driven Improvement

This update wouldn’t have happened without feedback from the community.
Real-world use exposed a change in the Microsoft Graph SDK behaviour, and the fix – adding -All – was simple but critical.

If you’ve used the original version, I highly recommend updating your copy with the new script to guarantee complete and reliable exports.

Download the updated script: Download-OD4BAccount.ps1

Feel free to share feedback or improvements. Real-world input keeps these tools evolving and useful for everyone.

Script to configure Azure AD Cloud Kerberos Trust

As businesses increasingly operate in hybrid environments spanning both on-premises and cloud infrastructure, the need for seamless authentication across multiple environments becomes paramount. To address this challenge, organizations are turning to automated processes for implementing and managing Cloud Kerberos Trust. This automated approach streamlines the integration of Kerberos-based authentication in diverse environments, ensuring efficient and secure access to cloud resources.

The PowerShell script Enable-CloudKerberosTrust.ps1 simplifies and automates the process of Configuring Azure AD Cloud Kerberos Trust.

To get a deeper understanding and a great story, You should also read to following article series by Ben Whitemore and Michael Mardahl who inspired the script.

1. Install Azure AD Kerberos PowerShell module
2. Prompt the user for domain admin credentials (if it detects it is not running as domain admin)
3. Create a Kerberos Server object
4. Verify a Kerberos Server object has been created successfully
5. Create "CKT-Policy" Intune configuration profile 
6. Create OMA-URI for Cloud Kerberos Trust enablement
7. Assign the configuration profile
1. Azure Active Directory global administrator.

2. Active Directory domain administrator.

3. Approve admin consent for the following permissions in Microsoft Graph application in Azure AD apps:
CloudPC.ReadWrite.All, DeviceManagementConfiguration.ReadWrite.All, DeviceManagementManagedDevices.ReadWrite.All, Directory.Read.All
.PARAMETER Domain
Specifies the on-premises Active Directory domain. A new Azure AD Kerberos Server object will be created in this Active Directory domain.
.PARAMETER UserName
Specifies the UPN of an Azure Active Directory global administrator.
.PARAMETER TenantID
Specifies the Azure AD tenant ID for the new Intune configuration policy.
.PARAMETER Group
Specifies the device group to assign the new Intune configuration policy.
.PARAMETER LogPath
Specifies path to save script output to.
.EXAMPLE
.\Enable-CloudKerberosTrust.ps1 -Domain xyz.com -UserName [email protected] -TenantID 0570e92c-8fb4-4775-9eb8-61f20dd2ce72 -Group Group1 -LogPath .\

Download the script: Enable-CloudKerberosTrust.ps1

NOTE: THIS SCRIPT IS CONTINUALLY BEING IMPROVED – If you would like to suggest additional checks or improvements, feel free to reach out with your input.

Introducing a New Script to Check Autopilot Prerequisites

Autopilot is an essential tool for managing and deploying Windows devices in the enterprise. However, before deploying Autopilot, it’s important to ensure that your environment meets the necessary prerequisites. This can be a time-consuming and error-prone process, which is why we’re excited to introduce a new script that automates the prerequisite checking process.

The new script, called Autopilot Prerequisite Checker, is a PowerShell script that checks whether your environment meets the prerequisites for deploying Autopilot. The script checks for the following prerequisites:

Tenant checks:

  • Check license requirements
  • Automatic Windows enrollment (MDM authority is set)
  • DNS records
  • Check user can join device to Azure AD
  • Check Enrollment Status Page
  • Check Windows Autopilot Deployment Profile
  • Check company branding

Device checks:

  • Windows OS version
  • Hardware hash uploaded to Intune
  • Check Windows Autopilot Deployment Profile assignment status

User checks:

  • User is licensed correctly

Network checks:

  • Required communication for Intune Autopilot is allowed

The script is easy to use and can be run on any machine with PowerShell installed. Simply download the script, run it, and wait for the results. The script will output indicating whether your environment meets the necessary prerequisites for Autopilot.

Download the script

The benefits of using the script are numerous. First and foremost, it saves time by automating the prerequisite checking process, allowing you to focus on more important tasks. Second, it reduces the risk of errors, ensuring that your Autopilot deployment is successful the first time. Finally, it provides peace of mind by giving you the confidence that your environment meets the necessary requirements for deploying Autopilot.

In conclusion, Autopilot Prerequisite Checker is a powerful new script that simplifies the process of checking the prerequisites for deploying Autopilot. Whether you’re an IT administrator or a consultant, Autopilot Prerequisite Checker is an essential tool for ensuring the success of your Autopilot deployment.


NOTE: THIS IS A WORK IN PROGRESS – If would like me to add a check, just ping me the info 🙂

Download all OneDrive files for a user using PowerShell

Powershell script to download a users OneDrive content.

New and improved: Download-OD4BAccount.ps1

.Example 
.\Download-OD4BAccount.ps1 -Username [email protected] -Destination "D:\OD4B" -ThreadCount 3 -Verbose

Script prerequisites:

1. Microsoft Graph PowerShell Module installed on local machine. The script automatically checks for and installs module if needed.

2. An Azure AD user that has an admin consent to approve the following permissions in Microsoft Graph application in Azure AD apps:
   Organization.Read.All, User.Read.All, Directory.Read.All

This was inspired by Adnan's script, which i have used on multiple occasions.
But when downloading very large OneDrive data structures, Multi-Threads seems to work faster and smoother.
 

Microsoft Intune – New Updates in PowerShell Scripts

Microsoft Intune is one of those brilliant products that has helped to optimize IT infrastructure for many businesses. It’s a platform that can transform your business into a modern workplace. And its capabilities are almost without limit. If you want to upload PowerShell scripts in Intune, there is the Microsoft Intune management extension (IME) that you can use for that. This management extension can enhance Mobile Device Management (MDM) resulting in a simpler move to modern management. With all this done, you can then run these scripts on Windows 10 devices. PowerShell scripts are important in a lot of different use cases and this blog is going to take a look at what this technology can do.

What is PowerShell?

PowerShell is a scripting and automation platform belonging to Microsoft. It’s an amazing product that is both a scripting language as well as an interactive command environment that is built on the .NET framework. Released back in 2006, PowerShell was basically a replacement for Command Prompt as the default method for automation of batch processes and creation of customized system management tools. PowerShell can easily automate laborious admin tasks by combining commands known as cmdlets and creating scripts. Available in all Windows OS starting with Windows 2008R2, PowerShell plays a huge role in helping IT professionals configure systems.

Adopting modern management

Modern workplaces now have plenty of user and business-owned platforms allowing users to work from anywhere. With MDM services like Microsoft Intune, you can manage devices that are running Windows 10. The Windows 10 management client will communicate with Intune to run enterprise management tasks. Windows 10 MDM features will be supplemented by IME. With this in place, you can create PowerShell scripts to run on Windows 10 devices e.g, creating a PowerShell script that does advanced device configurations. Having done this, you can upload the script to Intune and assign the script to an Azure AD group. Then run the script. Moreover, you can monitor the run status of the script from start to finish.

Latest updates from Microsoft

In November 2020, Microsoft announced the general availability of PowerShell 7.1 which is built on the foundation of PowerShell 7.0. The goal was to bring about improvements and fixes to the existing technology. Some of these features, updates, and breaking changes include:

  • PSReadLine 2.1.0, including Predictive IntelliSense
  • PowerShell 7.1 has been published to the Microsoft Store
  • Installer packages have been updated for new operating system versions with support for ARM64
  • 4 new experimental features and 2 experimental features promoted to mainstream
  • A number of breaking changes that improve usability

Using scripts in Intune

Before IME can automatically install, when a PowerShell script or a Win32 app is assigned to the device or user, a few prerequisites should be met:

  • Windows 10 version 1607 or later, Windows 10 version 1709 or later for devices enrolled using bulk auto-enrollment.
  • Devices joined to Azure AD including Hybrid Azure AD-joined which consists of devices that are joined to Azure AD, and are also joined to on-premises Active Directory (AD).
  • Devices enrolled in Intune namely devices enrolled in a group policy, devices that are manually enrolled in Intune, and co-managed devices that use both Configuration Manager and Intune.

Script policy creation

Start by signing in to the Microsoft Endpoint Manager admin center. From there you’ll select Devices then PowerShell scripts then add. Under Basics, you will then have to provide a name and a description for the PowerShell script. Next, you go to Script settings and you’ll have to enter the required properties. After that, you select Scope tags, however, these are optional. And then select Assignments > Select groups to include and an existing list of Azure AD groups will be shown. Lastly, in Review + add, you’ll see a summary of the settings you configured. Select Add to save the script. When you have done so, the policy is deployed to the groups you chose.

Important considerations

If you have scripts that are set to user context with the end-user having admin rights, by default, the PowerShell script runs under the administrator privilege. Also, end-users don’t need to sign in to the device to execute PowerShell scripts. The IME agent checks with Intune once per hour and after every reboot for any new scripts or changes. In the event of a script failing, the agent attempts to retry the script three times for the next 3 consecutive IME agent check-ins. And as far as shared devices are concerned, the PowerShell script runs for every new user that signs in.

PowerShell scripts limitations

Although with Microsoft Intune you can deploy PowerShell scripts to Windows 10 devices, there are a few limitations worth noting. These include: 

  • You won’t get support for running PowerShell scripts on a scheduled basis.
  • Although you can see whether the PowerShell script execution succeeded or failed, the output generated is only available on the endpoint that executes it and is not returned to the MEM Admin Portal.
  • Since executed PowerShell scripts are visible in the Intune Management Extension log file as plain text, credentials can’t be passed securely.
  • The Intune Management Extension agent responsible for executing PowerShell scripts on the endpoints only checks once an hour for new scripts so there is a delay with execution.

Wrap up about Microsoft Intune

Maximizing the time we have is increasingly a massive concern for most organizations. Technological innovation has made it such that we can have more productive time on our hands. PowerShell is a product that is very useful to IT professionals for overall system management. By being able to automate the administration of Windows OS and other applications, organizations can operate more efficiently. The evolution of this platform since its release fourteen years ago has seen it grow from strength to strength. Undoubtedly, this is a product that can easily boost your productivity.        

List Packages that run in user context (Run with user’s rights)

Introduction

After last weeks post with the script sample to list Packages that run in user context, there where some good feedback from people still using packages, and requiring a list of packages that install within the user context (Run with user’s rights / Execution mode as user)

It seemed that many was still using Packages, either as a result of legacy migration or to avoid some application re-packaging.

So here is the followup post, with a new script to list all packages and package with programs that run in user context.

From my point of view, its still the same; Using PSADT pretty much any package can be converted to be installed as system, and the needed stuff (registry keys, files etc) in the user context can be added in a structured and controlled way.

I do still come across some applications that i would prefer to have in MSI with all settings etc added, at least for simplicity, for those packages I still prefer to use Advanced Installer.
When talking Advanced Installer, they also have a great support for MSIX, that makes to process so much easier and cost efficient.

This script will list all packages with programs, that is configured to install as user (within the user context)

All you need to do is configure the path to your import module and set the site code.

A file will be created in “C:\TEMP\Packages_and_Programs_Run_Mode_List.csv” with the following format:

“Package Name”,”Package ID”,”Program Name”,”Run with USER’s right”
“My Application”,”BB10001D”,”execute”,”TRUE

With the example above we have a package ‘My Application’ that has a run mode configured: Run with user’s rights

Properties on the program, where the program run enviroment is configured to Run with Users’s rights


Download the script from TechNet Galleryhttps://gallery.technet.microsoft.com/Generate-a-list-of-d8778d4c?redir=0