Automate device groups based on discovered apps with PowerShell and Intune

This will be a shorter post than normal. Just a quickly put together script that I found useful.

I imagine many Intune admins have been asked in the past "We need a count of all devices with Adobe Acrobat installed, can you get us a list of devices?"

If the software is managed by Intune, then sure no problem. We can see in the Intune portal all the devices that have installed said app via company portal.

However, I have not found a streamlined way to create a device group with this information. So, I wrote something up that hopefully makes our lives that much easier.

I will breakdown the script, so we understand how it works, it's fairly simple.

First some requirements:

Required Powershell Modules:
    Name                                              Version
    ----                                              -------
    Microsoft.Graph.Authentication                    2.15.0
    Microsoft.Graph.Beta.DeviceManagement             2.15.0
    Microsoft.Graph.Beta.Groups                       2.15.0
    Microsoft.Graph.Beta.Identity.DirectoryManagement 2.15.0

Required Microsoft Graph API Permissions:
    - DeviceManagementConfiguration.ReadWrite.All
    - DeviceManagementManagedDevices.ReadWrite.All
    - Directory.ReadWrite.All
    - Group.ReadWrite.All
    - GroupMember.ReadWrite.All
    - Device.ReadWrite.All

We will be using the 'Discovered Apps' blade within Intune as reference.

I don't have many devices in my tenant at this time, so our group will be small.

Now, we'd want to retrieve all detected installations of "Adobe Acrobat (64-bit)"

$DetectedInstalls = Get-MgBetaDeviceManagementDetectedApp -Filter "displayname eq 'Adobe Acrobat (64-bit)'"

Next, we will retrieve the associated device name(s) of the detected installs.

$DetectedInstallHostnames = $DetectedInstalls | ForEach-Object {
   $DetectedInstall = $_
   Get-MgBetaDeviceManagementDetectedAppManagedDevice -DetectedAppId $DetectedInstall.id -ErrorAction Stop | Select-Object DeviceName
}

Next, we check for an existing group, and create it if needed.

# Define group details
$GroupName = "$($AppDisplayName -replace '[^a-zA-Z0-9]', '')_Installed_Devices" # Remove space and characters for MailNickname
$GroupDescription = "Devices with [$AppDisplayName] installed"

# Check if the group already exists
$Group = Get-MgBetaGroup -Filter "displayName eq '$GroupName'" -ErrorAction Stop | Select-Object -First 1

# Create the group if it doesn't exist
if (-not $Group) {
    $GroupParams = @{
        DisplayName     = $GroupName
        Description     = $GroupDescription
        MailEnabled     = $false
        MailNickname    = $GroupName
        SecurityEnabled = $true
        GroupTypes      = @()
    }
    $Group = New-MgBetaGroup @GroupParams
    Write-Host "Group '$GroupName' created."
}

Next, we gather all existing group members and add or remove devices from the group depending on if they are in the detected installs object.

# Get current members of the group
            $CurrentGroupMembers = Get-MgBetaGroupMember -GroupId $Group.Id -ErrorAction Stop | ForEach-Object { Get-MgBetaDevice -DeviceId $_.Id -ErrorAction Stop }

            # Loop through detected installations to add devices to the group
            $DetectedInstallHostnames | ForEach-Object {

                $DetectedInstallHostname = $_

                # Check if the device is already a member of the group
                $IsInGroup = $CurrentGroupMembers | Where-Object { $_.DisplayName -eq $DetectedInstallHostname.DeviceName }

                # Add the device to the group if it's not already a member
                if (-not $IsInGroup) {

                    $deviceObject = Get-MgBetaDevice -Filter "displayname eq '$($DetectedInstallHostname.DeviceName)'" -ErrorAction Stop

                    New-MgBetaGroupMember -GroupId $group.Id -DirectoryObjectId $deviceObject.id -ErrorAction Stop

                    Write-Host "Added $($DetectedInstallHostname.DeviceName) to group '$GroupName'."
                }
            }

            # Clean up: Remove devices from the group if they no longer have the app installed
            $CurrentGroupMembers | ForEach-Object {

                $GroupMember = $_

                $IsStillDetected = $DetectedInstallHostnames | Where-Object { $_.DeviceName -eq $GroupMember.DisplayName }

                # Remove the device from the group if it's no longer detected
                if (-not $IsStillDetected) {

                    $deviceObject = Get-MgBetaDevice -Filter "displayname eq '$($GroupMember.DisplayName)'" -ErrorAction Stop

                    Remove-MgBetaGroupMemberByRef -GroupId $group.Id -DirectoryObjectId $deviceObject.id -ErrorAction Stop

                    Write-Host "Removed $($GroupMember.DisplayName) from group '$GroupName' as '$AppDisplayName' is no longer detected."
                }
            }

This could be set up to run via an Azure App registration for automated updating, or just ran manually in one off scenarios. Please use as best fits your needs.

For the full script see below:

IntuneScripts/Invoke-AppInstalledDevicesGroup.ps1 at main · jorgeasaurus/IntuneScripts
Contribute to jorgeasaurus/IntuneScripts development by creating an account on GitHub.

Subscribe to > Jorgeasaurus

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe