ms-foxworks Thanks! Since i posted yesterday i have been able to get some code working, even the foreach-object -parallel. here is what i've got:
$objComputers = Invoke-Sqlcmd -ServerInstance $Siteserver -Query "select resourceid,Netbios_Name0,ADAttributefromDiscovery10,ADAttributefromDiscovery20 from v_R_System" -Database CM_DB
$objSMSMachineSettingsClass = Get-CimClass -ComputerName $Siteserver -Namespace "root\sms\site_$SiteCode" -ClassName "sms_machinesettings"
$objSMSMachineSettings = Get-CIMInstance -computername $Siteserver -namespace "root\sms\site_$SiteCode" -class $objSMSMachineSettingsClass.CimClassName
$varclass = Get-CimClass -ComputerName $Siteserver -Namespace "root\sms\site_$SiteCode" -ClassName "sms_machinevariable"
$objComputers | ForEach-Object -ThrottleLimit 10 -Parallel {
try {
$objComputer = $_
$objMachineSettings = $USING:objSMSMachineSettings | Where-Object { $_.ResourceID -eq $objComputer.ResourceID }
$objMachineSettingsValues = $objMachineSettings | Get-CIMInstance
foreach ($attr in ('ADAttributefromDiscovery10', 'ADAttributefromDiscovery20')) {
$var = ($objMachineSettingsValues.MachineVariables | Where-Object { $_.name -eq $attr })
If ( !$var -or ($objcomputer.$attr -ne $var.value)) {
$newcompvar = New-CimInstance -CimClass $using:varclass -ClientOnly
$newcompvar.Name = $attr
$newcompvar.Value = $objcomputer.$attr
$newcompvar.IsMasked = $false
$objMachineSettingsValues.MachineVariables = $objMachineSettingsValues.MachineVariables + $newcompvar
}
}
Set-CimInstance -CimInstance $objMachineSettingsValues | out-null
}
catch {
$_
}
}
i found i can get the classes and get all of the machine settings, then the class for the machine variable and build variables from that. and even set them. we have about 17,500 clients and if i put 'top 100' in the sql query at the top it parallelizes it and works through all 100 in about 28 seconds, which is pretty good. using the cmdlet to set them one at a time is about 3 secs per endpoint. i thought WMI would be faster so that's how i started down this rabbit hole.
as you say SMS_MachineVariable is only a type reference and it messed me up for a good bit because with WMI you can make a variable with the typecast on the path and it just makes it. the trouble i had was that when i tried to do that with CIM it would make the instance in WMI on the site server the first time and then complain that it already existed in subsequent invocations, and all i needed was the type on a variable locally. i found the -clientonly switch and that unlocked the whole thing for me yesterday.
the parallelization though makes it hard to know how far it gets. i think i get to some limit though because at just shy of running for an hour and a half, i don't know how many it's worked through and it starts failing with errors like unable to find the property 'name' on
$objMachineSettingsValues when it had worked on untold hundreds or thousands for the last 90 minutes. so i don't think it's the code, but some other limit. memory maybe? i dunno. i also don't know if this is even right, but it works and it writes those AD attributes we get from discovery into machine variables correctly.
i will try the adminservice to see if i can get it to complete that way, but i have a sense it will be slower.
speed is a thing for this because it will have to run regularly to get the AD attributes into variables on anything that moves in AD or new endpoints. we use the data in task sequences to let the endpoints know what department they belong to.
i'm close, i feel like, but not quite all the way through.