A colleague of mine asked me to help him with creating a relationship between an user and a device in ConfigMgr. He had been trying to use the Add-CMUserAffinityToDevice cmdlet but experienced some intermittent errors where the cmdlet would not work as expected. So I set out to explore how this could be done directly by scripting towards the SMS Provider directly and not using the cmdlet.

About User Device Affinity

A lot of you know that with ConfigMgr 2012, we got introduced to User Device Affinity (UDA). Instead of going with the traditional method by targeting systems (now referred to as devices), we could now target users and their primary devices. Targeting users is not something new, actually it was possible back in ConfigMgr 2007, but at that period there were no reason for doing so. Now with users having more than a single device, it’s become necessary to differentiate what device the user is using and what should be installed.

How to configure the Primary device for a user

There are several ways that you can determine the primary device of a users. Either you can let ConfigMgr take care of it or you can manually set the relationship between an user and a device.

If you want to let ConfigMgr determine the relationship, this will have to be enabled in the Client Settings.

1. Go to the Administration node and select Client Settings.
2. Open the Properties of either the Default Client Settings, or any custom Client Settings that you’ve created.
3. At the bottom, there’s a settings option called User and Device Affinity.
4. The setting called Automatically configure the device affinity from usage data would need to be configured to Yes, in order for ConfigMgr to determine the relationship based on the collected usage data.

103_1

By manually specifying the relationship, this can be done on either a device or the user.

User

1. Go to the Assets and Compliance node.
2. Select Users, right-click on the desired user and selected Edit Primary Devices.
3. Type in the name of a device that you want to add as the users primary device and click on Add.
4. Click on OK.

103_2

Device

1. Go to the Assets and Compliance node.
2. Select Devices, right-click on the desired device and select Edit Primary Users.
3. Type in the name of a user that you want to add as the primary user and click on Add.
4. Click on OK.

103_3

Now that I’ve shown you how this can be done manually by an administrator in the console, let’s get to the PowerShell part that this blog focuses on.

Creating a relationship between an User and a Device

As I mentioned earlier, the Add-CMUserAffinityToDevice cmdlet was giving my colleague a few intermittent errors. So instead we’ll look at how the relationship can be done by scripting towards the SMS Provider directly. In this example, I’m assuming that the name of the user and device is known. By that I mean that it can either be fed through parameters from another script or perhaps Orchestrator, or they’re manually entered.

First off, let’s specify some variables for connecting to the SMS Provider:

# Set variables for connecting to the SMS Provider
$SiteServer = "CAS01"
$SiteCode = "CAS"

We’ll take advantage of a method called CreateRelationship that’s available for the SMS_UserMachineRelationship WMI class. Before we go ahead and invokes that method, we need to determine what parameters it needs. The documentation for this method is available on TechNet here:

http://msdn.microsoft.com/en-us/library/hh948294.aspx

We can also determine that through PowerShell by running the following code:

# Set variables for an user and a device
$WMIConnection = [WmiClass]"\\$($SiteServer)\root\SMS\site_$($SiteCode):SMS_UserMachineRelationship"
$WMIConnection.psbase.GetMethodParameters("CreateRelationship")

This code combined with the variables set for connecting to the SMS Provider, will give us the following output:

103_4

From that we can determine that we have the 4 parameters that we need to specify in order to make use of the CreateRelationship method. If we read the documentation, TypeId is optional, but according to my tests in my lab environment, we need to specify that as well. If we further examine the documentation for this method, we can see that SourceId has a set of values that it accepts. The following table describe those values:

Software Catalog The end user enabled the relationship by selecting the option in the AppCatalog Web page.
Administrator An administrator created the relationship manually in the UI.
User Unused/deprecated.
Usage Agent The threshold of activity triggered a relationship to be created.
Device Management The user/device were tied together during enrollment.
OSD The user/device were tied together as part of OSD imaging.
Fast Install The user/device were tied together temporarily to enable an on-demand install from the catalog if no UDA relationship installed before the Install was triggered.
Exchange Server connector The device was provisioned through EAS.

Since the SourceId needs to be an integer, Software Catalog represents 1, Administrator represents 2 and so on. Unfortunately this is not documented on TechNet. The following code will determine the ResourceID, username as shown in ConfigMgr and the SourceId:

