question

otip-1132 avatar image
0 Votes"
otip-1132 asked otip-1132 answered

Set and Get AD-Computer extensionattribute in powershell

Hi,

I found how to set an extension attribute for a computer
First it must be cleared
Set-ADcomputer –Identity computername -Clear "extensionAttribute15"

Then I can fill it
Set-ADcomputer -Identity computername -Add @{extensionAttribute15 = "anystring"}

It becomes tricky when I then try to extract
$value = Get-ADcomputer -identity KRKL0590 -Properties extensionAttribute15 | Select-Object extensionAttribute15

$value
@{extensionAttribute15=12/06/2021 00:00:00} (my script actually pushed a date in me extensionAtribute15)

$value.extensionAttribute15
gives nothing.

It looks like a hash but I can't manipulate it like it, it would seem.
I don't find how to extract only the value of extensionAttribute15.

Any help appreciated.

Thank you.



windows-server-powershellwindows-active-directory
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hello,

Is it possible to tell us how you put the value in the extensionAttribute15 ?
I've tried to put some value in it and it works fine for me :
153317-image.png

Regards,

0 Votes 0 ·
image.png (78.9 KiB)

It's in my first post :
Then I can fill it
Set-ADcomputer -Identity computername -Add @{extensionAttribute15 = "anystring"}

Can you show $value.gettype() ?

0 Votes 0 ·

Below the command
153326-image.png


0 Votes 0 ·
image.png (180.5 KiB)
otip-1132 avatar image
0 Votes"
otip-1132 answered otip-1132 edited

The code is this one at the moment. There are other corrections to do I know.

 $ComputersWithManagedBy = get-adcomputer -ldapfilter '(managedby=*)' -properties name, managedby | select-object name, managedby
    
 $currentday = (Get-Date).ToUniversalTime()  
 $validedate = (Get-Date).adddays(7).ToUniversalTime()        
    
 Foreach ($CPT in $ComputersWithManagedBy){
    
     $ExpiryDate = Get-ADcomputer -identity $CPT -Properties extensionAttribute15 | Select-Object extensionAttribute15
    
     #struggling here with the date format
     if ($ExpiryDate -gt $validedate){
     Write-Host "Date is more than 7 days. Correcting to within 7 days. Maximum accepted value."
     Set-ADcomputer –Identity $CPT -Clear "extensionAttribute15"
     Set-ADcomputer -Identity $CPT -Add @{extensionAttribute15 = "$validedate"}
     }elseif($ExpiryDate -le $currentday ) {
             write-host "Emptying Managed by field"
             #some code
         }else{ 
             write-host "Date is inferior we don't take action"
    
     }
 }
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered

Your first problem is on line #8. When you use the "Select-Object" cmdlet the object that's returned is a PSCustomObject with a NoteProperty named "extentionAttribute15". To get the actual value you'd use $ExpiryDate.extentionAttribute15. You can get the actual value (without the creation of a PSCustomObject) by doing this: Select-Object -Expand extentionAttribute15.

The next problem is on line #11. Even by using the "-Expand" technique you're left with a string value, not a DateTime object in $ExpiryDate. Comparing dates using strings is subject to quite a few problems that lead to inaccuracies and incorrect results. You should cast $ExpiryDate as a "[DateTime]" object.

Line #14 should 1) remove the surrounding quotation marks from the $validedate, and 2) you should probably drop the time portion of the $validedate object before you store it: $validedate.Date.ToString("MM/dd/yyyy") -- unless the time of day is important (which it probably isn't).

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

otip-1132 avatar image
0 Votes"
otip-1132 answered otip-1132 edited

Hi Rich,

thank you so much for all this. I will review and come back to you.

There was another issue on line 8. $CPT.name in Get-ADComputer

I also had to deal with potential empty value.

