Skip to main content
Apprentice
August 25, 2026
Question

Power Rule - Hyper-V

  • August 25, 2026
  • 1 reply
  • 76 views

I really bought into “If you can do it in powershell, you can run it in a powerrule” but I’m learning it’s really not that easy. What I want to do: If someone runs the “Hyper-V Manager” console, it automatically will add that user to the hyper-v administrators local group in Windows.

I have a script that adds the user to the group, uploaded it, and targeted it with an app group to run, but it doesn’t do anything. I started looking into power rules more (EPM for Windows core scripting | EPM-WM) but quickly realized, it seems like there are special cmdlets you have to use? It’s very confusing.

If anyone can point me in the right direction, I’d really appreaciate it.

1 reply

Guru
August 27, 2026

Hi ​@KD8AVA 

This is using an Audit Script instead.
This should work for you, but there is usually the hurdle that a system would need to be logged off and back on before they get the group membership to Hyper-V Administrators functions.
Here is the script. 

<#
.SYNOPSIS
Adds the currently logged-on domain user to the local "Hyper-V Administrators" group.
.DESCRIPTION
Designed to run in the SYSTEM context (e.g., via SCCM, Intune, or a Scheduled Task).
Detects the interactive logged-on user by finding the owner of the explorer.exe process,
then adds that user to the built-in "Hyper-V Administrators" group.
No user interaction is required and nothing is displayed EPM Not allowed.
No functions are used in this script.
.NOTES
Prerequisite : Must be run as SYSTEM (elevated). The SYSTEM account has rights
#>

# --- Configuration ---
$GroupName = "Hyper-V Administrators"

# --- Run silently � suppress all output to the console ---
$ErrorActionPreference = "SilentlyContinue"
$WarningPreference = "SilentlyContinue"
$VerbosePreference = "SilentlyContinue"
$DebugPreference = "SilentlyContinue"
$ProgressPreference = "SilentlyContinue"

try {
# Step 1: Detect the logged-on domain user via explorer.exe process owner
$explorerProcesses = Get-CimInstance -ClassName Win32_Process -Filter "Name = 'explorer.exe'" -ErrorAction Stop

$loggedOnUser = $null

if (-not $explorerProcesses) {
# No explorer.exe found � no interactive session
exit 0
}

foreach ($proc in $explorerProcesses) {
$ownerInfo = $proc | Invoke-CimMethod -MethodName GetOwner -ErrorAction Stop

if ($ownerInfo.ReturnValue -eq 0 -and $ownerInfo.Domain -and $ownerInfo.User) {
$domainUser = "$($ownerInfo.Domain)\$($ownerInfo.User)"

# Skip machine/system accounts (end with $)
if ($ownerInfo.User -match '\$$') {
continue
}

# Skip the local SYSTEM account explicitly
if ($ownerInfo.User -ieq "SYSTEM") {
continue
}

$loggedOnUser = $domainUser
break
}
}

# Fallback: Try Win32_ComputerSystem if explorer method failed
if (-not $loggedOnUser) {
$cs = Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction SilentlyContinue
if ($cs.UserName) {
$loggedOnUser = $cs.UserName
}
}

# If still no user found, exit gracefully
if (-not $loggedOnUser) {
exit 0
}

# Step 2: Parse domain and username from the detected user string
$parts = $loggedOnUser -split '\\'
if ($parts.Count -ge 2) {
$domain = $parts[0]
$user = $parts[1]
}
elseif ($loggedOnUser -match '@') {
# Handle UPN format (user@domain.com)
$atParts = $loggedOnUser -split '@'
$domain = $atParts[1]
$user = $atParts[0]
}
else {
# Unrecognised format � exit gracefully
exit 0
}

# Skip if the detected user is a machine account
if ($user -match '\$$') {
exit 0
}

# Step 3: Connect to the local group via WinNT ADSI provider
$computerName = $env:COMPUTERNAME
$group = [ADSI]"WinNT://$computerName/$GroupName,group"

if (-not $group.Path) {
# Group does not exist (Hyper-V role may not be installed)
exit 1
}

# Step 4: Check if the user is already a member (idempotent check)
$alreadyMember = $false

$existingMembers = @($group.psbase.Invoke("Members"))

foreach ($member in $existingMembers) {
$adsPath = $member.GetType().InvokeMember("AdsPath", 'GetProperty', $null, $member, $null)
# Normalize: "WinNT://DOMAIN/User" vs "WinNT://DOMAIN/User,user"
$normalizedMember = ($adsPath -replace 'WinNT://', '' -replace ',.*$', '')
$normalizedTarget = "$domain/$user"

if ($normalizedMember -ieq $normalizedTarget) {
$alreadyMember = $true
break
}
}

if ($alreadyMember) {
# Already a member - no action needed, exit successfully
exit 0
}

# Step 5: Add the domain user to the Hyper-V Administrators group
$userAdsPath = "WinNT://$domain/$user"
$group.Add($userAdsPath)

# Exit successfully
exit 0
}
catch {
# Any unexpected error - exit with failure code
exit 1
}

Here is a GIF of how it works.

KR Jens