Skip to main content
Apprentice
August 25, 2026
Question

Power Rule - Hyper-V

  • August 25, 2026
  • 3 replies
  • 130 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.

3 replies

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

Paul
BeyondTrust Employee
BeyondTrust Employee
September 17, 2026

Perhaps a bit late - but what problem were you trying to solve with the script? Is it because the user needs to be a member of the group to use the Hyper-V snap-in?

If that’s the case, using a custom token to inject that Hyper-V group membership when that specific snap-in is loaded, is a more dynamic and product native way to achieve the same outcome. 

Obviously if you need to populate the group for another scenario, such as remove connections, this may not be the appropriate solution, but I wanted to offer it  just in case.

Guru
September 17, 2026

Spot on, just the group membership to my knowledge.

This can be done in many ways, GPO/Intune policy would be the preferred way of doing it.
WMI query for the service, if the Services are there add the logged on user to Hyper-V Administrators group.

​@Paul  suggestion would be to configure a custom token  like this one:

This would provide the membership when the Snap-in is launched only.

Plausible solution, but I think I recall some issues with functionality on Hyper-V using this method. similar to adding your self to the Administrators Group, it does not grant you full permissions until you log off and back on, while being a member of the group.

It’s worth a try.

Jens