Posts RSS Comments RSS 117 Posts and 170 Comments till now

Archive for December, 2007

AD Replication Metadata (when did that change?)

There was a discussion on the NG about determining when a user was disabled. The initial request was to determine this based on whenChanged, but I thought that could be invalid as you can easily change an account after it was disabled. I can not think of a way to be sure, but the best way I can think of is to use the replication metadata on the attribute userAccountControl (the second bit is what determines if its disabled or not.) While it is possible to change the useraccountcontrol after a user is disabled it is unlikely.

More info for UserAccountControl bits
http://support.microsoft.com/kb/305144

Of course the next question was how do you check the Replication Metadata for an attribute on and AD object?

Enter Get-ADObjectREplicationMetadata.ps1

This uses

System.DirectoryServices.ActiveDirectory.DirectoryContext
- http://msdn2.microsoft.com/en-us/library/system.directoryservices.activedirectory.directorycontext.aspx
System.DirectoryServices.ActiveDirectory.DomainController
- http://msdn2.microsoft.com/en-gb/library/system.directoryservices.activedirectory.domaincontroller.aspx

  1. # Get-ADObjectREplicationMetadata.ps1
  2. # Brandon Shell (www.bsonposh.com)
  3. # Purpose: Get attribute(s) Replication Metadata from a Domain controller.
  4. Param($Domain,$objectDN,$property)
  5. # Sets Context to Domain for System.DirectoryServices.ActiveDirectory.DomainController
  6. $context = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain",$domain)
  7. # .NET Class that returns a Domain Controller for Specified Context
  8. $dc = [System.DirectoryServices.ActiveDirectory.DomainController]::findOne($context)
  9. # GetReplicationMetadata returns metadate from the DC for the DN specified.
  10. $meta = $dc.GetReplicationMetadata($objectDN)
  11. if($property){$meta | %{$_.$Property}}else{$meta}

This will return either all the metadata or just the metadata for a specific attribute. I should note that if you do not specify an attribute it returns all of them. You should expect to parse these as each attribute has a child object with the data in it.

All Attributes. The value can be found by .PropertyName

  1. PS# .\Get-ADObjectMetaData.ps1 ‘my.lab.domain’ ‘CN=TestUser,DC=my,dc=lab,dc=domain’
  2.  
  3. Name                           Value
  4. —-                           —–
  5. countrycode                    System.DirectoryServices.ActiveDirectory.AttributeMetadata
  6. cn                             System.DirectoryServices.ActiveDirectory.AttributeMetadata
  7. mail                           System.DirectoryServices.ActiveDirectory.AttributeMetadata
  8. scriptpath                     System.DirectoryServices.ActiveDirectory.AttributeMetadata
  9. ntsecuritydescriptor           System.DirectoryServices.ActiveDirectory.AttributeMetadata
  10. accountexpires                 System.DirectoryServices.ActiveDirectory.AttributeMetadata
  11. displayname                    System.DirectoryServices.ActiveDirectory.AttributeMetadata
  12. profilepath                    System.DirectoryServices.ActiveDirectory.AttributeMetadata
  13. primarygroupid                 System.DirectoryServices.ActiveDirectory.AttributeMetadata
  14. unicodepwd                     System.DirectoryServices.ActiveDirectory.AttributeMetadata
  15. objectclass                    System.DirectoryServices.ActiveDirectory.AttributeMetadata
  16. objectcategory                 System.DirectoryServices.ActiveDirectory.AttributeMetadata
  17. instancetype                   System.DirectoryServices.ActiveDirectory.AttributeMetadata
  18. homedrive                      System.DirectoryServices.ActiveDirectory.AttributeMetadata
  19. samaccounttype                 System.DirectoryServices.ActiveDirectory.AttributeMetadata
  20. homedirectory                  System.DirectoryServices.ActiveDirectory.AttributeMetadata
  21. whencreated                    System.DirectoryServices.ActiveDirectory.AttributeMetadata
  22. useraccountcontrol             System.DirectoryServices.ActiveDirectory.AttributeMetadata
  23. msmqsigncertificates           System.DirectoryServices.ActiveDirectory.AttributeMetadata
  24. dbcspwd                        System.DirectoryServices.ActiveDirectory.AttributeMetadata
  25. title                          System.DirectoryServices.ActiveDirectory.AttributeMetadata
  26. samaccountname                 System.DirectoryServices.ActiveDirectory.AttributeMetadata
  27. supplementalcredentials        System.DirectoryServices.ActiveDirectory.AttributeMetadata
  28. userparameters                 System.DirectoryServices.ActiveDirectory.AttributeMetadata
  29. givenname                      System.DirectoryServices.ActiveDirectory.AttributeMetadata
  30. description                    System.DirectoryServices.ActiveDirectory.AttributeMetadata
  31. lmpwdhistory                   System.DirectoryServices.ActiveDirectory.AttributeMetadata
  32. pwdlastset                     System.DirectoryServices.ActiveDirectory.AttributeMetadata
  33. msnpallowdialin                System.DirectoryServices.ActiveDirectory.AttributeMetadata
  34. codepage                       System.DirectoryServices.ActiveDirectory.AttributeMetadata
  35. name                           System.DirectoryServices.ActiveDirectory.AttributeMetadata
  36. ntpwdhistory                   System.DirectoryServices.ActiveDirectory.AttributeMetadata
  37. userprincipalname              System.DirectoryServices.ActiveDirectory.AttributeMetadata
  38. admincount                     System.DirectoryServices.ActiveDirectory.AttributeMetadata
  39. objectsid                      System.DirectoryServices.ActiveDirectory.AttributeMetadata
  40. sn                             System.DirectoryServices.ActiveDirectory.AttributeMetadata
  41. msmqdigests                    System.DirectoryServices.ActiveDirectory.AttributeMetadata
  42. logonhours                     System.DirectoryServices.ActiveDirectory.AttributeMetadata
  43. lastlogontimestamp             System.DirectoryServices.ActiveDirectory.AttributeMetadata

Here is a specific Attribute

  1. PS# .\Get-ADObjectMetaData.ps1 ‘my.lab.domain’ ‘CN=TestUser,DC=my,dc=lab,dc=domain’ ‘useraccountcontrol’
  2.  
  3. Name                        : userAccountControl
  4. Version                     : 8
  5. LastOriginatingChangeTime   : 9/15/2005 1:45:32 PM
  6. LastOriginatingInvocationId : eeaeb6f9-8422-dddd-as34-04d7bd779285
  7. OriginatingChangeUsn        : 47264036
  8. LocalChangeUsn              : 49555172
  9. OriginatingServer           : dc.my.lab.domain

Me, Dean and A couple of Admins Podcasting (what fun!)

I was lucky enough to spend some time with the ACOAP (A couple of Admins Podcasting) guys and a friend (and fellow MVP) Dean Wells. We had a blast just discussing the MVP program and Other MS programs.

The ‘after party’ was really fun, but we only had so much time for the actual podcast so it had to get trimmed. We hope to do another session with them.

Podcast Here
Episode 28 - MVP’s In The House
www.acoupleofadmins.com

More Info for Dean Wells and MSETechnology
www.msetechnology.com

Get-CitrixServerLoad (The power of objects in Citrix)

I watch the forums at BrianMadden.com because I use Powershell a lot for Citrix. This question was brought up.

Q: How could one:
- query “server load” on all servers part of the farm
- extract all server under a minimum server load
- apply an “Offline” load evaluator on the extracted servers (in order to make them unavailable on the farm)

I posted a script to do what they wanted, but then I got to thinking… while it did achieve the goal it wasn’t very Powershellish.

As I have said over and over. The glory of Powershell is the objects. So I decided to Post this entry showing what I would consider the Powershell way :)
Ideally you should just do this at the prompt

PS> Get-CitrixServers | where{$_.WinServerObject.Serverload -lt $load} | Set-CitrixLoadEvalutor “OffLine”

This is easy to achieve with the following scripts or even better make them functions!

Get-CitrixServers

  1. param($Server)
  2. $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeFarm",$Server)
  3. $mfarm = [system.Activator]::CreateInstance($type)
  4. $mfarm.Initialize(1)
  5. $mfarm.zones | foreach-Object{$_.OnlineServers}

Set-CitrixLoadEvalutor

  1. Param($server,$LoadEvaluator = "MFDefaultLE",[switch]$Verbose)
  2. #NOTE: This only work for 4.0 and 4.5
  3. if($verbose){$verbosepreference = "Continue"}
  4.  
  5. function Set-LE{
  6.     Param($mySrv)
  7.     # Getting Current LE
  8.     write-Verbose "   + Set-LE called : $($mySrv.ServerName)"
  9.     $le = $mfServer.AttachedLE
  10.     $le.LoadData(1)
  11.     Write-Verbose "     - Old Evaluator: $($le.LEName)"
  12.     Write-Verbose "     - Setting to $LoadEvaluator"
  13.  
  14.     # Assigning New LE
  15.     $mySrv.AttachLEByName($LoadEvaluator)
  16.  
  17.     # Checking LE
  18.     $le = $mySrv.AttachedLE
  19.     $le.LoadData(1)
  20.     Write-Verbose "     - Load Evaluator Set to $($le.LEName)"
  21.  
  22. }
  23.  
  24. if($Server)
  25. {
  26.     # Loading Server Object
  27.     Write-Verbose " + Processing $Server"
  28.     $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$Server)
  29.     $mfServer = [system.Activator]::CreateInstance($type)
  30.     $mfServer.Initialize(6,$Server)
  31.     Write-Verbose "   - Calling Set-LE"
  32.     Set-LE $mfServer
  33. }
  34.  
  35. if($list)
  36. {
  37.     foreach($Srv in (Get-Content $list))
  38.     {
  39.         Write-Verbose " + Processing $Srv"
  40.         # Loading Server Object
  41.         Write-Verbose "   - Getting Citrix Object"
  42.         $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$Srv)
  43.         $mfServer = [system.Activator]::CreateInstance($type)
  44.         $mfServer.Initialize(6,$Srv)
  45.         Write-Verbose "   - Calling Set-LE"
  46.         Set-LE $mfServer
  47.     }
  48. }
  49.  
  50. if($input)
  51. {
  52.     foreach($Srv in $input)
  53.     {
  54.         Write-Verbose     " + Processing $Srv"
  55.         if($Srv.ServerName)
  56.         {
  57.             Write-Verbose "   - Input is a Citrix Server: $Srv"
  58.             Write-Verbose "   - Calling Set-LE"
  59.             Set-LE $Srv
  60.         }
  61.         else
  62.         {
  63.             Write-Verbose "   - Input: $Srv"
  64.             # Loading Server Object
  65.             Write-Verbose "   - Getting Citrix Object"
  66.             $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$Srv)
  67.             $mfServer = [system.Activator]::CreateInstance($type)
  68.             $mfServer.Initialize(6,$Srv)
  69.             Write-Verbose "   - Calling Set-LE"
  70.             Set-LE $mfServer
  71.         }
  72.     }
  73. }

This was the all in one that I posted

  1. Param($Server,$minLoad = 1000,$LoadEval,[switch]$verbose)
  2. if($verbose){$verbosepreference = "continue"}
  3. function Get-CitrixFarm{
  4.     param($Srv)
  5.     $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeFarm",$Srv)
  6.     $mfarm = [system.Activator]::CreateInstance($type)
  7.     $mfarm.Initialize(1)
  8.     Write-Verbose "Loading Farm $($mFarm.FarmName)"
  9.     return $mFarm
  10. }
  11. function Set-CitrixLoadEvalutor{
  12.     Param($server,$LoadEvaluator = "MFDefaultLE")
  13.  
  14.     # Loading Server Object
  15.     $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$Server)
  16.     $mfServer = [system.Activator]::CreateInstance($type)
  17.     $mfServer.Initialize(6,$Server)
  18.  
  19.     # Getting Current LE
  20.     $le = $mfServer.AttachedLE
  21.     $le.LoadData(1)
  22.     Write-Verbose "Old Evaluator: $($le.LEName)"
  23.     Write-Verbose "Setting Load Evaluator on $server to $LoadEvaluator"
  24.  
  25.     # Assigning New LE
  26.     $mfServer.AttachLEByName($LoadEvaluator)
  27.  
  28.     # Checking LE
  29.     $le = $mfServer.AttachedLE
  30.     $le.LoadData(1)
  31.     Write-Verbose "Load Evaluator Set to $($le.LEName)"
  32. }
  33.  
  34. $farm = Get-CitrixFarm $Server
  35. foreach($ctxServer in $farm.Servers)
  36. {
  37.     $load = $ctxServer.WinServerObject.Serverload
  38.     Write-Host ("{0,-15} :: {1}" -f $ctxServer.ServerName,$load)
  39.     if($load -lt $minLoad)
  40.     {
  41.         Write-Verbose "Setting Offline Load Eval"
  42.         if($LoadEval){Set-CitrixLoadEvalutor $ctxServer.ServerName $LoadEval}
  43.     }
  44. }