You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1 line
7.1 KiB
1 line
7.1 KiB
## Global Variables ##
|
|
|
|
$DomainControllerName = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().FindDomainController().Name
|
|
|
|
## Functions ##
|
|
|
|
function Get-ADSite
|
|
{
|
|
|
|
[CmdletBinding(
|
|
ConfirmImpact="Low",
|
|
DefaultParameterSetName="Name"
|
|
)]
|
|
|
|
Param (
|
|
[Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true,ParameterSetName="Name")]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string] $Name,
|
|
|
|
[Parameter(Mandatory=$true,ParameterSetName="All")]
|
|
[switch] $All,
|
|
|
|
[Parameter(Mandatory=$true,ParameterSetName="Current")]
|
|
[switch] $Current,
|
|
|
|
[Parameter(Mandatory=$true,ParameterSetName="ByIPAddress")]
|
|
[System.Net.IPAddress] $IPAddress,
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[ValidateScript({
|
|
if (-not $_.Contains("."))
|
|
{
|
|
throw "The Name must be a FQDN"
|
|
}
|
|
return $true
|
|
})]
|
|
[string] $Server
|
|
)
|
|
|
|
begin {
|
|
$script:ctx = $null
|
|
try
|
|
{
|
|
if (-not $Server)
|
|
{
|
|
$script:Server = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().FindDomainController().Name
|
|
$script:ctx = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer", $script:Server)
|
|
}
|
|
else
|
|
{
|
|
$script:Server = $Server
|
|
$script:ctx = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer", $script:Server)
|
|
}
|
|
}
|
|
catch [Exception]
|
|
{
|
|
Write-Error $_
|
|
return
|
|
}
|
|
}
|
|
|
|
process {
|
|
$site = $null
|
|
try
|
|
{
|
|
switch ($pscmdlet.ParameterSetName)
|
|
{
|
|
"name"
|
|
{
|
|
[System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::FindByName($script:ctx, $name)
|
|
}
|
|
}
|
|
}
|
|
catch [Exception]
|
|
{
|
|
Write-Error -Exception $_.Exception -Message "Could not get the site / sites"
|
|
}
|
|
}
|
|
|
|
end { }
|
|
}
|
|
|
|
function GetSingleDomainController
|
|
{
|
|
param(
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateScript({
|
|
if (-not $_.Contains("."))
|
|
{
|
|
throw "The Name must be a FQDN"
|
|
}
|
|
return $true
|
|
})]
|
|
[string] $DomainControllerName
|
|
)
|
|
|
|
$rootDSE = [adsi]"LDAP://$script:server/rootDSE"
|
|
|
|
$ds = New-Object System.DirectoryServices.DirectorySearcher
|
|
$ds.SearchRoot = "LDAP://$script:server/CN=Sites,$($rootDSE.configurationNamingContext)"
|
|
$ds.Filter = "(&(objectclass=server)(dNSHostName=$DomainControllerName))"
|
|
|
|
try
|
|
{
|
|
$serverDn = $ds.FindOne().GetDirectoryEntry().DistinguishedName.Value
|
|
$siteDn = $serverDn.Substring($serverDn.IndexOf("CN=Servers") + 11, $serverDn.IndexOf("CN=Sites") - ($serverDn.IndexOf("CN=Servers") + 12))
|
|
$siteName = $siteDn.Substring(3)
|
|
}
|
|
catch [Exception]
|
|
{
|
|
throw "Could not find domain controller in $($ds.SearchRoot.DistinguishedName): $($_.Exception.Message)"
|
|
}
|
|
|
|
try
|
|
{
|
|
$dc = (Get-ADSite -Name $siteName -Server $script:Server).Servers | Where-Object { $_.Name -eq $DomainControllerName }
|
|
if (-not $dc)
|
|
{
|
|
throw "The server $DomainControllerName cannot be found"
|
|
}
|
|
$dc
|
|
}
|
|
catch [Exception]
|
|
{
|
|
throw "Cannot read servers from site $siteName : ($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
function Get-Type
|
|
{
|
|
param(
|
|
[Parameter(Position=0,Mandatory=$true)]
|
|
[string] $GenericType,
|
|
|
|
[Parameter(Position=1,Mandatory=$true)]
|
|
[string[]] $T
|
|
)
|
|
|
|
$Types = $T -as [type[]]
|
|
|
|
try
|
|
{
|
|
$generic = [type]($GenericType + '`' + $Types.Count)
|
|
$generic.MakeGenericType($Types)
|
|
}
|
|
catch [Exception]
|
|
{
|
|
throw New-Object System.Exception("Cannot create generic type", $_.Exception)
|
|
}
|
|
}
|
|
|
|
|
|
function Get-ADReplicationLink
|
|
{
|
|
[CmdletBinding()]
|
|
|
|
param(
|
|
[Parameter(Mandatory=$true,ParameterSetName="AllDCsInSite",ValueFromPipelineByPropertyName=$true)]
|
|
[string] $SiteName,
|
|
|
|
[Parameter(Mandatory=$true,ParameterSetName="AllDCsInForest")]
|
|
[switch] $AllDCsInForest,
|
|
|
|
[Parameter(Mandatory=$true,ParameterSetName="AllDCsInDomain")]
|
|
[switch] $AllDCsInDomain,
|
|
|
|
[Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateScript({
|
|
if (-not $_.Contains("."))
|
|
{
|
|
throw "The Name must be a FQDN"
|
|
}
|
|
return $true
|
|
})]
|
|
[string] $DomainName,
|
|
|
|
[Parameter(Position=0,Mandatory=$false,ValueFromPipelineByPropertyName=$true,ParameterSetName="DcByName")]
|
|
[ValidateScript({
|
|
if (-not $_.Contains("."))
|
|
{
|
|
throw "The Name must be a FQDN"
|
|
}
|
|
return $true
|
|
})]
|
|
[Alias("DCName")]
|
|
[string[]] $DomainControllerName,
|
|
|
|
[Parameter(Position=0,Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
|
|
[Alias("NC")]
|
|
[string] $NamingContext,
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[switch] $ErrorsOnly,
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[string] $Server
|
|
)
|
|
|
|
begin {
|
|
$global:tempDestinationServer = $null
|
|
$script:ctx = $null
|
|
try
|
|
{
|
|
if (-not $Server)
|
|
{
|
|
$script:Server = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().FindDomainController().Name
|
|
$script:ctx = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer", $script:Server)
|
|
|
|
$script:serverObject = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().FindDomainController()
|
|
}
|
|
else
|
|
{
|
|
$script:Server = $Server
|
|
$script:ctx = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer", $script:Server)
|
|
|
|
$script:serverObject = GetSingleDomainController -DomainControllerName $Server
|
|
}
|
|
}
|
|
catch [Exception]
|
|
{
|
|
Write-Error $_
|
|
return
|
|
}
|
|
}
|
|
|
|
process {
|
|
$dcList = New-Object System.Collections.ArrayList
|
|
foreach ($DomainController in $DomainControllerName)
|
|
{
|
|
[Void]$dcList.Add((GetSingleDomainController -DomainControllerName $DomainController))
|
|
}
|
|
|
|
foreach ($dc in $dcList)
|
|
{
|
|
foreach ($partition in $dc.Partitions)
|
|
{
|
|
$repNeighbors = $dc.GetReplicationNeighbors($partition)
|
|
if ($ErrorsOnly)
|
|
{
|
|
$repNeighbors = $repNeighbors | Where-Object { $_.LastSyncResult -ne 0 }
|
|
}
|
|
|
|
foreach ($repNeighbor in $repNeighbors)
|
|
{
|
|
$repInfo = New-Object (Get-Type -GenericType System.Collections.Generic.List -T System.Management.Automation.PSObject)
|
|
$repNeighbor = $repNeighbor | Add-Member -MemberType NoteProperty -Name DestinationServer -Value $dc.Name -PassThru
|
|
$repInfo.Add([psobject]$repNeighbor)
|
|
$repInfo | ForEach-Object {
|
|
$repl = new-object System.Collections.ArrayList
|
|
$currtime = Get-Date -format 'yyyy-MM-ddTHH:mm:sszzz'
|
|
$repltime = get-date -format "yyyy-MM-dd HH:mm:ss zzz" -date $($_.LastAttemptedSync)
|
|
[void]$repl.add($currtime);
|
|
[void]$repl.add("LastAttemptedSync=`"$repltime`"")
|
|
[void]$repl.add("type=`"ReplicationEvent`"")
|
|
[void]$repl.add("usn=$($_.UsnLastObjectChangeSynced)")
|
|
[void]$repl.add("src_host=`"$($_.SourceServer)`"")
|
|
[void]$repl.add("Result=`"$($_.LastSyncResult)`"")
|
|
[void]$repl.add("transport=`"$($_.TransportType)`"")
|
|
[void]$repl.add("naming_context=`"$($repNeighbor.PartitionName)`"")
|
|
Write-Host ($repl -join " ")
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
end { }
|
|
}
|
|
|
|
## Call The functions ##
|
|
|
|
Get-ADReplicationlink $DomainControllerName |