View Applicable Devices for Driver Deployments

The commercial Driver and Firmware servicing has been big talk across the system management community (SEE PRESS RELEASE HERE) since it’s release on valentines day. It can be challenging though to find out the applicable devices, the UI does offer an applicable device count in its current state, however this post is to show you how to find the applicable devices in your audiences.

We will be looking at how we can do this via the Graph API, and also how you can retrieve this data from the Windows Update for Business Reports log analytics workspace.

If you don’t have WUfB Reports configured, you can take a look at my VLOG to assist with the configuration.


  • Permissions to connect to the Graph API with the following scopes
    • WindowsUpdates.ReadWrite.All
  • Permission to query your Log Analytics workspace hosting WUfB Reports data
  • Permissions to Azure AD with the Ability to connect via PowerShell
  • Microsoft.Graph PowerShell Module

Connecting to the Graph API

Connecting via this module could not be easier, follow the below steps after ensuring the Microsoft.Graph module is installed.;

  1. Launch a PowerShell prompt
  2. Enter Connect-MgGraph -Scopes WindowsUpdates.ReadWrite.All -ContextScope Process, hit Enter
  3. Sign in, If not already consented, you will be prompted with an image like the below. You can choose to grant for yourself or your organisation if you have the permissions.
MGraph Module Authentication Prompt

Microsoft Graph Profile Selection

The first thing we need to do before running any commands is call Select-MgProfile -Name beta to ensure we are using the Beta endpoint of the Microsoft Graph.

Find Applicable Device id’s using the Graph

This will only display the AzureAD Device ID, this will not give you the device name.

To list all of the applicable content from a policy, you must first know the deploymentAudience id to which your policy is targeted. You can take a look at my Driver Management via Graph API and PowerShell post on how to obtain this information.

Once you have your deployment audience you can run (Invoke-MgGraphRequest -Method GET -Uri "'<audienceID>')/applicableContent?`$expand=catalogEntry").Value, replacing the <audienceID> with your audience id, this will return something like the following;

Name                           Value
----                           -----
matchedDevices                 {8exxxxxx-2bbe-xxxx-ba2c-xxxxxxxxxxf9, 16xxxxxx-aee7-xxxx-xxxx-xxxxxxxxxx39}
catalogEntry                   {[deployableUntilDateTime, ], [setupInformationFile, ], [provider, Intel], [versionDate
matchedDevices                 {24xxxxx-xxxx-xxxx-b50c-xxxxxxxxxxda, 8exxxxxx-2bbe-xxxx-ba2c-xxxxxxxxxxf9, 16xxxxxx-a
catalogEntry                   {[deployableUntilDateTime, ], [setupInformationFile, ], [provider, Intel], [versionDate
matchedDevices                 {8exxxxxx-2bbe-xxxx-ba2c-xxxxxxxxxxf9, 16xxxxxx-aee7-xxxx-xxxx-xxxxxxxxxx39, dd8af46f-4
catalogEntry                   {[deployableUntilDateTime, ], [setupInformationFile, ], [provider, Intel], [versionDate
matchedDevices                 {8exxxxxx-2bbe-xxxx-ba2c-xxxxxxxxxxf9}

As you can see the matchedDevices has your Device IDs, however, from the above view, it isn’t ver consumable as you cannot see what driver is which, so you could run something like the following to try and make it a bit better;

$applicableConent = (Invoke-MgGraphRequest -Method GET -Uri "'<audienceID>')/applicableContent?`$expand=catalogEntry").Value

$consumableContent = @()
FOREACH ($dObj in $applicableConent) {
    $dContent = @{}
    $dContent.driverDisplayName += $dObj.catalogEntry.displayName
    $dContent.matchedDevices += $dObj.matchedDevices

    $consumableContent += $dContent

#Run this to view an example of your output

If you have run the above you should then see something like the following.

Name                           Value
----                           -----
matchedDevices                 {8exxxxxx-2bbe-xxxx-ba2c-xxxxxxxxxxf9, 16xxxxxx-aee7-xxxx-xxxx-xxxxxxxxxx39}
driverDisplayName              Intel - net -

This is a lot more consumable, however, it is still only a list of ID’s which you would then have to circle through with the AzureAD powershell module to help this be of more use. You also have to do this for each deployment audience you have, so if you have multiple, this could soon become very complex.

So, with that in mind, lets take a look at a more consumable, and user friendly way to do this with WUfB Reports Log Data.

WUfB Reports Data

This data will have a delay of up to 24 hours.

We will not be looking at the Monitor Workbook for this section, we will only be looking at the Log Data in the Log Analytics workspace. So if you browse to your workspace and open up the logs section we will then be able to run a couple of queries.

Lets break the first couple of lines of the queries down a little before we look at the final summarization.

  1. We select the table where the data is stored
  2. We filter for the DriverUpdate Category
  3. We ensure we are only picking up devices with applicable content, and where the status is not cancelled
  4. We join the UCClient table on the AzureADDeviceID so we can consume the DeviceName
  5. We then summerize the results to get the latest entry per device object.

From the above we then summerize this data in a couple of ways to get different views on the data.

By CatalogID

There are numerous ways we can group the data for review, however, no matter what the PolicyID, or DeploymentID is, if the update CatalogID is the same it makes sense to logically group them by this for a view across the entire estate.

So with that you end up with the following query, which will display a count of devices, the Device DisplayNames along with the catalogID and Update DisplayName as in the image at the end.

| where UpdateCategory == "DriverUpdate"
| where isnotempty(ServiceState) and ServiceState !in ("Cancelled")
| join UCClient on AzureADDeviceId
| summarize arg_max(TimeGenerated,*) by AzureADDeviceId
| summarize DeviceCount=count(), Devices=make_list(DeviceName) by CatalogId, UpdateDisplayName
query1 Output

By Policy

If you would prefer to view applicable device by policy, the following query will do just that, the output will be very similar to above however it will be broken down by the PolicyID as show in the image.

| where UpdateCategory == "DriverUpdate"
| where isnotempty(ServiceState) and ServiceState !in ("Cancelled")
| join UCClient on AzureADDeviceId
| summarize arg_max(TimeGenerated,*) by AzureADDeviceId
| summarize DeviceCount=count(), Devices=make_list(DeviceName) by PolicyId, UpdateDisplayName
query2 Output

Closing Thoughts

When all is said and done, I would choose the Log Analytics data to report on this, I know it’s 24 hours behind, but how often do you need to know the data at that single point in time? And if you do, you could then always perform is semi-manully.

There are also many other ways you can manipulate this data for your needs, these are basic examples to set you on your way!.

comments powered by Disqus