Here is the corrected and working script. Thank you so much. I'll later had a test for searching "NEVER" string in my attribute. And make it run on multiple domains :)

 $ComputersWithManagedBy = get-adcomputer -ldapfilter '(managedby=*)' -properties name, managedby, extensionAttribute15 | select-object name, managedby, extensionAttribute15
    
 $currentday = (Get-Date).ToUniversalTime()  
 $validedate = (Get-Date).adddays(7).ToUniversalTime()        
    
 Foreach ($CPT in $ComputersWithManagedBy){
    
     $ExpiryDate = Get-ADcomputer -identity $CPT.name -Properties extensionAttribute15 | Select-Object -expand extensionAttribute15
    
     if(!$ExpiryDate){
     Write-Host "Null not allowed. Correcting to within 7 days. Maximum accepted value." -ForegroundColor DarkRed
     Set-ADcomputer –Identity $CPT.name -Clear "extensionAttribute15" -WhatIf
     Set-ADcomputer -Identity $CPT.name -Add @{extensionAttribute15 = $validedate.Date.ToString("MM/dd/yyyy")} -whatif
     } else {
     [datetime]$ExpiryDate 
       
         if ($ExpiryDate -gt $validedate){
         Write-Host "Date is more than 7 days. Correcting to within 7 days. Maximum accepted value." -ForegroundColor Red
         Set-ADcomputer –Identity $CPT.name -Clear "extensionAttribute15" -WhatIf
         Set-ADcomputer -Identity $CPT.name -Add @{extensionAttribute15 = $validedate.Date.ToString("MM/dd/yyyy")} -WhatIf
         }elseif($ExpiryDate -le $currentday ) {
                 write-host "Emptying Managed by field for $($CPT.name)" -ForegroundColor Yellow
                 #some code
             }else{ 
                 write-host "Date is inferior to 7 days we don't take action for $($CPT.name)" -ForegroundColor Green
         }#end if
     }#end if
 }#end foreach



· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Dealing with a data set that may have "empty" values isn't difficult. In this case, replace line #7 with:

 if ($CPT.Trim().Length -lt 1){ continue }
0 Votes 0 ·

Thank you Rich for this proposition.
However I don't want to continue if empty. I want to force a value if empty. So I believe my code would be right for that purpose. What do you think?

I have one last thig to manage which is the case where extensionattribute15 is not NEVER, not empty and not a data. Let say the value is Eyjafjallajökull (Icelandic volcano :) )

My script would try to convert that to a date and most probably generate an error. How should I handle that? I thought about using Try Catch. But I feel like it's the right path to my solution. I want to replace these random values the same way I replace empty values.

I saw this, but not sure what to do with it in my case. https://stackoverflow.com/questions/2014820/how-do-i-check-that-a-string-contains-a-date

Thanks

PS : I'm also thinking to replace the IFs and elseif by this switch as this :
switch($someString.ToLower())
{
{($ -eq "y") -or ($ -eq "yes")} { "You entered Yes." }
default { "You entered No." }
}

feels cleaner

0 Votes 0 ·
RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered

Why would the "name" property of a computer object be empty? And why, it you found one, would you want to use an empty value as the identity value in Get-ADComputer? I'm not even sure I understand why you're using a Select-Object cmdlet on line #1 -- the computer objects returned by the Get-ADComputer have the properties you need.

Line #8 wouldn't need the Get-ADComputer cmdlet if you removed the Select-Object from line #1 because you'd be working with a computer object in the $CPT variable. All you'd need would be the "$ExpiryDate =Select-Object -Expand expansionAttribute 15".

I think you're confusing the "$CPT.name" being empty with $ExpiryDate not being populated.

For your how-to question about dates, try something like this:

 $ExpiryDate = "Eyjafjallajökull"
 Try{
     $ExpiryDate = [DateTime]$ExpiryDate
 }
 Catch{
     $ExpiryDate = (Get-Date).AddDays(90).Date.ToString("MM/dd/yyyy")
 }
 $ExpiryDate
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

