DirectoryService/Get-DSForest.ps1
<#
.SYNOPSIS Get Active Directory Forest information. .DESCRIPTION Gets Active Directory forest information for the forest the current host is a member of, a specified forest given it FQDN and supports the use of alternate credentials. .PARAMETER ComputerName Fully Qualified Name of a remote domain controller to connect to. .PARAMETER Credential Alternate credentials for retrieving forest information. .PARAMETER Forest Fully Qualified Name of a forest to get information on when running from a host joined to the domain. .EXAMPLE C:\PS> Get-DSForest Gets the forest for the domain the host is corrently joined to. .EXAMPLE C:\PS> Get-DSForest -ComputerName dc01.acmelabs.com -Credential (Get-Credential user1) Connect to a remote domain controller and get the forest for domain it manages using the provided credentials. .EXAMPLE C:\PS> Get-DSForest -ForestName frabrikan.com Gets the forest frabikan.com that the current domain has a trust relationship with. .OUTPUTS System.DirectoryServices.ActiveDirectory.Forest .NOTES This function is heavily dependent on DNS. The host running the function is highly recomended to be using the same DNS server as the domain whe are querying. #> function Get-DSForest { [CmdletBinding(DefaultParameterSetName = 'Current')] param( # Domain controller to connect to when not in a domain. [Parameter(ParameterSetName = 'Remote', Mandatory = $true)] [string] $ComputerName, # Credentials to use for getting forest information. [Parameter(ParameterSetName = 'OtherForest', Mandatory = $false)] [Parameter(ParameterSetName = 'Remote', Mandatory = $true)] [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, # Forest name. [Parameter(ParameterSetName = 'OtherForest', Mandatory = $true)] [string] $ForestName ) begin { } process { $sig = @" [DllImport("Netapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)] public static extern int NetGetJoinInformation(string server,out IntPtr domain,out int status); "@ switch ($PSCmdlet.ParameterSetName) { 'Current' { $type = Add-Type -MemberDefinition $sig -Name Win32Utils -Namespace NetGetJoinInformation -PassThru $ptr = [IntPtr]::Zero $joinstatus = 0 $type::NetGetJoinInformation($null, [ref] $ptr, [ref]$joinstatus) |Out-Null if ($joinstatus -eq 3){ $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() # Get sid for root domain. if ($ForestObject -ne $null) { $RootDN = "DC=$(($ForestObject.Name).replace('.',',DC='))" $DEObj = Get-DSDirectoryEntry -DistinguishedName $RootDN $Sid = (New-Object -TypeName System.Security.Principal.SecurityIdentifier($DEObj.objectSid.value,0)).value Add-Member -InputObject $ForestObject -MemberType NoteProperty -Name 'Sid' -Value $Sid } } else { throw 'This computer is not joined to a domain so no forest could be retrieved.' } } 'Remote' { $cArgs = @( 'DirectoryServer', $ComputerName, $Credential.UserName, $Credential.GetNetworkCredential().Password ) $typeName = 'DirectoryServices.ActiveDirectory.DirectoryContext' $context = New-Object $typeName $cArgs $ForestObject = [DirectoryServices.ActiveDirectory.Forest]::GetForest($context) # Get sid for root domain. $RootDN = "DC=$(($ForestObject.Name).replace('.',',DC='))" $DEObj = Get-DSDirectoryEntry -DistinguishedName $RootDN -ComputerName $ComputerName -Credential $Credential $Sid = (New-Object -TypeName System.Security.Principal.SecurityIdentifier($DEObj.objectSid.value,0)).value Add-Member -InputObject $ForestObject -MemberType NoteProperty -Name 'Sid' -Value $Sid } 'OtherForest' { if ($Credential.UserName -ne $null){ # Arguments to get forest with alternate credentials $cArgs = @( 'Forest', $ForestName, $Credential.UserName, $Credential.GetNetworkCredential().Password ) } else { # Arguments to only get forest with no alternate credentials $cArgs = @( 'Forest', $ForestName ) } $typeName = 'DirectoryServices.ActiveDirectory.DirectoryContext' $context = New-Object $typeName $cArgs $ForestObject = [DirectoryServices.ActiveDirectory.Forest]::GetForest($context) $RootDN = "DC=$(($ForestObject.Name).replace('.',',DC='))" if ($Credential.UserName -ne $null){ $DEObj = Get-DSDirectoryEntry -DistinguishedName $RootDN -Credential $Credential } else { $DEObj = Get-DSDirectoryEntry -DistinguishedName $RootDN } $Sid = (New-Object -TypeName System.Security.Principal.SecurityIdentifier($DEObj.objectSid.value,0)).value Add-Member -InputObject $ForestObject -MemberType NoteProperty -Name 'Sid' -Value $Sid } Default {} } $ForestObject } end { } } |