Set-PsIntuneDeviceCategory.ps1

function Set-PSIntuneDeviceCategory {
    <#
    .SYNOPSIS
        Batch update Intune device category assignment
    .DESCRIPTION
        Batch update Intune device category assignment using
        an input file (csv or txt) to filter the computer names
    .PARAMETER IntputFile
        Path and name of .CSV or .TXT input file
        CSV file must have a column named "Computer"
        TXT file must be computer names only, one per line
    .PARAMETER CategoryName
        A valid category name. If the name does not exist in the
        Intune subscription, it will return an error
    .PARAMETER Credential
        User with permissions to access and modify Intune managed devices
    .EXAMPLE
        Set-PSIntuneDeviceCategory -InputFile ".\computers.txt" -CategoryName "Personal" -Credential $mycredential
    .EXAMPLE
        Set-PSIntuneDeviceCategory -InputFile ".\computers.csv" -CategoryName "Corporate" -Credential $mycredential
    .NOTES
        Requires an Azure AD app registration with Application permissions assigned:
        Device.Read / Read.All / ReadWrite.All
        DeviceManagementManagedDevice.Read.All / ReadWrite.All
        0.1 - 2021-02-03 - David Stein, Catapult Systems
    #>

    [CmdletBinding(SupportsShouldProcess=$True)]
    param (
        [parameter(Mandatory)][string][ValidateNotNullOrEmpty()] $InputFile,
        [parameter(Mandatory)][string] $CategoryName,
        [parameter(Mandatory)][pscredential] $Credential
    )
    if (-not(Test-Path $InputFile)) {
        throw "file not found: $InputFile"
    }
    if ($InputFile.EndsWith(".csv")) {
        [array]$computers = Import-Csv -Path $InputFile | Select-Object Computer
    } elseif ($InputFile.EndsWith(".txt")) {
        [array]$computers = Get-Content -Path $InputFile | Where-Object {-not($($_).ToString().StartsWith(';'))}
    } else {
        throw "invalid file type (.csv or .txt only)"
    }

    if ($computers.Count -gt 0) {
        Write-Host "processing $($computers.Count) computer names"
    } else {
        throw "no computers were imported from file"
    }

    Write-Verbose "connecting to: azure ad"
    $azconn = Connect-AzureAD -Credential $Credential -ErrorAction Stop
    if (!$WhatIfPreference) { Write-Verbose "connected to $($azconn.TenantDomain)" }

    Write-Verbose "connecting to: msgraph"
    $conn = Connect-MSGraph -Credential $credential -PassThru

    Update-MSGraphEnvironment -SchemaVersion 'beta' | Out-Null
    [string]$baseUrl = "https://graph.microsoft.com/beta"

    Write-Verbose "getting devices"
    [array]$devices = Get-DeviceManagement_ManagedDevices
    Write-Verbose "returned $($devices.Count) devices"

    Write-Verbose "getting device categories"
    [array]$cats = Get-DeviceManagement_DeviceCategories
    Write-Verbose "returned $($cats.Count) categories"

    Write-Verbose "validating requested category: $CategoryName"
    $cat = $cats | Where-Object {$_.displayName -eq $CategoryName}
    if ($null -eq $cat) { throw "category not found: $CategoryName" }
    $DeviceCategory = $cat.id
    Write-Verbose "categoryId........ $DeviceCategory"

function Set-DeviceCategory {
    [CmdletBinding(SupportsShouldProcess=$True)]
    param (
        [parameter(Mandatory)][string] $DeviceID,
        [parameter(Mandatory)][string] $CategoryID
    )
    Write-Verbose "updating device... $DeviceID"
    $requestBody = @{
        "@odata.id" = "$baseUrl/deviceManagement/deviceCategories/$CategoryID"
    }
    $url = "$baseUrl/deviceManagement/managedDevices/$DeviceID/deviceCategory/`$ref"
    Write-Verbose "request-url: $url"
    if (!$WhatIfPreference) {
        $result = Invoke-MSGraphRequest -HttpMethod PUT -Url $url -Content $requestBody
    } else {
        Write-Host "[WHAT-IF] would submit request to graph API" -ForegroundColor Cyan
    }
    #$result
}

    foreach ($computer in $computers) {
        $device = $devices | Where-Object {$_.deviceName -eq $computer}
        if ($null -eq $device) { 
            Write-Warning "device not found: $computer"
        } else {
            $deviceid = $device.id
            Write-Verbose "deviceName........ $computer"
            Write-Verbose "deviceId.......... $deviceId"
            Write-Verbose "current-category.. $($device.deviceCategoryDisplayName)"
            Set-DeviceCategory -DeviceID $device.id -category $DeviceCategory
        }
    }
}