Creating a Intune Application Deployment Overview

Standard

The last couple of weeks I toke some time to investigate the possibilities of the Microsoft Graph API with Intune and AzureAD. In this blogpost I want to share my results of these investigations. One of the big advantages of having Microsoft Intune on the ‘new’ platform is the availability of Microsoft Graph API. Through the Graph API you easily control Microsoft Intune. In this blogpost I want to focus on creating an Application Deployment overview for applications deployed with Microsoft Intune to your Windows 10 workstations. My goal was to create an overview of the applications with the following information: Number of deployments to devices and if they are successful or failed. And based on those numbers I wanted to have the percentage of successful and failed deployments.

Before we continue with the actual scripts and the results I want to make note that: This blogpost is based on the beta Microsoft Graph API section of Intune. Be aware of using this in production environment since this is not supported by Microsoft at this moment. I’ve tested this script on my test environment and it’s not tested on a production environment yet.

The first step we need to take is to make sure that we can authenticate against the Graph API and that we’ve the rights to query the Intune data. I used the following blogpost of colleague MVP Nickolaj Andersen to create an AzureAD applications for this: http://www.scconfigmgr.com/2017/08/03/create-an-azure-ad-app-registration-for-accessing-microsoft-intune-graph-api-with-powershell/. He also created a very nice function which takes care of the authentication. You can find the latest version here: https://github.com/SCConfigMgr/Intune/blob/master/Authentication/Get-MSGraphAuthenticationToken.ps1. Because I’m using the AzureAD Preview Module I had to change line 47 of his function to:

$AzureADModules = Get-InstalledModule -Name "AzureAD*"

With that change the script is capable of using both the AzureAD and the AzureAD Preview module. Another very good resource for starting querying Intune through the Graph API is the Intune PowerShell section on Github: https://github.com/microsoftgraph/powershell-intune-samples. Microsoft has provided some great examples, but let’s start with creating a script to get the application deployment status. The first thing to do is querying all applications within Intune except the managed applications and the VPP applications. The following code will get the Apps from your Intune environment:

try {
 $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)"
 $apps = (Invoke-RestMethod -Uri $uri –Headers $AuthenticationHeader –Method Get).Value | Where-Object { (!($_.'@odata.type').Contains("managed")) -and (!($_.'@odata.type').Contains("#microsoft.graph.iosVppApp")) }
}

catch {
  $ex = $_.Exception
  Write-Host "Request to $Uri failed with HTTP Status $([int]$ex.Response.StatusCode) $($ex.Response.StatusDescription)" -f Red
  $errorResponse = $ex.Response.GetResponseStream()
  $reader = New-Object System.IO.StreamReader($errorResponse)
  $reader.BaseStream.Position = 0
  $reader.DiscardBufferedData()
  $responseBody = $reader.ReadToEnd();
  Write-Host "Response content:`n$responseBody" -f Red
  Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)"
  write-host
  break
}

The next step is to loop through all applications and retrieve the install status of the application. Currently this overview is focusing only device deployment status overview. So we need to retrieve the device status of each application, this is done by the following code:

$AppDisplayName    = $app.displayName
$AppId             = $app.id
$AppType           = $app.'@odata.type'

try {
  $Resource   = "deviceAppManagement/mobileApps/$AppId/deviceStatuses/"
  $uri        = "https://graph.microsoft.com/$graphApiVersion/$($Resource)"
  $appsstatus = (Invoke-RestMethod -Uri $uri –Headers $AuthenticationHeader –Method Get).Value
}

catch {
  $ex = $_.Exception
  Write-Host "Request to $Uri failed with HTTP Status $([int]$ex.Response.StatusCode) $($ex.Response.StatusDescription)" -f Red
  $errorResponse = $ex.Response.GetResponseStream()
  $reader = New-Object System.IO.StreamReader($errorResponse)
  $reader.BaseStream.Position = 0
  $reader.DiscardBufferedData()
  $responseBody = $reader.ReadToEnd();
  Write-Host "Response content:`n$responseBody" -f Red
  Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)"
  write-host
  break
}

Now we have all the data we need to process this. This script will generate the following output:

  1. All detailed deployment statuses will be exported as csv files so you can work with Excel/PowerBI to look for specific details of further analysis;
  2. An formatted HTML file which contains the Application Deployment overview;

