0

More specifically, What I am trying to do is to loop through all intunemanageddevices and updated the device category based off of matching the serial number that is listed in a csv file. Example: If the script finds any serial number that is in both the csv and intune, to update the device category to 'in use'. I already I have this category created and the devicecategory id.

How can I modify this script? So far, I have something like this but I dont know how to add the foreach loop with the foreach like I have below:

Connect-MSGraph

Update-MSGraphEnvironment -SchemaVersion 'beta'

function Set-DeviceCategory {

  param(

    [Parameter(Mandatory)]

    [string]$DeviceID,


    [Parameter(Mandatory)]

    [string]$DeviceCategory

  )

  $body = @{ '@odata.id' = "https://graph.microsoft.com/beta/deviceManagement/deviceCategories/$DeviceCategory" }

  Invoke-MSGraphRequest -HttpMethod PUT -Url "deviceManagement/managedDevices/$DeviceID/deviceCategory/`$ref"
  -Content $body

}

$devices = (Invoke-MSGraphRequest -HttpMethod GET -Url 'deviceManagement/managedDevices').value

$devices | ForEach-Object {

  if ($_.serialnumber -eq 'serial') {

    $deviceCategory = 'category id'

    Write-Host "Set device category '$deviceCategory' for $($_.serialnumber)"

    Set-DeviceCategory -DeviceID $_.id -DeviceCategory $deviceCategory

  }
  else {

    'Failed to update'

  }

}

I tried nesting the foreach loops but doesnt seem to work. No error either.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thanks; I've tweaked the formatting with indentation that helps readability, and I've added another tag that hopefully attracts subject-matter experts (Personally, I can't be of further help). – mklement0 Aug 25 '23 at 23:34

1 Answers1

0

This should do the trick:

Connect-MSGraph
Update-MSGraphEnvironment -SchemaVersion 'beta'
function Set-DeviceCategory 
{
    param(
    [Parameter(Mandatory)]
    [string]$DeviceID,
    [Parameter(Mandatory)]
    [string]$DeviceCategory

    )
    Write-Host "Setting device category: $DeviceCategory, for device: $DeviceID"
    $body = @{ '@odata.id' = "https://graph.microsoft.com/beta/deviceManagement/deviceCategories/$DeviceCategory" }
    Invoke-MSGraphRequest -HttpMethod PUT -Url "deviceManagement/managedDevices/$DeviceID/deviceCategory/`$ref" -Content $body

}

$intuneDevices = (Invoke-MSGraphRequest -HttpMethod GET -Url 'deviceManagement/managedDevices').value
$referenceDevices = Import-Csv 'PATH TO CSV HERE' #Assuming we have columns for DeviceName, and DeviceSerial
$deviceCategory = 'category id' 

foreach ($Device in $intuneDevices)
{
    if ($referenceDevices.DeviceSerial -contains $Device.serialnumber) 
    {
        Set-DeviceCategory -DeviceID $Device.id -DeviceCategory $deviceCategory
    }
    else 
    {
        #Maybe set it to a different category if its not in your list?
    }
}

You could also probably speed up the time taken to get all the intune devices if you use a filter. Also if you have more than 1k devices, you will need to use a foreach and get each 1k page of results, as Graph calls are paginated:

https://learn.microsoft.com/en-us/graph/paging

KG-DROID
  • 268
  • 6
  • Thank you very much! Works well! By the way, since graph calls are paginated would the -all switch be all what’s needed? If I was to make another foreach loop, how would that be? Within the if statement of set-device category? – PowerShellWiz Aug 27 '23 at 12:30
  • If you used something like: https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.devicemanagement/get-mgdevicemanagementmanageddevice?view=graph-powershell-1.0 rather than the invoke command, yeah looks like you can use the all switch. You can nest multiple foreach within foreach, you would just give the item a different name, in the example above I have used $Device as the name of each item in the foreach, so the nested foreach could be anything else, and you can still use the $Device within the nested foreach. – KG-DROID Aug 28 '23 at 10:59
  • Thats true. Or I could do a do until loop until it stops asking for a next link.but I would need to creat an authorization header connector for that. But for now, I simply added the next link pages url as a variable and added it to my for each. Thank you again for your help! – PowerShellWiz Aug 30 '23 at 15:24
  • By the way, do you know how you would filter out devices in other states? Example, the csv includes a column called “state” and some devices show as “in use” and some show as “retired”. I am wondering how I can update the categories to in use but not update the ones that show as retired. – PowerShellWiz Aug 30 '23 at 16:57
  • You could just add to the existing IF statement like this: `if (($referenceDevices.DeviceSerial -contains $Device.serialnumber) -and ($Device.State -eq 'in use'))` – KG-DROID Aug 31 '23 at 18:08
  • This didn’t work for me. State is the column name in the csv for the device category name. Wouldn’t it be referencedevices.state -eq “in use”? I tried that and still no luck. The only luck I have is doing device.devucecategorydisplayname -eq “in use” and the same in my else if statement except with -eq “retired” and to update to retired category. This does it but it doesn’t work if the device is in use. – PowerShellWiz Aug 31 '23 at 19:27
  • ah wups sorry yeah it would be referenceDevices but your not in a foreach for that, so it would need more tweaking: `foreach ($Device in $intuneDevices) { $matchingReference = $referenceDevices | Where-Object DeviceSerial -eq $Device.serialnumber if ($matchingReference -and ($matchingReference.State -eq 'in use')) { Set-DeviceCategory -DeviceID $Device.id -DeviceCategory $deviceCategory } else { #Action for if there is no matching device in the csv or state isnt in use } }` – KG-DROID Aug 31 '23 at 19:54
  • Ahhhh i see!!! And for my other 5 categories I can just add a else if condition for each state. Awesome. Thanks a ton! – PowerShellWiz Aug 31 '23 at 20:28