otip-1132 avatar image
0 Votes"
otip-1132 answered

What I check for emptiness or wrong value is the extensionattribute15

I'll review all you comment and try to improve my code. thank you

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered RichMatheisen-8856 edited

See if this is close to your requirements:

 $WHATIF = $true
        
  $currentday = (Get-Date).ToUniversalTime().Date
  $validedate = (Get-Date).adddays(7).ToUniversalTime().Date
            
  Get-ADComputer -ldapfilter '(managedby=*)' -properties name, managedby, extensionAttribute15 |
      ForEach-Object{
          $ExpiryDate = $_ | Select-Object -expand extensionAttribute15
          $dn = $_.distinguishedname     # needed in "Catch" block
          if(-not $ExpiryDate){
              Write-Host "Null not allowed. Correcting to within 7 days. Maximum accepted value." -ForegroundColor DarkRed
              Set-ADcomputer -Identity $_.distinguishedName -Clear "extensionAttribute15" -WhatIf:$WHATIF
              Set-ADcomputer -Identity $_.distinguishedName -Add @{extensionAttribute15 = $validedate.ToString("MM/dd/yyyy")} -WhatIf:$WHATIF
          } 
          else {
              Try{
                  $ExpiryDate = [datetime]$ExpiryDate
                  if ($ExpiryDate -gt $validedate){
                      Write-Host "Date is more than 7 days. Correcting to within 7 days. Maximum accepted value." -ForegroundColor Red
                      Set-ADcomputer -Identity $_.distinguishedName -Clear "extensionAttribute15" -WhatIf:$WHATIF
                      Set-ADcomputer -Identity $_.distinguishedName -Add @{extensionAttribute15 = $validedate.Date.ToString("MM/dd/yyyy")} -WhatIf:$WHATIF
                  }
                  elseif($ExpiryDate -le $currentday ) {
                      write-host "Emptying Managed by field for $($_.name)" -ForegroundColor Yellow
                      #some code
                  }
                  else{ 
                      write-host "Date is inferior to 7 days we don't take action for $($_.name)" -ForegroundColor Green
                  }
              }
              Catch{
                  Write-Host "Invalid expiry date found in extentionAttribute15. Correcting to +7 days from today."
                  Set-ADcomputer -Identity $dn -Clear "extensionAttribute15" -WhatIf:$WHATIF
                  Set-ADcomputer -Identity $dn -Add @{extensionAttribute15 = $validedate.ToString("MM/dd/yyyy")} -WhatIf:$WHATIF
              }
          }
      }   #end foreach


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

otip-1132 avatar image
0 Votes"
otip-1132 answered RichMatheisen-8856 edited

Hi Rich,