# Determine the device ResourceID, username as shown in ConfigMgr and the SourceId
$CMDeviceResourceID = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_R_System -ComputerName $SiteServer -Filter "Name like '%$($DeviceName)%'" | Select-Object -ExpandProperty ResourceID
$CMUserName = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_R_User -ComputerName $SiteServer -Filter "Name like '%$($UserName)%'" | Select-Object -ExpandProperty Name
$CMUserName = $CMUserName.Split(" ")[0]
[int]$SourceId = 2 #2 mean that it's been added by an administrator

Then we need to specify the WMI Class where the CreateRelationship method resides:

# Specify the WMI Class
$WMIConnection = [WmiClass]"\\$($SiteServer)\root\SMS\site_$($SiteCode):SMS_UserMachineRelationship"

Now that we have the WMI Class in $WMIConnection, we continue with setting the parameters in the $NewRelation variable:

# Get the method parameters and set them
$NewRelation = $WMIConnection.psbase.GetMethodParameters("CreateRelationship")
$NewRelation.MachineResourceId = $CMDeviceResourceID
$NewRelation.SourceId = $SourceId
$NewRelation.TypeId = 1
$NewRelation.UserAccountName = $CMUserName

Finally we just need to invoke the CreateRelation method to create our relationship between the User and the Device:

# Invoke the CreateRelationship method
$WMIConnection.psbase.InvokeMethod("CreateRelationship", $NewRelation, $null)

That’s it! When you have executed the script, you’ll now see that a relation between the specified user and device has been created:

103_5

The whole script

# Set variables for connecting to the SMS Provider
$SiteServer = "CAS01"
$SiteCode = "CAS"

# Set variables for an user and a device
$DeviceName = "CL03"
$UserName = "nickolaj"

# Determine the device ResourceID, username as shown in ConfigMgr and the SourceId
$CMDeviceResourceID = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_R_System -ComputerName $SiteServer -Filter "Name like '%$($DeviceName)%'" | Select-Object -ExpandProperty ResourceID
$CMUserName = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_R_User -ComputerName $SiteServer -Filter "Name like '%$($UserName)%'" | Select-Object -ExpandProperty Name
$CMUserName = $CMUserName.Split(" ")[0]
[int]$SourceId = 2 #2 mean that it's been added by an administrator

# Specify the WMI Class
$WMIConnection = [WmiClass]"\\$($SiteServer)\root\SMS\site_$($SiteCode):SMS_UserMachineRelationship"

# Get the method parameters and set them
$NewRelation = $WMIConnection.psbase.GetMethodParameters("CreateRelationship")
$NewRelation.MachineResourceId = $CMDeviceResourceID
$NewRelation.SourceId = $SourceId
$NewRelation.TypeId = 1
$NewRelation.UserAccountName = $CMUserName

# Invoke the CreateRelationship method
$WMIConnection.psbase.InvokeMethod("CreateRelationship", $NewRelation, $null)

That’s how you can leverage PowerShell to create a relationship (affinity) between an user and a device.

Nickolaj Andersen
Principal Consultant and Enterprise Mobility MVP. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows deployments and Automation. In 2015 Nickolaj was awarded as PowerShell Hero by the community for his script and tools contributions. Author of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService and a frequent speaker at user groups.

(889)

comments
  • Dimitry
    Posted at 10:08 April 14, 2015
    Dimitry
    Reply
    Author

    very interesting article.
    As we are moving our device based installations to User based, we are configuring the primary users.
    To create a relationship works fine by your example but I’m also looking for a sollution to delete a relationship.

  • HeyAdmin
    Posted at 22:18 June 10, 2015
    HeyAdmin
    Reply
    Author

    Are you positive about your description of the SourceID column? I queried the view for all records where the SourceID = ‘2’, and then inquired with the person returned in the CreatedBy column for each record. None of them had created a manual relationship in the console. Is it possible your list is out of order?

  • Eden Oliveira
    Posted at 03:15 July 11, 2017
    Eden Oliveira
    Reply
    Author

    Hi Nickolaj, quick question. I have a CSV file with 200 PCs and usernames. They all have the relationship as “UsageAgent”. I woudl like to change them to “Administrator”, How could I achieve that?

    PS: I am not a powershell expert, still learning.

    Thank you

    Eden Oliveira

  • Leave a Reply