Public/Invoke-CMClientPolicyRefreshBulk.ps1

function Invoke-CMClientPolicyRefreshBulk {
    <#
    .SYNOPSIS
        Triggers machine policy retrieval + evaluation on many clients from a list or a collection.
    .DESCRIPTION
        Source devices from -ComputerName, a text file (-InputFile, one name per line), or a
        collection (-CollectionId, resolved via the SMS Provider). Two modes:
          Direct - CIM TriggerSchedule on each client (needs WinRM/DCOM + local admin), parallel on PS7.
          Notification - Invoke-CMClientNotification via the site (needs the console module, no client remoting).
    .PARAMETER SiteCode
        Site code (needed for -CollectionId or Notification mode).
    .PARAMETER ProviderMachineName
        SMS Provider server.
    .PARAMETER ComputerName
        Explicit device names.
    .PARAMETER InputFile
        Text file with device names.
    .PARAMETER CollectionId
        Collection whose members are targeted.
    .PARAMETER Mode
        Direct or Notification.
    .PARAMETER ThrottleLimit
        Parallelism for Direct mode on PowerShell 7.
    .EXAMPLE
        Invoke-CMClientPolicyRefreshBulk -SiteCode HOU -ProviderMachineName cm01 -CollectionId HOU00042 -WhatIf
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [string]$SiteCode,
        [Alias('SiteServer')][string]$ProviderMachineName,
        [string[]]$ComputerName,
        [string]$InputFile,
        [string]$CollectionId,
        [ValidateSet('Direct','Notification')][string]$Mode = 'Direct',
        [ValidateRange(1,128)][int]$ThrottleLimit = 32
    )

    if (($CollectionId -or $Mode -eq 'Notification') -and (-not $SiteCode -or -not $ProviderMachineName)) {
        throw '-SiteCode and -ProviderMachineName are required for -CollectionId or Notification mode.'
    }

    if ($Mode -eq 'Notification' -and $CollectionId -and -not $ComputerName -and -not $InputFile) {
        Connect-CMSite -SiteCode $SiteCode -ProviderMachineName $ProviderMachineName | Out-Null
        if ($PSCmdlet.ShouldProcess("Collection $CollectionId", 'Invoke-CMClientNotification DownloadComputerPolicy')) {
            Invoke-CMClientNotification -DeviceCollectionId $CollectionId -ActionType DownloadComputerPolicy
        }
        return
    }

    $names = [System.Collections.Generic.List[string]]::new()
    if ($ComputerName) { $names.AddRange([string[]]$ComputerName) }
    if ($InputFile) { Get-Content -LiteralPath $InputFile | Where-Object { $_.Trim() } | ForEach-Object { $names.Add($_.Trim()) } }
    if ($CollectionId) {
        Get-CimInstance -ComputerName $ProviderMachineName -Namespace "root\SMS\site_$SiteCode" -ErrorAction Stop `
            -Query "SELECT Name FROM SMS_FullCollectionMembership WHERE CollectionID = '$CollectionId'" |
            ForEach-Object { $names.Add($_.Name) }
    }
    $names = $names | Sort-Object -Unique
    if (-not $names) { Write-Warning 'No devices to target.'; return }
    Write-Verbose "Targeting $($names.Count) device(s) in $Mode mode."

    if ($Mode -eq 'Notification') {
        Connect-CMSite -SiteCode $SiteCode -ProviderMachineName $ProviderMachineName | Out-Null
        foreach ($n in $names) {
            if ($PSCmdlet.ShouldProcess($n, 'Invoke-CMClientNotification DownloadComputerPolicy')) {
                Invoke-CMClientNotification -DeviceName $n -ActionType DownloadComputerPolicy
            }
        }
        return
    }

    if (-not $PSCmdlet.ShouldProcess("$($names.Count) device(s)", 'Trigger Machine Policy Retrieval + Evaluation')) { return }

    $block = {
        param($c)
        $ids = '{00000000-0000-0000-0000-000000000021}', '{00000000-0000-0000-0000-000000000022}'
        try {
            foreach ($id in $ids) {
                Invoke-CimMethod -ComputerName $c -Namespace root\ccm -ClassName SMS_Client -MethodName TriggerSchedule `
                    -Arguments @{ sScheduleID = $id } -OperationTimeoutSec 30 -ErrorAction Stop | Out-Null
            }
            [pscustomobject]@{ ComputerName = $c; Result = 'Triggered' }
        } catch {
            [pscustomobject]@{ ComputerName = $c; Result = "Failed: $($_.Exception.Message)" }
        }
    }

    if ($PSVersionTable.PSVersion.Major -ge 7) {
        $text = $block.ToString()
        $names | ForEach-Object -Parallel { & ([scriptblock]::Create($using:text)) $_ } -ThrottleLimit $ThrottleLimit
    } else {
        foreach ($n in $names) { & $block $n }
    }
}