apart from ( typo on line 9 it looks great. Thank you again.

I have added some detailed information in all write-host to show the expirydate value and computer name so I can then search for my test computer.

however when testing the cases :
- Extensionattribute15 is empty => gets in the right test
- Extensionattribute15 is having a valid date (within the 7 days) => gets in the right test
- Extensionattribute15 is having a far date (further than 7 days) => get in the right test
- Extensionattribute15 is having a past date => gets in the right test
- Extensionattribute15 is having a "blablabla" value => gets in the right test BUT $ is lost in the process !! The first set with $DN works but the second one with $.Distinguedname fails saying it receives a null value (I could confirm that, hence my trick with $DN.

Do you know why $_.Distinguedname works find in the try but not in the catch section?

The code is now this :

 cls
 #activate simulation mode
 $WHATIF = $true
 $maxtime = 7
    
 #Get current day and maximum period for beeing an admin $maxtime day  
 $currentday = (Get-Date).ToUniversalTime().Date
 $validedate = (Get-Date).adddays($maxtime).ToUniversalTime().Date
    
 $DC = Get-ADDomainController -Discover
     
 [string] $DCName = $DC.Hostname
     
 write-host $DCName
    
 #Get the list of PCs worlwide with a content in ManagedBy field        
 Get-ADComputer -ldapfilter "(&(managedby=*)(name=NCYL3604))" -Server $DCName -properties name, managedby, extensionAttribute15 |
      ForEach-Object{
          $DN= $_.distinguishedName
          $ExpiryDate = $_ | Select-Object -expand extensionAttribute15
          if(-not $ExpiryDate){
              #Expiry date is empty
              Write-Host "Value of expiryDate is : $($ExpiryDate) for $($_.distinguishedName). Null not allowed. Correcting to within $($maxtime) days. Maximum accepted value." -ForegroundColor DarkRed
              Set-ADcomputer -Identity $_.distinguishedName -Clear "extensionAttribute15" -WhatIf:$WHATIF
              Set-ADcomputer -Identity $_.distinguishedName -Add @{extensionAttribute15 = $validedate.ToString("MM/dd/yyyy")} -WhatIf:$WHATIF
          } 
          else {
              Try{
                  #Expiry date is a date
                  $ExpiryDate = [datetime]$ExpiryDate
                  if ($ExpiryDate -gt $validedate){
                      #Expiry date is futher than next $($maxtime) days
                      Write-Host "Value of expiryDate is : $($ExpiryDate) for $($_.distinguishedName). Date is more than $($maxtime) days => Correcting to within $($maxtime) days." -ForegroundColor Red
                      Set-ADcomputer -Identity $_.distinguishedName -Clear "extensionAttribute15" -WhatIf:$WHATIF
                      Set-ADcomputer -Identity $_.distinguishedName -Add @{extensionAttribute15 = $validedate.Date.ToString("MM/dd/yyyy")} -WhatIf:$WHATIF
                  }
                  elseif($ExpiryDate -le $currentday ) {
                      #Expiry date is past
                      write-host "Value of expiryDate is : $($ExpiryDate) for $($_.distinguishedName). Date is in the past => Emptying Managed by field for $($_.name)" -ForegroundColor Yellow
                      #some code
                  }
                  else{ 
                      #Expiry date is withing the $maxtime days period
                      write-host "Value of expiryDate is : $($ExpiryDate) for $($_.distinguishedName). Date is inferior to $($maxtime) days => No action for $($_.name)" -ForegroundColor Green
                  }
              }
              Catch{
                  #Expiry date is a not a date
                  Write-Host "Value of expiryDate is : $($ExpiryDate) for $($_.distinguishedName). Invalid expiry date found in extentionAttribute15. Correcting to +$($maxtime) days from today."
                  write-host $DN
                  Set-ADcomputer -Identity $DN -Clear "extensionAttribute15" -WhatIf:$WHATIF
                  Set-ADcomputer -Identity $_.distinguishedName -Add @{extensionAttribute15 = $validedate.ToString("MM/dd/yyyy")} -WhatIf:$WHATIF
              }
          }
      }   #end foreach
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Sorry about the typo.

The reason you have a problem in the Catch block is that the variable $<underbar> no longer contains a computer object -- it's been replaced by the "Error" object that caused the exception.

I corrected both and updated the code I posted.

FYI, on line 52 of your code you need to replace the use of the distinguishedname property with the variable $DN as you did on line 51.

0 Votes 0 ·
otip-1132 avatar image
0 Votes"
otip-1132 answered

Yes I left line 52 it for demonstration.
Thank you for the explanation.

So final version is here ! (I use my $DN everywhere it's easier I fill).
Also I added a possibility to have NEVER in the extensionattribute15 to be able to handle the exceptions (there are always exception to the so called strict rules :/ ).
I will probably had some logging lines.
On v2 I might want to think if using Switch could simplify this code.
But still, I'm happy with it so far. Thanks again.

 cls
 #activate simulation mode
 $WHATIF = $true
 $maxtime = 7
    
 #Get current day and maximum period for beeing an admin $maxtime day  
 $currentday = (Get-Date).ToUniversalTime().Date
 $validedate = (Get-Date).adddays($maxtime).ToUniversalTime().Date
    
 $DC = Get-ADDomainController -Discover
     
 [string] $DCName = $DC.Hostname
     
 write-host $DCName
    
 #Get the list of PCs worldwide with a content in ManagedBy field        
 Get-ADComputer -ldapfilter "(&(managedby=*)(name=NCYL3604))" -Server $DCName -properties name, managedby, extensionAttribute15 |
 Get-ADComputer -ldapfilter "(managedby=*)" -Server $DCName -properties name, managedby, extensionAttribute15 |
      ForEach-Object{
          $DN= $_.distinguishedName
          $ExpiryDate = $_ | Select-Object -expand extensionAttribute15
          if(-not $ExpiryDate){
              #Expiry date is empty => correcting to 7 days
              Write-Host "Value of expiryDate is : $($ExpiryDate) (empty) for $($DN). Null not allowed. Correcting to within $($maxtime) days. Maximum accepted value." -ForegroundColor DarkRed -BackgroundColor Yellow
              Set-ADcomputer -Identity $DN -Clear "extensionAttribute15" -WhatIf:$WHATIF
              Set-ADcomputer -Identity $DN -Add @{extensionAttribute15 = $validedate.ToString("MM/dd/yyyy")} -WhatIf:$WHATIF
          } elseif($ExpiryDate -eq "NEVER"){
              #Expiry date is NEVER => No action
              write-host "Value of expiryDate is : $($ExpiryDate) for $($DN). Date is NEVER => No action for $($_.name)" -ForegroundColor Green
          } else {
              Try{
                  #Expiry date is a date
                  $ExpiryDate = [datetime]$ExpiryDate
                  if ($ExpiryDate -gt $validedate){
                      #Expiry date is further than next $($maxtime) days => correcting to 7 days
                      Write-Host "Value of expiryDate is : $($ExpiryDate) for $($DN). Date is more than $($maxtime) days => Correcting to within $($maxtime) days." -ForegroundColor Red
                      Set-ADcomputer -Identity $DN -Clear "extensionAttribute15" -WhatIf:$WHATIF
                      Set-ADcomputer -Identity $DN -Add @{extensionAttribute15 = $validedate.Date.ToString("MM/dd/yyyy")} -WhatIf:$WHATIF
                  }
                  elseif($ExpiryDate -le $currentday ) {
                      #Expiry date is in the past => Clearing Managedby and extensionAttribute15
                      write-host "Value of expiryDate is : $($ExpiryDate) for $($DN). Date is in the past => Emptying Managed by field for $($_.name)" -ForegroundColor Yellow
                      Set-ADcomputer -Identity $DN -Clear "extensionAttribute15" -WhatIf:$WHATIF
                      Set-ADcomputer -Identity $DN -Clear "managedby" -WhatIf:$WHATIF
                  }
                  else{ 
                      #Expiry date is within the $maxtime days period => No action
                      write-host "Value of expiryDate is : $($ExpiryDate) for $($DN). Date is inferior to $($maxtime) days => No action for $($_.name)" -ForegroundColor Green
                  }
              }
              Catch{
                  #Expiry date is a not a date => correcting to 7 days
                  Write-Host "Value of expiryDate is : $($ExpiryDate) for $($DN). Invalid expiry date found in extentionAttribute15. Correcting to +$($maxtime) days from today." -ForegroundColor red -BackgroundColor Yellow
                  Set-ADcomputer -Identity $DN -Clear "extensionAttribute15" -WhatIf:$WHATIF
                  Set-ADcomputer -Identity $DN -Add @{extensionAttribute15 = $validedate.ToString("MM/dd/yyyy")} -WhatIf:$WHATIF
              }
          }
      }   #end foreach
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.