# GetSchedule.ps1 # PowerShell script to document the replication schedule # of a specified Active Directory connection object. # # Copyright (c) 2018 Richard L. Mueller # Version 1.3 - October 24, 2018 # # ---------------------------------------------------------------------- # You have a royalty-free right to use, modify, reproduce, and # distribute this script file in any way you find useful, provided that # you agree that the copyright owner above has no warranty, obligations, # or liability for such use. # Specify the supported parameters. The first one or more letters of each # parameter can be used as an alias. Param( [String]$Site, [String]$ToServer, [String]$FromServer, [String]$Name, [String]$DN, [Switch]$Black, [Switch]$CSV, [Switch]$Value, [Switch]$Frequency, [Switch]$Key, [Switch]$Help ) # Script version and date. $Version = "Version 1.3 - October 24, 2018" $Today = Get-Date # Flag any parameters not recognized and abort the script. Any parameters that # do not match the supported parameters (specified by the Param statement # above) will populate the $Args collection, an automatic variable. If all of # the parameters supplied are recognized, then $Args will be empty. $Abort = $False ForEach ($Arg In $Args) { If ($Arg -Like "-*") { Write-Host "Argument not recognized: $Arg" ` -ForegroundColor Red -BackgroundColor Black } Else { Write-Host "Value not recognized: $Arg" ` -ForegroundColor Red -BackgroundColor Black } $Abort = $True } # Breaking out of the above ForEach would not break out of the script. # Breaking out of the If statement will. If ($Abort) { # Display a brief help listing the supported parameters # and their data types. Write-Host "Syntax: GetSchedule.ps1 [[-Site] ]`r`n" ` " [[-ToServer] ] [[-FromServer] ]`r`n" ` " [[-Name] ] [[-DN] ] [-Black] [-CSV]`r`n" ` " [-Value] [-Frequency] [-Key] [-Help]" ` -ForegroundColor Yellow -BackgroundColor Black Write-Host "For help use GetSchedule.ps1 -Help" ` -ForegroundColor yellow -BackgroundColor Black Break } If ($Help) { # User has requested help information. "GetSchedule.ps1" "$Version" "PowerShell script to document the replication schedule of a specified" "Active Directory connection object." "Parameters:" " -Site: The name of the site, where the connection object for" " intra-site replication is located." " -ToServer: The NetBIOS name of the destination server in the site." " -FromServer: The NetBIOS name of the source server in the site." " -Name: The name of a connection object for inter-site" " replication. This is the Relative Distinguished Name." " -DN: Distinguished name of connection object. The value must" " be in quotes. Only needed if you do not use -Site," " -ToServer, -FromServer, or -Name. Useful if you" " have many DN values in a text file." " -Black: Switch to output without using the Write-Host cmdlet," " so the output can be redirected to a file." " -CSV: Switch to output values in comma delimited format." " Implies -Black, so output can be redirected. Output" " can be -Value (the default) or -Frequency." " -Value: Switch to output decimal values for each hour." " -Frequency: Switch to output number of replications per hour." " -Key: Switch to output a table of possible schedule values" " for each hour in decimal, hex, and binary. The table" " indicates what each value means (when replication is" " scheduled during each hour)." " -Help: Switch that outputs this help." "Notes:" " For intra-site replication (between DCs within a site), use the -Site," "-ToServer, and -FromServer parameters." " For inter-site replication (between two sites), use the -Name" "parameter." " The first one or more letters of each parameter can be used as an" "alias. But at least 3 letters are needed to distinguish between" "-FromServer and -Frequency." " You can provide -Site, -ToServer, and -FromServer in order without the" "parameter names. See examples below." " The parameter values can be quoted, but quotes are only required if" "the value has spaces or commas." " The default if neither -Value, -Frequency, nor -CSV is selected is to" "output for each hour an indication of which 15 minute intervals" "replication is scheduled. For example, ""nYnY"" means replication is" "scheduled 15 and 45 minutes after the hour." "Some usage examples:" ".\GetSchedule.ps1 -Site Site-1 -To ServerA -From ServerC -CSV" " Outputs comma delimited decimal values that can be redirected to a" " text file. The resulting file can be modified, then used as input" " for the SetSchedule.ps1 PowerShell script to modify the schedule." ".\GetSchedule.ps1 My-Site ServerA ServerD -val" " Outputs decimal values for each hour of each day of a week. The" " values indicate in which 15 minute intervals replication is" " scheduled. This schedule is for intra-site replication." ".\GetSchedule.ps1 -N SiteA-SiteB -freq" " Outputs the frequency of times replication is scheduled each hour." " This schedule is for inter-site replication." ".\GetSchedule.ps1 My-Site ServerA ServerB" " Produces the default output, which indicates in which 15 minute" " interval replication is scheduled each hour. For example," " ""nnYn"" means replication is scheduled between 30 and 44" " minutes past the hour." Break } If ($Key) { "Key to values in the schedule array, one value for each hour of each day" "of the week. n = no replication, Y = replication scheduled." "For example, ""nnYn"" (decimal 4) means replication is scheduled during" "the third 15 minute interval after the hour." " --- Minutes after hour ---" "Decimal Hex Binary Syncs/Hr 00-14 15-29 30-44 45-59 Display" " 0 0 0000 0 n n n n nnnn" " 1 1 0001 1 Y n n n Ynnn" " 2 2 0010 1 n Y n n nYnn" " 3 3 0011 2 Y Y n n YYnn" " 4 4 0100 1 n n Y n nnYn" " 5 5 0101 2 Y n Y n YnYn" " 6 6 0110 2 n Y Y n nYYn" " 7 7 0111 3 Y Y Y n YYYn" " 8 8 1000 1 n n n Y nnnY" " 9 9 1001 2 Y n n Y YnnY" " 10 A 1010 2 n Y n Y nYnY" " 11 B 1011 3 Y Y n Y YYnY" " 12 C 1100 2 n n Y Y nnYY" " 13 D 1101 3 Y n Y Y YnYY" " 14 E 1110 3 n Y Y Y nYYY" " 15 F 1111 4 Y Y Y Y YYYY" "Note:" "The first bit in each binary value corresponds to the first 15 minute" "interval, from 0 to 14 minutes after the hour. The first bit is the" "far right hand bit of the binary representation of the value." Break } Trap { Write-Host "Error: $_" ` -ForegroundColor Yellow -BackgroundColor Black Break } # CSV output should not use Write-Host. No colorization needed as output # probably will be redirected to a text file. Colorization is only helpful # for the default output, not when decimal values or frequency is requested. If ($CSV -And -Not $Value -And -Not $Frequency) {$Value = $True} If ($CSV -Or $Value -Or $Frequency) {$Black = $True} If ($Value -And $Frequency) { Write-Host "The output cannot be both -Value and -Frequency" ` -ForegroundColor Red -BackgroundColor Black Write-Host "Script Aborted." -ForegroundColor Red -BackgroundColor Black Break } # Retrieve local Time Zone bias from machine registry in hours. # This bias changes with Daylight Savings Time. $Bias = (Get-ItemProperty -Path ` HKLM:\System\CurrentControlSet\Control\TimeZoneInformation).ActiveTimeBias # Account for negative bias. If ($Bias -gt 10080){$Bias = $Bias - 4294967296} $Bias = [Math]::Round($Bias/60, 0, [MidpointRounding]::AwayFromZero) # Determine Configuration naming context from RootDSE object. $RootDSE = [System.DirectoryServices.DirectoryEntry]([ADSI]"LDAP://RootDSE") $ConfigNC = $RootDSE.Get("configurationNamingContext") # Verify parameters required to identify the connection object. If ((-Not $Name) -And (-Not $DN)) { If (-Not $Site) { $Site = Read-Host "Enter the name of the AD destination site" } # Validate Site. $DestCont = [ADSI]"LDAP://cn=$Site,cn=Sites,$ConfigNC" If (-Not $DestCont.Name) { Write-Host "Site $Site not found." ` -ForegroundColor Red -BackgroundColor Black Write-Host "Script Aborted." ` -ForegroundColor Red -BackgroundColor Black Break } If (-Not $ToServer) { $ToServer = Read-Host "Enter the NetBIOS name of destination server" } # Validate ToServer. $Server = ` [ADSI]"LDAP://cn=$ToServer,cn=Servers,cn=$Site,cn=Sites,$ConfigNC" If (-Not $Server.Name) { Write-Host "Server $ToServer not found in site $Site." ` -ForegroundColor Red -BackgroundColor Black Write-Host "Script Aborted." ` -ForegroundColor Red -BackgroundColor Black Break } If (-Not $FromServer) { $FromServer = Read-Host "Enter the NetBIOS name of source server" If (-Not $FromServer) { Write-Host "Source server required." ` -ForegroundColor Red -BackgroundColor Black Write-Host "Script Aborted." ` -ForegroundColor Red -BackgroundColor Black Break } } # $Site, $ToServer, and $FromServer have been provided. # Use ADSI Searcher object to find any connection objects with the # specified FromServer in the site. $Searcher = New-Object System.DirectoryServices.DirectorySearcher $Searcher.SearchScope = "subtree" $Searcher.PropertiesToLoad.Add("distinguishedName") > $Null # Base of search is the ToServer container in the configuration container. $Searcher.SearchRoot = ` "LDAP://cn=$ToServer,cn=Servers,cn=$Site,cn=Sites,$ConfigNC" # LDAP syntax filter to find the connection object. $Searcher.Filter = "(fromServer=cn=NTDS Settings" ` + ",cn=$FromServer,cn=Servers,cn=$Site,cn=Sites,$ConfigNC)" $Connections = $Searcher.FindAll() $Count = $Connections.Count If ($Count -eq 0) { Write-Host "No connection object found with fromServer $FromServer." ` -ForegroundColor Red -BackgroundColor Black Write-Host "Script Aborted." ` -ForegroundColor Red -BackgroundColor Black Break } ForEach ($Connection In $Connections) { If ($Count -eq 1) { $DN = $Connection.Properties.Item("distinguishedName") } Else { $DN = $Connection.Properties.Item("distinguishedName") Write-Host "More than one connection object found." -NoNewLine write-Host " Select the DN desired." Write-Host "$DN" $Ans = Read-Host "Is this object DN correct? Reply ""Y"" or ""N""" If (($Ans.Trim().ToLower() -eq "y") ` -Or ($Ans.Trim().ToLower() -eq "yes")) {Break} Else {$DN = $Null} } } } # End -Not $Name -And -Not $DN. ElseIf (($Name) -And (-Not $DN)) { # Specify the distinguished name of the connection object. $DN = "cn=$Name,cn=IP,cn=Inter-Site Transports,cn=Sites,$ConfigNC" } # Bind to the object, using the distinguished name. $Connection = [ADSI]"LDAP://$DN" # Retrieve the value of the schedule attribute. # This is an array of bytes, datatype OctetString. $Sched = $Connection.schedule.Value # Validate the DN. If (-Not $Sched) { If ($Connection.Name) { Write-Host "Schedule attribute not set," Write-Host "so replication always available." # Create an array of 188 bytes. $Sched = New-Object 'Byte[]' 188 For ($j = 0; $j -le 187; $j = $j + 1) { If ($j -eq 0) {$Sched[$j] = 188} If (($j -gt 0) -And ($j -lt 8)) {$Sched[$j] = 0} If ($j -eq 8) {$Sched[$j] = 1} If (($j -gt 8) -And ($j -lt 16)) {$Sched[$j] = 0} If ($j -eq 16) {$Sched[$j] = 20} If (($j -gt 16) -And ($j -lt 20)) {$Sched[$j] = 0} If ($j -ge 20) {$Sched[$j] = 15} } } Else { Write-Host "Connection object not found," ` + " or Active Directory not available." ` -ForegroundColor Red -BackgroundColor Black Write-Host "Check the Distinguished Name of the connection object:" Write-Host "$DN" Write-Host "Script Aborted." -ForegroundColor Red -BackgroundColor Black Break } } # If $Name has a value, we assume inter-site connection object. If (-Not $Name) { If ($DN -Match "cn=IP,cn=Inter-Site Transports,cn=Sites") { # Inter-Site connection object, assign $Name. $Name = $DN.Split(",")[0].SubString(3) } } # Retrieve the options attribute. $Options = $Connection.options.Value # Check the options attribute to see if the KCC automatically # assigns a schedule, or if change notification enabled. If ($Options -band 1) {$KCC =$True} Else {$KCC = $False} If ($Name) { $Cost = $Connection.cost.Value $Interval = $Connection.replInterval.Value $SiteList = $Connection.siteList.Value } # Output heading lines. If ($CSV) { # Output to the console, not redirected to a file. Write-Host "GetSchedule.ps1" Write-Host "$Version" Write-Host "Date: $Today" If ($Name) { Write-Host "Inter-Site Replication" Write-Host "Connection Object Name: $Name" Write-Host "Cost: $Cost" Write-Host "Replication Interval (minutes): $Interval" ForEach ($Item In $SiteList) {Write-Host "Site: $Item"} } Else { Write-Host "Intra-Site Replication" Write-Host "Site: $Site" Write-Host "Destination Server: $ToServer" Write-Host "Source Server: $FromServer" } Write-Host "Connection Object:" Write-Host "$DN" Write-Host "Time Zone Bias (in hours): $Bias" If ($Name) {Write-Host "Change notification enabled: $KCC"} Else {Write-Host "KCC automatically assigns a schedule: $KCC"} If ($Value) { Write-Host "Schedule values in decimal for each hour of each day" ` + " in a week (in local time)" } If($Frequency) { Write-Host "Number of times replication scheduled each hour" ` + " of each day in a week (in local time)" } # Output heading line defining the fields to be redirected to the CSV. # The CSV will have one field for each hour in a day # and one line for each day of the week. "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23" } # End If $CSV. Else { # All output can be redirected to a text file. "GetSchedule.ps1" "$Version" "Date: $Today" If ($Name) { "Inter-Site Replication" "Connection Object Name: $Name" "Cost: $Cost" "Replication Interval (minutes): $Interval" ForEach ($Item In $SiteList) {"Site: $Item"} } Else { "Intra-Site Replication" "Site: $Site" "Destination Server: $ToServer" "Source Server: $FromServer" } "Connection Object:" "$DN" "Time Zone Bias (in hours): $Bias" If ($Name) {"Change notification enabled: $KCC"} Else {"KCC automatically assigns a schedule: $KCC"} If ($Value) { "Schedule values in decimal for each hour of each day" ` + " in a week (in local time)" } If($Frequency) { "Number of times replication scheduled each hour of each day" ` + " in a week (in local time)" } If ($Value -Or $Frequency) { " ---- Start / End of Each Hour of Each Day, Sunday through Saturday ----" " 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23" " 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24" "Day -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --" } Else { # Default output indicates the 15 minute interval when replication" # is scheduled. "When replication is scheduled, in 15 minute intervals each hour of each day of the week (in local time)" If ($Black) { "For example, ""Ynnn"" means replication is scheduled between 0 and 14 minutes after the hour." } Else { Write-Host "For example, """ -NoNewLine Write-Host "Y" -ForegroundColor Green -BackgroundColor Black -NoNewLine Write-Host "nnn" -ForegroundColor Red -BackgroundColor Black -NoNewLine Write-Host """ means replication is scheduled between 0 and 14 minutes after the hour." } "------------------ Start / End of Each Hour of Each Day, Sunday through Saturday --------------------------------------" " 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23" " 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24" "---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----" } } # Specify array of days of the week. $Days = "Sun","Mon","Tue","Wed","Thu","Fri","Sat" # Ignore first 20 bytes of schedule array (index 0 through 19). $Start = 20 # Loop through the last 168 bytes, from index 20 to 187. These bytes # represent the 168 hours in a week, Sunday through Saturday, in UTC. # Loop first through each day of the week (index 0 through 6). For ($j = 0; $j -le 6; $j = $j + 1) { # Line to be output for this day of the week (-Not $CSV). If ($Value -Or $Frequency) {$Line = $Days[$j] + " "} Else {$Line = ""} If ($Value -Or $Frequency) {$L = " "} Else {$L = ""} $First = $True # Loop through the 24 hours in the day (index 0 through 23). For ($k = 0; $k -le 23; $k = $k + 1) { # Adjust for time zone bias. The values in the schedule attribute are # in UTC, so they must be adjusted for the local time zone bias. # $m is the index into the byte array $Sched. $m = $start + $k + $Bias # If the time zone adjusted index is less than 20, add 168. If ($m -lt 20) {$m = $m + 168} # If the time zone adjusted index is greater than 187, subtract 168. If ($m -gt 187) {$m = $m - 168} # Each byte indicates when replication is scheduled in the hour. If ($CSV) { If ($Value) { # Output decimal values for each hour, comma delimited. # This is the format required by the SetSchedule.ps1 script. If ($First) {$Line = $Sched[$m]} Else {$Line = "$Line," + $Sched[$m]} } ElseIf ($Frequency) { # Output frequency for each hour, comma delimited. If ($First) { Switch ($Sched[$m]) { 0 {$Line = "0"} 1 {$Line = "1"} 2 {$Line = "1"} 3 {$Line = "2"} 4 {$Line = "1"} 5 {$Line = "2"} 6 {$Line = "2"} 7 {$Line = "3"} 8 {$Line = "1"} 9 {$Line = "2"} 10 {$Line = "2"} 11 {$Line = "3"} 12 {$Line = "2"} 13 {$Line = "3"} 14 {$Line = "3"} 15 {$Line = "4"} } # End Frequency Switch. } Else { Switch ($Sched[$m]) { 0 {$Line = "$Line,0"} 1 {$Line = "$Line,1"} 2 {$Line = "$Line,1"} 3 {$Line = "$Line,2"} 4 {$Line = "$Line,1"} 5 {$Line = "$Line,2"} 6 {$Line = "$Line,2"} 7 {$Line = "$Line,3"} 8 {$Line = "$Line,1"} 9 {$Line = "$Line,2"} 10 {$Line = "$Line,2"} 11 {$Line = "$Line,3"} 12 {$Line = "$Line,2"} 13 {$Line = "$Line,3"} 14 {$Line = "$Line,3"} 15 {$Line = "$Line,4"} } # End Frequency Switch. } } } Else { # Not CSV format. If ($Value) { # Output decimal values. If ($Sched[$m] -gt 9) { $Line = "$Line$L" + $Sched[$m] } Else { $Line = "$Line$L " + $Sched[$m] } } ElseIf ($Frequency) { # Output Frequency of replications scheduled each hour. Switch ($Sched[$m]) { 0 {$Line = "$Line$L 0"} 1 {$Line = "$Line$L 1"} 2 {$Line = "$Line$L 1"} 3 {$Line = "$Line$L 2"} 4 {$Line = "$Line$L 1"} 5 {$Line = "$Line$L 2"} 6 {$Line = "$Line$L 2"} 7 {$Line = "$Line$L 3"} 8 {$Line = "$Line$L 1"} 9 {$Line = "$Line$L 2"} 10 {$Line = "$Line$L 2"} 11 {$Line = "$Line$L 3"} 12 {$Line = "$Line$L 2"} 13 {$Line = "$Line$L 3"} 14 {$Line = "$Line$L 3"} 15 {$Line = "$Line$L 4"} } # End Frequency Switch. } # End Frequency output. Else { # Default output indicating which 15 minute interval # in each hour when replication scheduled. If ($Black) { Switch ($Sched[$m]) { 0 {$X = "nnnn"} 1 {$X = "Ynnn"} 2 {$X = "nYnn"} 3 {$X = "YYnn"} 4 {$X = "nnYn"} 5 {$X = "YnYn"} 6 {$X = "nYYn"} 7 {$X = "YYYn"} 8 {$X = "nnnY"} 9 {$X = "YnnY"} 10 {$X = "nYnY"} 11 {$X = "YYnY"} 12 {$X = "nnYY"} 13 {$X = "YnYY"} 14 {$X = "nYYY"} 15 {$X = "YYYY"} } # End Switch statement for Black default output. # Output the line for this day $Line = "$Line$L$X" } # End default output without Write-Host. Else { # Default output using Write-Host for colorization. Switch ($Sched[$m]) { 0 { Write-Host $L -NoNewLine Write-Host "nnnn" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine } 1 { Write-Host $L -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "nnn" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine } 2 { Write-Host $L -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "nn" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine } 3 { Write-Host $L -NoNewLine Write-Host "YY" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "nn" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine } 4 { Write-Host $L -NoNewLine Write-Host "nn" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine } 5 { Write-Host $L -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine } 6 { Write-Host $L -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "YY" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine } 7 { Write-Host $L -NoNewLine Write-Host "YYY" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine } 8 { Write-Host $L -NoNewLine Write-Host "nnn" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine } 9 { Write-Host $L -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "nn" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine } 10 { Write-Host $L -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine } 11 { Write-Host $L -NoNewLine Write-Host "YY" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine } 12 { Write-Host $L -NoNewLine Write-Host "nn" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "YY" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine } 13 { Write-Host $L -NoNewLine Write-Host "Y" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "YY" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine } 14 { Write-Host $L -NoNewLine Write-Host "n" -ForegroundColor Red ` -BackgroundColor Black -NoNewLine Write-Host "YYY" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine } 15 { Write-Host $L -NoNewLine Write-Host "YYYY" -ForegroundColor Green ` -BackgroundColor Black -NoNewLine } } # End Switch statement for default output. } # End default output using Write-Host. } # End default output. } # End output. If ($First) { $First = $False $L = " " } } # End of loop for the 24 hours in a day. # Output for this day. If ($Black) {"$Line"} Else {Write-Host "`r`n"} # Advance 24 hours (bytes) to the next day. $Start = $Start + 24 } # End of loop for the 7 days in a week.