Home > OS >  powershell script to populate uidnumber problem with conversion to systm.Int32 value
powershell script to populate uidnumber problem with conversion to systm.Int32 value

Time:09-19

i'm trying to write a script to popolate uidnumber in active directory.

$SearchBase = "OU=test,DC=xxx,DC=local"
$lastuid = Get-ADUser -Filter * -searchbase $searchbase -Properties * | Where {($_.uidNumber -ne $null)} | select uidnumber | Measure-Object -Property uidnumber -Maximum | select maximum | 
Format-Wide
$i= $lastuid
$nouid = Get-ADUser -Filter * -searchbase $searchbase -Properties * | Where {($_.uidNumber -eq $null)} | select samaccountname
$nouid | %{Set-ADUser $_.samAccountName -add @{uidnumber=('{0:D4}' -f $i  )}}

This do not produce error but pupulate uidnumber starting from 0, ignoring lastuid. If i use

$i= $lastuid

produce error like

    "Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32". At C:\-\Documents\uid.ps1:16 char:15...  $nouid | %{Set-ADUser $_.samAccountName -replace @{uidnumber=([int]  ...
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 CategoryInfo          : InvalidArgument: (:) [], RuntimeException
 FullyQualifiedErrorId : ConvertToFinalInvalidCastException"

any suggestion?

CodePudding user response:

The command that determines the currently highest uidNumber is broken; replace it with the following:

[int] $lastuid = (
  Get-ADUser -Filter * -searchbase $searchbase -Properties uidnumber | 
  Measure-Object -Property uidnumber -Maximum
).Maximum

Note:

  • (...).Maximum, i.e. direct property access is used to obtain the maximum value from the Measure-Object call.

    • There is no need for select (Select-Object), and especially not Format-Wide - see next section.
  • There's no need for filtering out $null values with a Where (Where-Object) call, as Measure-Object will simply ignore them.

  • Using -Properties * is expensive and best avoided; here, you only need one (presumably) non-default property, uidnumber.


A separate problem is that *your code for updating the uidnumber field doesn't increment the number for each targeted user: [int] $i 1 assigns the same value to all; the simplest solution is to use :

$noUid | Set-ADUser -replace @{ uidnumber =   $i }

Note:

  • There is no need for % (ForEach-Object), as you can pipe the user objects stored in $noUid directly to Set-ADUser.

There's potential for additional optimization of your code, such as calling Get-ADUser -Filter * only once, assuming that all users objects fit into memory at once:

$withoutUid, $withtUid = 
  (Get-ADUser -Filter * -searchbase $searchbase -Properties uidnumber).
  Where({ $null -eq $_.uidnumber }, 'Split')

[int] $lastuid = ($withUid | Measure-Object -Property uidnumber -Maximum).Maximum

$withoutUid | Set-ADUser -replace @{ uidnumber =   $lastuid }

As for what you tried:

  • Format-* cmdlets such as Format-Wide emit output objects whose sole purpose is to provide formatting instructions to PowerShell's for-display output-formatting system. In short: only ever use Format-* cmdlets to format data for display, never for subsequent programmatic processing - see this answer for more information.

    • Apart from Format-Wide not representing the data you intended, it output multiple objects, which $lastuid = ... captured in an array. It is that array that caused the error you saw.
  • Omitting Format-Wide wouldn't suffice in your case, because select maximum (Select-Object maximum) also wouldn't work as intended: it would create an object with a .Maximum property, instead of directly emitting the value of the .Maximum property of the property returned by Measure-Object. For the latter you need Select-Object -ExpandProperty maximum - see this answer for more information.

  • Related