User-Context Detection Rules for Intune Win32 Apps

Today I had to create a Win32 app in Intune that sets a registry key in the current user context to toggle a setting in the OS. Somehow I thought I’d have it done in a jiffy, but I stumbled on a couple of unexpected issues along the way….

First, as the app simply runs a PowerShell script that sets the registry key, the install command I was using created the key in the WOW6432node because the IME runs as a 32-bit app. So I had to change the command to use SysNative:

%windir%\SysNative\WindowsPowershell\v1.0\PowerShell.exe -ExecutionPolicy Bypass -File MyInstallScript.ps1

Second, the app is only applicable to Windows 11 yet in the Minimum operating system requirement, Windows 11 is not available, nor even is Windows 10 21H2. I guess that’ll get updated at some point…

So I had to choose a Windows 10 OS and add an additional scripted requirement rule for Windows 11:

[int]$BuildNumber = Get-CimInstance Win32_OperatingSystem -Property BuildNumber | Select -ExpandProperty BuildNumber
If ($BuildNumber -ge 22000)
{
    Write-Output "Pass"
}
else
{
    Write-Output "Fail"
}

Next came a more tricky problem – the detection rule. This had to done using a custom detection script, but the script runs in SYSTEM context so by default it can’t detect changes in the logged-on user registry hive.

I recalled some code I had used elsewhere to detect the current logged on user in SYSTEM context and simply modified the detection script to check the HKEY_Users hive instead of HKEY_CURRENT_USER hive based on the SID of the logged on user. This works as long as only a single user is logged in:

Function Get-LoggedOnUserSID {
    # ref https://www.reddit.com/r/PowerShell/comments/7coamf/query_no_user_exists_for/
    $header=@('SESSIONNAME', 'USERNAME', 'ID', 'STATE', 'TYPE', 'DEVICE')
    $Sessions = query session
    [array]$ActiveSessions = $Sessions | Select -Skip 1 | Where {$_ -match "Active"}
    If ($ActiveSessions.Count -ge 1)
    {
        $LoggedOnUsers = @()
        $indexes = $header | ForEach-Object {($Sessions[0]).IndexOf(" $_")}        
        for($row=0; $row -lt $ActiveSessions.Count; $row++)
        {
            $obj=New-Object psobject
            for($i=0; $i -lt $header.Count; $i++)
            {
                $begin=$indexes[$i]
                $end=if($i -lt $header.Count-1) {$indexes[$i+1]} else {$ActiveSessions[$row].length}
                $obj | Add-Member NoteProperty $header[$i] ($ActiveSessions[$row].substring($begin, $end-$begin)).trim()
            }
            $LoggedOnUsers += $obj
        }

        $LoggedOnUser = $LoggedOnUsers[0]
        $LoggedOnUserSID = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\SessionData\$($LoggedOnUser.ID)" -Name LoggedOnUserSID -ErrorAction SilentlyContinue |
            Select -ExpandProperty LoggedOnUserSID
        Return $LoggedOnUserSID
    } 
}

$LoggedOnUserSID = Get-LoggedOnUserSID

If ($null -ne $LoggedOnUserSID)
{
    If ($null -eq (Get-PSDrive -Name HKU -ErrorAction SilentlyContinue))
    {
        $null = New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS
    }
    $i = Get-Item "HKU:\$LoggedOnUserSID\Software\<regkey>" -ErrorAction SilentlyContinue
    if ($null -eq $i)
    {
        # key doesn't exist, need to set
        "nada"
        Exit 1
    }
    else 
    {
        $r = Get-ItemProperty "HKU:\$LoggedOnUserSID\Software\<regkey>" -Name '(Default)' -ErrorAction SilentlyContinue | 
            Select -ExpandProperty '(default)' 
        If ($r.Length -gt 0)
        {
            # default key is not correct value, need to update    
            "not right value"
            Exit 1
        }
        else 
        {
            # all good
            "all good" 
            Exit 0   
        }
    }
}
Else
{
    # no logged on user detected
    "no logged on user detected"
    Exit 1
}

After that, finally the app installed and detected correctly!

4 thoughts on “User-Context Detection Rules for Intune Win32 Apps

  1. this is sick, i had to slightly adjust it, so it runs on a German OS:

    Function Get-LoggedOnUserSID {

        # Define the expected column headers based on localized output

        $header = @(‘SITZUNGSNAME’, ‘BENUTZERNAME’, ‘ID’, ‘STATUS’, ‘TYP’, ‘GERÄT’)

        $Sessions = query session 2>&1

        # Ensure the command executed successfully and returned valid output

        if (-not $Sessions -or $Sessions[0] -notmatch “BENUTZERNAME”) {

            Write-Host “Query session command failed or returned unexpected output.”

            return $null

        }

        try {

            # Skip the header row and filter for active sessions

            [array]$ActiveSessions = $Sessions | Select -Skip 1 | Where-Object { $_ -match “Aktiv” }

            # Check if there are active sessions

            if ($ActiveSessions.Count -eq 0) {

                Write-Host “No active sessions found.”

                return $null

            }

            # Parse each session into objects

            $LoggedOnUsers = foreach ($row in $ActiveSessions) {

                $columns = $row -split ‘s{2,}’

                if ($columns.Count -ge 3) { # Ensure the row has enough columns

                    [PSCustomObject]@{

                        SITZUNGSNAME = $columns[0]

                        BENUTZERNAME = $columns[1]

                        ID           = $columns[2]

                        STATUS       = $columns[3]

                        TYP          = if ($columns.Count -gt 4) { $columns[4] } else { “” }

                    }

                }

            }

            # Select the first logged-on user

            $LoggedOnUser = $LoggedOnUsers | Select-Object -First 1

            # Retrieve the SID for the logged-on user

            if ($LoggedOnUser -and $LoggedOnUser.ID) {

                $LoggedOnUserSID = Get-ItemProperty “HKLM:SOFTWAREMicrosoftWindowsCurrentVersionAuthenticationLogonUISessionData$($LoggedOnUser.ID)” -Name LoggedOnUserSID -ErrorAction SilentlyContinue |

                    Select-Object -ExpandProperty LoggedOnUserSID -ErrorAction SilentlyContinue

                return $LoggedOnUserSID

            } else {

                Write-Host “Failed to retrieve logged-on user details.”

                return $null

            }

        } catch {

            Write-Host “An error occurred while processing the session data: $_”

            return $null

        }

    }

    Write-Host “Attempting to identify currently logged-on user’s SID…”

    $LoggedOnUserSID = Get-LoggedOnUserSID

    if (-not $LoggedOnUserSID) {

        Write-Host “No logged-on user detected. Exiting with failure.”

        Exit 1

    } else {

        Write-Host “Logged-on user SID: $LoggedOnUserSID”

    }

  2. This is awesome. This is exactly what I need, but I can’t seem to get it to work. Intune is reporting my install is still failing even though that if I run the script locally as admin (in a 64-bit context), it evaluates as ‘all good’. Is there something I’m missing?

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.