The following code will take care of formatting the data and exporting the CSV and HTML file.:

foreach($status in $appsstatus) {
  $status | Add-Member -MemberType NoteProperty -Name 'AppName' -Value $AppDisplayName
  $status | Add-Member -MemberType NoteProperty -Name 'AppType' -Value $AppType
  $AppStatusProcessed += $status
}

Write-Host "Exporting detailed data for application: $AppDisplayName ($appid) to $AppDepStatus_csv"
$AppStatusProcessed | Where-Object { ($_.AppName -eq $AppDisplayName) -and ($_.mobileAppInstallStatusValue -ne 'notApplicable')} | select AppName,AppType,userPrincipalName, UserName, OSDescription, OSVersion, mobileAppInstallStatusValue, errorcode, lastsyncdatatime, deviceName, deviceid | Export-Csv -Path $AppDepStatus_csv -Delimiter "," -NoTypeInformation -Append
    
Write-Host "Generating Statistics for application: $AppDisplayName ($appid)"
$AppDeployedTotal           = (($AppStatusProcessed | Where-Object { ($_.AppName -eq $AppDisplayName) -and ($_.mobileAppInstallStatusValue -ne 'notApplicable')}) | Measure-Object).Count
$AppDeployedSucces          = (($AppStatusProcessed | Where-Object { ($_.AppName -eq $AppDisplayName) -and ($_.mobileAppInstallStatusValue -eq 'installed')}) | Measure-Object).Count
$AppDeployedFailed          = (($AppStatusProcessed | Where-Object { ($_.AppName -eq $AppDisplayName) -and ($_.mobileAppInstallStatusValue -eq 'failed')}) | Measure-Object).Count
$AppDeployedNotIns          = (($AppStatusProcessed | Where-Object { ($_.AppName -eq $AppDisplayName) -and ($_.mobileAppInstallStatusValue -eq "notInstalled")}) | Measure-Object).Count
    
if($AppDeployedTotal -gt 0) { 
   $AppDeployedSuccesRate  = ($AppDeployedSucces / $AppDeployedTotal).ToString("P")
   $AppDeployedFailedRate  = ($AppDeployedFailed / $AppDeployedTotal).ToString("P")
} else {
   $AppDeployedSuccesRate  = '0,00 %'
   $AppDeployedFailedRate  = '0,00 %'
}

$props = @{
   AppName                 = $AppDisplayName
   AppType                 = $AppType
   AppDeployedTotal        = $AppDeployedTotal
   AppDeployedSucces       = $AppDeployedSucces
   AppDeployedFailed       = $AppDeployedFailed
   AppDeployedNotIns       = $AppDeployedNotIns
   AppDeployedSuccesRate   = $AppDeployedSuccesRate
   AppDeployedFailedRate   = $AppDeployedFailedRate
}

$ServiceObject = New-Object -TypeName PSObject -Property $props
$AppDeplStatistics += $ServiceObject

Write-Host ""

$html = '<style>'
$html = $html + 'BODY{background-color:#FAFAFA;font-family:"Trebuchet MS", Helvetica, sans-serif}'
$html = $html + 'TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}'
$html = $html + 'TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:#6E6E6E}'
$html = $html + 'TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:#D8D8D8;text-align:center;}'
$html = $html + '</style>'

$AppDeplStatistics | select AppName,AppType,AppDeployedSucces,AppDeployedFailed,AppDeployedNotIns,AppDeployedTotal,AppDeployedSuccesRate,AppDeployedFailedRate | Sort-Object AppName | ConvertTo-HTML -head $html -body "<H2>Intune Application Deployment Status Overview</H2>" | Out-File $AppDepStatus_html

The total script can be run from the command line by using the following syntax:

.\Get-ApplicationDeploymentOverview.ps1 -TenantName <Name of the AzureAD tenant> -ClientID <ID of the AzureAD application> -Exportpath <Path to a location on your local disk where the exported files will be saved>

The result will be an CSV file with all detailed deployment status information and a HTML file containing an overview of the deployment status. See below and example of the overview:

The full script can be downloaded from my GitHub account: https://github.com/arjanvroege/GraphAPI/blob/master/Get-ApplicationDeploymentStatus.ps1

One thought on “Creating a Intune Application Deployment Overview

Leave a Reply