This Module contains several functions to pull information from the database used by BES. This enables fast access to information, and the possibility of scripting with this information.
It contains the following functions:
Each function has at least basic help that can be read by using the Get-Help cmdlet with the function name.
Use the Import-Module cmdlet to import the module before use.
################################################################################# DFSR-Report.ps1 - DFS replication report ## Author: John Sneddon ## Version: 1.0.5 ## ################################## REQUIREMENTS ################################## Run this from the DFS host you want to report against - ideally a hub server ## if you want data on all connections ## ################################### PARAMETERS ################################### $partner - Comma seperated array of partner servers to report against ## ################################ VERSION HISTORY ################################# 1.0.0 - Initial release ## 1.0.1 - Added parameter to restrict report to specified partner server(s) ## 1.0.2 - Added date and report conditions to report. Also appends date/time ## to output filename ## 1.0.3 - Bug fixes to email report. Seperate XSL is used to remove javascript ## elements and CSS fixes due to HTML rendering in Outlook ## 1.0.4 - Option to only send email when there is a backlog ## 1.0.5 - Updated True False section for only sending when backlog present ## (Known Bug - if you computer name is longer than 15 characters ## the ping section will error. you can just add a 15 character long ## name in DNS to solve this) ## #################################################################################param([string[]]$partner, [string]$mailTo)
$smtpServer = "MailServer"
$emailFrom = '"DFS-R Report" '
# Set this to true if you only want to be alerted when there is a backlog$suppressEmail = $false;
# Highlight backlog count on console if above this number$BacklogErrorLevel = 10
## Setup my variables$ping = New-Object System.Net.NetworkInformation.Ping
$ComputerName = $env:ComputerName
$backlogPresent = $false
## Query DFSR groups from the local MicrosftDFS WMI namespace.$DFSRGroupWMIQuery = 'SELECT FROM DfsrReplicationGroupConfig'
$RGroups = Get-WmiObject -Namespace "root\MicrosoftDFS" -Query $DFSRGroupWMIQuery
$xml = New-Object xml
[void]$xml.PrependChild($xml.CreateProcessingInstruction('xml-stylesheet', "type='text/xsl' href='report.xsl'"))
$root = $xml.CreateElement("DFS")
$root.SetAttribute("date", (get-date -format "HH:mm dd/MM/yyyy") )
$root.SetAttribute("server", $ComputerName )
if (!$partner)
{$root.SetAttribute("partners", "all partner servers" )
}else{$root.SetAttribute("partners", "$partner" )
}[void]$xml.AppendChild($root)
foreach ($Group in $RGroups)
{if ($RepGrpXML)
{Clear-Variable -name RepGrpXML
} ## Cycle through all Replication groups found$DFSRGFoldersWMIQuery = "SELECT FROM DfsrReplicatedFolderConfig WHERE ReplicationGroupGUID='" + $Group.ReplicationGroupGUID + "'"
$RGFolders = Get-WmiObject -Namespace "root\MicrosoftDFS" -Query $DFSRGFoldersWMIQuery
## Grab all connections associated with a Replication Group$DFSRConnectionWMIQuery = "SELECT FROM DfsrConnectionConfig WHERE ReplicationGroupGUID='" + $Group.ReplicationGroupGUID + "'"
$RGConnections = Get-WmiObject -Namespace "root\MicrosoftDFS" -Query $DFSRConnectionWMIQuery
foreach ($Connection in $RGConnections)
{$ConnectionName = $Connection.PartnerName.Trim()
$IsInBound = $Connection.Inbound
$IsEnabled = $Connection.Enabled
## Do not attempt to look at connections that are Disabledif ($IsEnabled -eq $True)
{ ## If the connection is not ping-able, do not attempt to query it for Backlog info$Reply = $ping.send("$ConnectionName")
if ($reply.Status -eq "Success")
{ ## Cycle through the Replication Folders that are part of the replication group and run DFSRDIAG tool to determine the backlog on the connection partners.foreach ($Folder in $RGFolders)
{ $RGName = $Group.ReplicationGroupName
$RFName = $Folder.ReplicatedFolderName
## Determine if current connect is an inbound connection or not, set send/receive members accordinglyif ($IsInBound -eq $True)
{$SendingMember = $ConnectionName
$ReceivingMember = $ComputerName
} else {$SendingMember = $ComputerName
$ReceivingMember = $ConnectionName
}if ((!$partner) -or (($partner -contains $SendingMember) -and ($ReceivingMember -eq $ComputerName)) -or (($partner -contains $ReceivingMember) -and ($SendingMember -eq $ComputerName)))
{$RGName + ":" + $RFName + " - S:"+$SendingMember + " R:" + $ReceivingMember
## Execute the dfsrdiag command and get results back in the $Backlog variable$BLCommand = "dfsrdiag Backlog /RGName:'" + $RGName + "' /RFName:'" + $RFName + "' /SendingMember:" + $SendingMember + " /ReceivingMember:" + $ReceivingMember
$Backlog = Invoke-Expression -Command $BLCommand
$BackLogFilecount = 0
foreach ($item in $Backlog)
{if ($item -ilike "*Backlog File count*")
{$BacklogFileCount = [int]$Item.Split(":")[1].Trim()
} }if ($BacklogFileCount -gt $BacklogErrorLevel)
{$outColour = "red"
} else {$outColour = "green"
}if ($BacklogFileCount -gt 0)
{$backlogPresent = $true;
} #Write-Host "$RGName: $RFName has $BacklogFilecount files in the backlog from $SendingMember to $ReceivingMember`n" -ForegroundColor $outColourWrite-Host "$BacklogFilecount files in backlog`n" -ForegroundColor $outColour
$ConnXML = $xml.CreateElement("Connection")
$ConnXML.SetAttribute("foldername", $RFName)
$ConnXML.SetAttribute("Smem", $SendingMember)
$ConnXML.SetAttribute("Rmem", $ReceivingMember)
$ConnXML.SetAttribute("backlogcount", $BacklogFilecount)
if ($BacklogFilecount -gt 0 )
{$blXML = $xml.CreateElement("backlog")
foreach ($line in $Backlog)
{if ($line -match "([0-9]*)\. (.*)")
{$blitemXML = $xml.CreateElement("file")
$blitemXML.innerText = $Matches[2]
[void]$blXML.AppendChild($blitemXML)
} }[void]$ConnXML.AppendChild($blXML)
} # if the replication group XML doesn't exist, add it. Do this to avoid empty elementsif (!$RepGrpXML)
{$RepGrpXML = $xml.CreateElement("ReplicationGroup")
$RepGrpXML.SetAttribute("name", $Group.ReplicationGroupName)
}[void]$RepGrpXML.AppendChild($ConnXML)
} } } else { Write-Host $ConnectionName "is not pingable"
"Server """ + $ConnectionName + """ could not be reached.`nPlease verify it is on the network and pingable."
} } }if ($RepGrpXML)
{[void]$root.AppendChild($RepGrpXML)
}}$date = get-date -format "yyyy-MM-dd_HH-mm"
$xml.save("$pwd\$date-DFSR-Report.xml")
Write-Host "Completed Report bit"
Write-Host $backlogPresent
Write-Host $suppressEmail
# Email the reportif ($mailTo -and ($backlogPresent -and -not $suppressEmail))
{ # apply the XSL transform - first try .Net 3.5 as is is quicker$EAP = $ErrorActionPreference
$ErrorActionPreference = "SilentlyContinue"
$script:xslt = new-object system.xml.xsl.xslcompiledtransform
trap [System.Management.Automation.PSArgumentException]
{ # no 3.5, use the slower 2.0 one
$ErrorActionPreference = $EAP
$script:xslt = new-object system.xml.xsl.xsltransform
}$ErrorActionPreference = $EAP
# load xslt file and transform$xslt.load( "$pwd\email.xsl" )
$xslt.Transform( "$pwd\$date-DFSR-Report.xml", "$pwd\$date-DFSR-Report.html" )
"`nEmailing Report...`n" # setup email variablesif (!$partner)
{$subject = "DFS-R Report between $ComputerName and all partners"
} else {$subject = "DFS-R Report between $ComputerName and $partner"
}$msg = New-Object System.Net.Mail.MailMessage $emailFrom, $mailTo, $subject, (Get-Content "$pwd\$date-DFSR-Report.html")
$msg.IsBodyHtml = $true;
# send email$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($msg)
}