PowerShell & Intune, Automate your Work - Part 2: Retrieve Win32 App Assignments

Written by Alex Marin · June 19th, 2024 · 5min read

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:

Permission requested by Microsoft

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.

Microsoft Graph Explorer view

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:

IInvoke-MgGraphRequest -apps

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.

Written by
See author's page
Alex Marin

Application Packaging and SCCM Deployments specialist, solutions finder, Technical Writer at Advanced Installer.

Comments: