Posts RSS Comments RSS 249 Posts and 391 Comments till now

Archive for June, 2009

blog: Discovery options with R2 AD Cmdlets

Last week I talked about how to "discover" information using the built in .NET classes for ActiveDirectory. This week I would like to show how you can do similar things with the ActiveDirectory cmdlets that ship with Win7 and R2.

The first task we discussed was getting Forest information like Domains, Sites, ForestMode, RootDomain, and Forest masters.

With .NET we do this
  1. $Forest = [DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
With the cmdlets we do this
  1. $Forest = Get-ADForest

Next we discussed getting Domain information like Domain Controllers, DomainMode, Domain Masters, and Forest Root.
  1. $Domain = [DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
With the cmdlets we do this
  1. $Domain = Get-ADDomain

Now the object we get back is slightly different so lets take a look

First lets look at what $Forest has to offer
  1. PS C:UsersAdministrator> $Forest
  2.  
  3. ApplicationPartitions : {}
  4. CrossForestReferences : {}
  5. DomainNamingMaster : Win2K8R2DC1.R2.Dev.Lab
  6. Domains : {R2.Dev.Lab}
  7. ForestMode : Windows2008R2Forest
  8. GlobalCatalogs : {Win2K8R2DC1.R2.Dev.Lab}
  9. Name : R2.Dev.Lab
  10. PartitionsContainer : CN=Partitions,CN=Configuration,DC=R2,DC=Dev,DC=Lab
  11. PSShowComputerName : {}
  12. RootDomain : R2.Dev.Lab
  13. SchemaMaster : Win2K8R2DC1.R2.Dev.Lab
  14. Sites : {Default-First-Site-Name}
  15. SPNSuffixes : {}
  16. UPNSuffixes : {}
  17. WriteErrorStream : {}

Finally, Lets look at $Domain
  1. PS C:UsersAdministrator> $domain
  2.  
  3. AllowedDNSSuffixes : {}
  4. ChildDomains : {}
  5. ComputersContainer : CN=Computers,DC=R2,DC=Dev,DC=Lab
  6. DeletedObjectsContainer : CN=Deleted Objects,DC=R2,DC=Dev,DC=Lab
  7. DistinguishedName : DC=R2,DC=Dev,DC=Lab
  8. DNSRoot : R2.Dev.Lab
  9. DomainControllersContainer : OU=Domain Controllers,DC=R2,DC=Dev,DC=Lab
  10. DomainMode : Windows2008R2Domain
  11. DomainSID : S-1-5-21-4244231903-4101880959-1987002231
  12. ForeignSecurityPrincipalsContainer : CN=ForeignSecurityPrincipals,DC=R2,DC=Dev,DC=Lab
  13. Forest : R2.Dev.Lab
  14. InfrastructureMaster : Win2K8R2DC1.R2.Dev.Lab
  15. LastLogonReplicationInterval :
  16. LinkedGroupPolicyObjects : {CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,CN=System,DC=R2,DC=Dev,DC=Lab}
  17. LostAndFoundContainer : CN=LostAndFound,DC=R2,DC=Dev,DC=Lab
  18. ManagedBy :
  19. Name : R2
  20. NetBIOSName : R2
  21. ObjectClass : domainDNS
  22. ObjectGUID : c2d8e67d-2a49-4352-a795-de2b6508b1dc
  23. ParentDomain :
  24. PDCEmulator : Win2K8R2DC1.R2.Dev.Lab
  25. QuotasContainer : CN=NTDS Quotas,DC=R2,DC=Dev,DC=Lab
  26. ReadOnlyReplicaDirectoryServers : {}
  27. ReplicaDirectoryServers : {Win2K8R2DC1.R2.Dev.Lab}
  28. RIDMaster : Win2K8R2DC1.R2.Dev.Lab
  29. SubordinateReferences : {CN=Configuration,DC=R2,DC=Dev,DC=Lab}
  30. SystemsContainer : CN=System,DC=R2,DC=Dev,DC=Lab
  31. UsersContainer : CN=Users,DC=R2,DC=Dev,DC=Lab

Here are some more specific examples on how to use these variables:

To see the forest roles
  1. $forest | select SchemaMaster,DomainNamingMaster
To see the domain roles
  1. $domain | select PDCEmulator,RIDMaster,InfrastructureMaster
To see what application partitions your forest has
  1. $forest.ApplicationPartitions

NOTE: you can use this command to see all the AD Cmdlets have to offer
  1. get-command -Module ActiveDirectory

blog: Avoid hardcoding in scripts. Here are some Simple discovery options in Powershell

When writing scripts I have always been a fan of making them as generic as possible. This may make the script a tad more complicated, but it allows it to be dynamic and also allows you to share these scripts between environments (i.e. Lab, QC, Production.) Basically we want to avoid hardcoding Domains, Domain Controllers, OUs, Containers, and site info.

Below I provide some simple examples of getting this information dynamically. This will allow you to discover the information instead of hardcoding it in the script.

To get forest information like Domains, Sites, ForestMode, RootDomain, and Forest masters you can use this:
  1. $Forest = [DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()

To get Domain information like Domain Controllers, DomainMode, Domain Masters, and Forest Root.
  1. $Domain = [DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()

To get the current Site information for the local machine like Subnets, Sitelinks, Location, Bridgehead Servers, and Domain Controllers.
  1. $MySite = [DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite()

With these variables you can find all the Active Directory infrastructure information you could possibly want.

Here are some more specific examples on how to use these variables:

To find all your Global Catalogs in the forest
  1. $Forest.GlobalCatalogs

To find all the Domain Controllers in the current domain
  1. $Domain.DomainControllers

To see what application partitions your forest has
  1. $forest.ApplicationPartitions

To see the forest roles
  1. $forest | select SchemaRoleOwner,NamingRoleOwner

To see the domain roles
  1. $domain | select PDCRoleOwner,RidRoleOwner,InfrastructureRoleOwner

To see the subnets in the current site
  1. $MySite.subnets

To see the bridgehead Servers
  1. $MySite.BridgeheadServers

ADMG (aka ADWS for none 2008 R2 )

As you may or may not know the AD cmdlets that ship with Win7 and Windows 2008 R2 use the ADWS (Active Directory Web Service) but fear not! MS release ADMG (Active Directory Management Gateway) that allows you to use the AD cmdlets and ADAC (Active Directory Administrative Center)

Download here: http://support.microsoft.com/default.aspx?scid=kb;en-us;969041&sd=rss&spid=12925

For more information about Active Directory Web Services: http://technet.microsoft.com/en-us/library/dd391908.aspx

For more information about the Active Directory Module for Windows PowerShell: http://technet.microsoft.com/en-us/library/dd378937.aspx

blog: More details on Select-Object

I often to get asked what I mean by "Select-Object changes the object type." I believe this one of those things that is easier to illustrate than just explain. First let me show the object type Change
  1. PS> ($dir = Get-item C:\temp).Gettype()
  2.  
  3. IsPublic IsSerial Name BaseType
  4. -------- -------- ---- --------
  5. True True DirectoryInfo System.IO.FileSystemInfo
  6.  
  7. PS> ($dir = Get-item C:\temp | select-Object Fullname,Name,Parent).Gettype()
  8.  
  9. IsPublic IsSerial Name BaseType
  10. -------- -------- ---- --------
  11. True False PSCustomObject System.Object
  12.  
  13. Even if you specifiy PSBASE you have new object type.
  14.  
  15. PS> ($dir = Get-item C:\temp).psbase.Gettype()
  16.  
  17. IsPublic IsSerial Name BaseType
  18. -------- -------- ---- --------
  19. True True DirectoryInfo System.IO.FileSystemInfo
  20.  
  21. PS> ($dir = Get-item C:\temp | select-Object Fullname,Name,Parent).psbase.Gettype()
  22.  
  23. IsPublic IsSerial Name BaseType
  24. -------- -------- ---- --------
  25. True False PSCustomObject System.Object
Now look at what you lose using this method.

First you will notice you have 21 items returned from Get-Member (I only included Properties for simplicity, but methods work the same way.)
  1. PS> get-item C:\temp | Get-Member -MemberType Properties | ft Name
  2.  
  3. Name
  4. ----
  5. PSChildName
  6. PSDrive
  7. PSIsContainer
  8. PSParentPath
  9. PSPath
  10. PSProvider
  11. Attributes
  12. CreationTime
  13. CreationTimeUtc
  14. Exists
  15. Extension
  16. FullName
  17. LastAccessTime
  18. LastAccessTimeUtc
  19. LastWriteTime
  20. LastWriteTimeUtc
  21. Name
  22. Parent
  23. Root
  24. Mode
  25. ReparsePoint
  26.  
  27. ## After piping to Select-Object you now only have 3
  28.  
  29. PS> Get-Item C:\temp | Select-Object Name,Fullname,Parent | Get-Member -MemberType Properties | ft name
  30.  
  31. Name
  32. ----
  33. FullName
  34. Name
  35. Parent
  36.  
  37. ## Now.. methods before "Conversion"
  38.  
  39. PS> Get-item C:\temp | Get-Member -MemberType Methods | ft name
  40.  
  41. Name
  42. ----
  43. Create
  44. CreateObjRef
  45. CreateSubdirectory
  46. Delete
  47. Equals
  48. GetAccessControl
  49. GetDirectories
  50. GetFiles
  51. GetFileSystemInfos
  52. GetHashCode
  53. GetLifetimeService
  54. GetObjectData
  55. GetType
  56. get_Attributes
  57. get_CreationTime
  58. get_CreationTimeUtc
  59. get_Exists
  60. get_Extension
  61. get_FullName
  62. get_LastAccessTime
  63. get_LastAccessTimeUtc
  64. get_LastWriteTime
  65. get_LastWriteTimeUtc
  66. get_Name
  67. get_Parent
  68. get_Root
  69. InitializeLifetimeService
  70. MoveTo
  71. Refresh
  72. SetAccessControl
  73. set_Attributes
  74. set_CreationTime
  75. set_CreationTimeUtc
  76. set_LastAccessTime
  77. set_LastAccessTimeUtc
  78. set_LastWriteTime
  79. set_LastWriteTimeUtc
  80. ToString
  81.  
  82. ## After
  83.  
  84. PS> Get-item C:\temp | select-object FullName,Name,Parent | Get-Member -MemberType Methods | ft name
  85.  
  86. Name
  87. ----
  88. Equals
  89. GetHashCode
  90. GetType
  91. ToString
As you can see... Effectively they are all gone on the new object. When I first experienced this.. I thought maybe the methods were just hidden... but try to access them
  1. PS> $dir = Get-Item C:\temp
  2. PS> $dir.GetDirectories()
  3.  
  4. Mode LastWriteTime Length Name
  5. ---- ------------- ------ ----
  6. d---- 5/22/2007 1:58 PM Console
  7. d---- 5/10/2007 4:36 PM test32
  8.  
  9. PS> $dir = Get-Item C:\temp | Select-Object FullName,Name,Parent
  10. PS> $dir.GetDirectories()
  11. Method invocation failed because [System.Management.Automation.PSCustomObject] doesn't contain a method named 'GetDirectories'.
  12. At line:1 char:20
I want to be clear... This is not a bug. Its not even a bad idea. I find it useful, but I think it confuses a lot of people. Like most people I didn't read the help before I used it or I would have seen this excerpt from get-help Select-Object:
If you use Select-Object to select specified properties, it copies the values of those properties from the input objects and creates new objects that have the specified properties and copied values.
So, the moral of the story is don't be shocked when your object changes after using Select-Object. Embrace the change :)

More details leaked about the XenApp SDK for Powershell

XENAPP SNEAK PEEK – PowerShell Commands for XenApp Tech Preview

blog: Creating Custom Objects with “Select-Object”

Once you grab a hold of the "Object" concept in Powershell it brings a whole new light to scripting. The power that is at your finger tips is basically limitless, but to harness this power you not only need to know how to use objects but also create them as well.

Here is my way of creating objects.
  1. $myobj = ""| select-Object Server,Result
IMO this is the simplest way to create custom objects.

Effectively what happens is you set your $myobj to a empty string and pipe to select-object. While this may seem odd, its actually quite useful because what select-object returns is a PSCustomObject with the properties that you specify. This allows you to create you object with defined properties that you can fill out later in one line.

The "proper" way to create a custom object is to do this.
  1. $myobj = new-object System.Object
  2. $myobj | add-member -membertype noteproperty -name Server -value $sname
  3. $myobj | add-member -membertype noteproperty -name Result -value $sResult
While this isn't that much more work... I think its harder to read (and more typing) so I go with this shortcut
  1. $myobj = "" | select-Object Server,Result
  2. $myobj.Server = $sname
  3. $myobj.Result = $sResult
I will give you one warning about select-object (not related, but while I'm on this subject.) select-object does Change the object type and therefore you lose methods and properties you may expect to be there. I have seen numerous post on the news groups that have this exact problem.

If you pipe Get-ChildItem to Get-member you get tons of methods and properties for both System.IO.FileInfo and System.IO.DirectoryInfo
  1. PS> get-childitem | gm
Now pipe it to select-object and do a Get-Member
  1. PS> (get-childitem | select-object Fullname,length) | gm
  2.  
  3. TypeName: System.Management.Automation.PSCustomObject
  4.  
  5. Name MemberType Definition
  6. ---- ---------- ----------
  7. Equals Method System.Boolean Equals(Object obj)
  8. GetHashCode Method System.Int32 GetHashCode()
  9. GetType Method System.Type GetType()
  10. ToString Method System.String ToString()
  11. FullName NoteProperty System.String FullName=C:WindowsSystem32409
  12. length NoteProperty length=null
Just be careful to remember this. I actually avoid using select-object to filter objects simply because of this. Instead... I just use the properties.

Win7 to ship Oct 22 2009

It appears #Win7 to be in consumers hands by OCT 22… Click Here.

Perhaps even RTM as early as next month.