PowerShell & Intune, Automate your Work - Part 2: Retrieve Win32 App Assignments
Today's increased demand for efficiency in IT necessitates knowledge of how to speed up workflow using powerful tools such as PowerShell and Intune.
It is the scripting capability provided by PowerShell that enables the automation of complex tasks, which are performed repeatedly, while Intune, part of Microsoft’s Endpoint Manager, allows devices and applications in an organization to be managed. This makes them achieve improved efficiencies and compliance in Windows application management.
Recap of Part 1: Retrieving Win32 Apps
In our first part titled “PowerShell & Intune automate your work: Part 1 - Retrieve Win32 Apps,” we covered several foundational skills that are essential when interacting with Azure and Microsoft Graph API through PowerShell. We went over some fundamental aspects of the AZ Module, negotiating authorization processes with Azure as well as what Microsoft Graph can do.
We also discovered how to use the Connect-MgGraph and Invoke-MgGraphRequest cmdlets to fetch a list of Win32 apps from Intune which will serve as background for more complicated application management exercises.
Retrieve Win32 App Assignments in Intune using PowerShell
Moving on from our initial exploration, this article delves into retrieving Win32 App Assignments.
Our script kicks off by establishing a connection to Microsoft Graph using specific scopes necessary for accessing detailed app data. These scopes include:
- "User.Read.All"
- "Group.ReadWrite.All"
- "DeviceManagementApps.Read.All"
- "DeviceManagementApps.ReadWrite.All"
- "GroupMember.Read.All"
- "Directory.Read.All"
- "Directory.ReadWrite.All"
- "Group.Read.All"
During the first run and the initial login in your tenant, you will be asked to provide consent to the above scopes:
Alternatively, you can also check the permissions and consent to them when you use the Graph Explorer. Just go to the Modify Permissions tab and everything needed for the operation will be displayed there.
Upon connection, the script fetches all Win32 applications using a targeted Graph API request.
For each application retrieved, it then queries for associated assignments:
Where-Object { ($PSItem.target.'@odata.type' -like "*groupAssignmentTarget") -or ($PSItem.intent -like $Intent) }
These are the configurations that dictate how apps are distributed to various groups within the organization.
The script meticulously parses through these assignments to determine details such as the group's inclusion or exclusion status and the specifics of deployment settings like notifications and restart behavior.
Each piece of assignment data is processed and stored in a custom PowerShell object, providing a structured and actionable overview of app distribution across the organization.
Error handling is built into the script to manage and report any issues encountered during the data retrieval process, ensuring robust and reliable execution.
$PSObject = [PSCustomObject]@{ Type = $Win32AppAssignment.target.'@odata.type' AppName = $Win32MobileApp.displayName GroupID = $Win32AppAssignment.target.groupId GroupName = $AzureADGroupResponse.displayName Intent = $Win32AppAssignment.intent GroupMode = $GroupMode Notifications = $Win32AppAssignment.settings.notifications RestartSettings = $Win32AppAssignment.settings.restartSettings InstallTimeSettings = $Win32AppAssignment.settings.installTimeSettings } $Win32AppAssignmentList.Add($PSObject) | Out-Null
Here is the full script for these operations:
Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All", "DeviceManagementApps.Read.All", "DeviceManagementApps.ReadWrite.All", "GroupMember.Read.All", "Directory.Read.All", "Directory.ReadWrite.All", "Group.Read.All" $Win32AppList = New-Object -TypeName "System.Collections.Generic.List[Object]" $Win32AppAssignmentList = New-Object -TypeName "System.Collections.Generic.List[Object]" $Win32MobileApps = Invoke-MgGraphRequest -Method GET "https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps?`$filter=isof('microsoft.graph.win32LobApp')" if ($Win32MobileApps -ne "") { $Win32MobileApps = $Win32MobileApps.value if ($Win32MobileApps -ne $null) { foreach ($Win32MobileApp in $Win32MobileApps) { #$Win32MobileApp.id | Out-String | Write-Host $Win32MobileApps2 = Invoke-MgGraphRequest -Method GET "https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps/$($Win32MobileApp.id)/assignments" #$Win32MobileApps2.value | Out-String | Write-Host # $Win32AppList.Add($Win32MobileApp) $Win32AppAssignmentMatches = $Win32MobileApps2.value | Where-Object { ($PSItem.target.'@odata.type' -like "*groupAssignmentTarget") -or ($PSItem.intent -like $Intent) } #$Win32AppAssignmentMatches.id | out-string | write-host foreach ($Win32AppAssignment in $Win32AppAssignmentMatches) { try { # Retrieve group name from given group id $Win32AppAssignmentValue = $Win32AppAssignment.target.groupId $AzureADGroupResponse = Invoke-MgGraphRequest -Method GET "https://graph.microsoft.com/v1.0/groups/$Win32AppAssignmentValue" # Determine if assignment is either Include or Exclude for GroupMode property output switch ($Win32AppAssignment.target.'@odata.type') { "#microsoft.graph.groupAssignmentTarget" { $GroupMode = "Include" } "#microsoft.graph.exclusionGroupAssignmentTarget" { $GroupMode = "Exclude" } } # Create a custom object for return value $PSObject = [PSCustomObject]@{ Type = $Win32AppAssignment.target.'@odata.type' AppName = $Win32MobileApp.displayName GroupID = $Win32AppAssignment.target.groupId GroupName = $AzureADGroupResponse.displayName Intent = $Win32AppAssignment.intent GroupMode = $GroupMode Notifications = $Win32AppAssignment.settings.notifications RestartSettings = $Win32AppAssignment.settings.restartSettings InstallTimeSettings = $Win32AppAssignment.settings.installTimeSettings } $Win32AppAssignmentList.Add($PSObject) | Out-Null # $PSObject | out-string | write-host } catch [System.Exception] { Write-Warning -Message "An error occurred while resolving groupId for assignment with ID: $($Win32AppAssignment.id). Error message: $($_.Exception.Message)" } return $Win32AppAssignmentList } } }}
Retrieve Win32 App Assignments for a Particular Application
If you only want to find the assignments for a specific application based on the DisplayName, you can easily adapt the script.
All you need to do is check if the DisplayName matches your target application.
if($Win32MobileApp.displayName -like "*vlc*"){
Once we add the simple line above in the code, we will see the following output:
Here’s the full modified code for searching the assignments of a particular app in Intune with PowerShell:
Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All", "DeviceManagementApps.Read.All", "DeviceManagementApps.ReadWrite.All", "GroupMember.Read.All", "Directory.Read.All", "Directory.ReadWrite.All", "Group.Read.All" $Win32AppList = New-Object -TypeName "System.Collections.Generic.List[Object]" $Win32AppAssignmentList = New-Object -TypeName "System.Collections.Generic.List[Object]" $Win32MobileApps = Invoke-MgGraphRequest -Method GET "https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps?`$filter=isof('microsoft.graph.win32LobApp')" if ($Win32MobileApps -ne "") { $Win32MobileApps = $Win32MobileApps.value if ($Win32MobileApps -ne $null) { foreach ($Win32MobileApp in $Win32MobileApps) { if($Win32MobileApp.displayName -like "*vlc*"){ # $Win32MobileApp.id | Out-String | Write-Host $Win32MobileApps2 = Invoke-MgGraphRequest -Method GET "https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps/$($Win32MobileApp.id)/assignments" $Win32AppAssignmentMatches = $Win32MobileApps2.value | Where-Object { ($PSItem.target.'@odata.type' -like "*groupAssignmentTarget") -or ($PSItem.intent -like $Intent) } foreach ($Win32AppAssignment in $Win32AppAssignmentMatches) { try { $Win32AppAssignmentValue = $Win32AppAssignment.target.groupId $AzureADGroupResponse = Invoke-MgGraphRequest -Method GET "https://graph.microsoft.com/v1.0/groups/$Win32AppAssignmentValue" switch ($Win32AppAssignment.target.'@odata.type') { "#microsoft.graph.groupAssignmentTarget" { $GroupMode = "Include" } "#microsoft.graph.exclusionGroupAssignmentTarget" { $GroupMode = "Exclude" } } # Create a custom object for return value $PSObject = [PSCustomObject]@{ Type = $Win32AppAssignment.target.'@odata.type' AppName = $Win32MobileApp.displayName GroupID = $Win32AppAssignment.target.groupId GroupName = $AzureADGroupResponse.displayName Intent = $Win32AppAssignment.intent GroupMode = $GroupMode Notifications = $Win32AppAssignment.settings.notifications RestartSettings = $Win32AppAssignment.settings.restartSettings InstallTimeSettings = $Win32AppAssignment.settings.installTimeSettings } $Win32AppAssignmentList.Add($PSObject) | Out-Null } catch [System.Exception] { Write-Warning -Message "An error occurred while resolving groupId for assignment with ID: $($Win32AppAssignment.id). Error message: $($_.Exception.Message)" } return $Win32AppAssignmentList } } } }}
Conclusion
IT administrators can automate the retrieval of application assignment data, which is quite critical and ensures that all employees have the tools they need to perform their tasks.
In addition, it saves time and improves accuracy thus reducing human errors during this process.
We are currently building on our PowerShell & Intune knowledgebase as we consider how IT operations could be improved and how security automation could be achieved.
Watch out for more insights in future parts of our series.