PowerShell script to find all maintenance windows in an SCCM environment:
Showing posts with label Maintenance Windows. Show all posts
Showing posts with label Maintenance Windows. Show all posts
Wednesday, July 24, 2024
Friday, September 22, 2017
Powershell script to create SCCM maintenance window collections based on an external source (CMDB)
As written this will download the external data from a URL but that is easily converted to a simple file copy (or completely removed) if a URL is not how you get your CMDB data. As always, don't just download and run stuff that you find on the internet, check it over for possible malicious code before you do anything with it. Enjoy!
-------------------------------------------------------------
Update-MWCollections.ps1
-------------------------------------------------------------
<#
-------------------------------------------------------------
-------------------------------------------------------------
-------------------------------------------------------------
Update-MWCollections.ps1
-------------------------------------------------------------
<#
.Synopsis
Maintains Software Updates Maintenance Window Collections in SCCM
based on information from an external source (CMDB)
.DESCRIPTION
***********************************************************
Look for the "#User Variables" to make any necessry changes
The script will not download a copy the CMDB information
while in test mode (will use the test file). It will,
however, create maintenance windows on any collections that
it creates so ensure that you only have test machines in
your test file's data.
***********************************************************
Downloads data from CMDB website and stores a local copy as a .csv
Reads the CMDB data from the .csv into an array of objects
Reads SCCM data directly from SCCM into an array of objects
Loops through the array of CMDB objects, checking each against the SCCM objects
Sets a count of SCCM maintenance windows collections to the number that the CMDB object belong to
If the count of SCCM maintenance windows collections is more than 1,
it removes the computer from all SCCM maintenance windows and sets the count to 0
If the count of SCCM maintenance windows collections is exactly 1,
it checks to ensure that the one maintenance window collection to which the computer belongs is correct
if it is not correct it removes the computer from its current collection and sets the count to 0
If the count of SCCM maintenance windows collections is 0,
it checks to see if the correct maintenance window collection exists, if not it creates it
it adds the computer to the correct maintenance window collection
.NOTES
Created by Mark Randol - randoltech.blogspot.com
#>
function Get-OccuranceOfDayOfWeek{
[CmdletBinding(DefaultParameterSetName='OccuranceOfDayOfWeek',
SupportsShouldProcess=$true,
PositionalBinding=$false)]
[OutputType([DateTime])]
Param(
# Day of the Week
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=0,
ParameterSetName='OccuranceOfDayOfWeek')]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateLength(0,15)]
[ValidateSet("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")]
[Alias("day","dayname","dow")]
[String]
$DayOfWeek,
# Occurance
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=1,
ParameterSetName='OccuranceOfDayOfWeek')]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateSet(1,2,3,4)]
[Alias("occ")]
[Int]
$Occurance
)
Begin{
}
Process{
[Int]$TestDayNum = 0
[Arr]$OccuranceDates = @()
do
{
$TestDayNum = $TestDayNum + 1
$TestDayName = (Get-Date -Day $TestDayNum).DayOfWeek
}
until ($TestDayName -eq $DayOfWeek)
$OccuranceDate = $TestDayNum
do{
$OccuranceDates += @($OccuranceDate)
$OccuranceDate = $OccuranceDate + 7
}
while ($OccuranceDate -lt 32)
}
End{
[Int]$OutputInt = $Occurance - 1
[DateTime]$MyOutput = (Get-Date -Year (Get-Date).Year -Month (Get-Date).Month -Day $OccuranceDates[$OutputInt]).Date
Return $MyOutput
}
}
function Add-SCCMArrayMember{
[CmdletBinding(DefaultParameterSetName='CollectionMembership',
SupportsShouldProcess=$true,
PositionalBinding=$false)]
[OutputType([object])]
Param(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0,
ParameterSetName='CollectionMembership')]
[string]$MaintenanceWindow,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1,
ParameterSetName='CollectionMembership')]
[string]$CollectionID,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2,
ParameterSetName='CollectionMembership')]
[string]$ComputerName,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3,
ParameterSetName='CollectionMembership')]
[string]$ResourceID
)
Begin{
$CollectionMembership = new-object PSObject
}
Process{
$properties = @{'MaintenanceWindow'=$MaintenanceWindow;
'CollectionID'=$CollectionID;
'ComputerName'=$ComputerName;
'ResourceID'=$ResourceID}
$CollectionMembership = New-Object -Property $properties -TypeName PSObject
}
End{
return $CollectionMembership
}
}
function Add-CMDBArrayMember{
[CmdletBinding(DefaultParameterSetName='CMDBArrayMember',
SupportsShouldProcess=$true,
PositionalBinding=$false)]
[OutputType([object])]
Param(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0,
ParameterSetName='CMDBArrayMember')]
[string]$MaintenanceWindow,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1,
ParameterSetName='CMDBArrayMember')]
[string]$ComputerName
)
Begin{
$Membership = new-object PSObject
}
Process{
$properties = @{'MaintenanceWindow'=$MaintenanceWindow;
'ComputerName'=$ComputerName}
$Membership = New-Object -Property $properties -TypeName PSObject
}
End{
return $Membership
}
}
function Create-NewSCCMMWCollection{
[CmdletBinding(DefaultParameterSetName='NewSCCMMWCollection',
SupportsShouldProcess=$true,
PositionalBinding=$false)]
[OutputType([object])]
Param(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0,
ParameterSetName='NewSCCMMWCollection')]
[string]$CollectionName,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1,
ParameterSetName='NewSCCMMWCollection')]
[string]$TargetFolderID,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2,
ParameterSetName='NewSCCMMWCollection')]
[string]$Schedule,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3,
ParameterSetName='NewSCCMMWCollection')]
[string]$LimitingCollectionID,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4,
ParameterSetName='NewSCCMMWCollection')]
[int]$MaintDuration,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=5,
ParameterSetName='NewSCCMMWCollection')]
[string]$DeploymentCollectionID,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=5,
ParameterSetName='NewSCCMMWCollection')]
[string]$SiteCode
)
Begin{
}
Process{
#Create the collection
$ActivityMessage = "Adding new SCCM Maintenance Window collection " + $CollectionName
$StatusMessage = "Creating collection named " + $CollectionName
Write-Output $StatusMessage
$newColl = New-CMDeviceCollection -Name $CollectionName -limitingcollectionid $LimitingCollectionID -RefreshType Continuous #Create the collection
$NewCollectionID = $($newColl).collectionid
$NewCollectionName = $($newColl).Name
#Move the to the correct folder
$CurrentFolderID = 0
$ObjectTypeID = 5000
$StatusMessage = "Moving " + $NewCollectionName + " to Maintenance Windows Folder"
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
Write-Output $StatusMessage
$Namespace = "Root\SMS\Site_" + $SiteCode
Invoke-WmiMethod -Namespace $Namespace -Class SMS_objectContainerItem -Name MoveMembers -ArgumentList $CurrentFolderID,$NewCollectionID,$ObjectTypeID,$TargetFolderID
#Put a maintenance window on the collection
#Turn the schedule variable into a comma delimited array
$CommaDelimitedSchedule = $Schedule.Replace("st-",",").Replace("nd-",",").Replace("rd-",",").Replace("th-",",").Replace("st&","").Replace("nd&","").Replace("rd&","").Replace("th&","").Replace("@",",").Replace("-",",")
#Initialize variables from the array contents
$WeekOrderStr = $CommaDelimitedSchedule.Split(',')[0]
$DayOfWeek = $CommaDelimitedSchedule.Split(',')[1]
$StartTimeStr = $CommaDelimitedSchedule.Split(',')[2]
$StartHour = Get-Date $schedule.split('@')[1]
[Int]$WeekOrder = 0
$EndTime = $StartTime.AddHours($maintDuration)
if ($WeekOrderStr -eq "every"){
$WeekOrder = 0 #Set up for every week
$MWWindowName = "$prefix $WeekOrderStr-$DayOfWeek@$StartTimeStr"
$StatusMessage = "Adding $MWWindowName to collection " + $NewCollectionName
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
Write-Output $StatusMessage
IF ($DayOfWeek -eq "Day" -or $DayOfWeek -eq "day"){ #schedule is every day
$StartTime = ((get-date -Day 1).Date).AddHours($StartHour.Hour)
$EndTime = $StartTime.AddHours($maintDuration)
$StatusMessage = "Adding $MWWindowName to collection " + $NewCollectionName
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
Write-Output $StatusMessage
$schedtoken = New-CMSchedule -Start $StartTime -End $EndTime -RecurInterval Days -RecurCount 1
New-CMMaintenanceWindow -CollectionID $NewCollectionID -Name $MWWindowName -Schedule $schedtoken
} #schedule is every day
else{ #schedule is one day of week
$StartTime = (Get-OccuranceOfDayOfWeek -DayOfWeek $DayOfWeek -Occurance 1).AddHours($StartHour.Hour)
$EndTime = $StartTime.AddHours($maintDuration)
$StatusMessage = "Adding $MWWindowName to collection " + $NewCollectionName
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
Write-Output $StatusMessage
$schedtoken = New-CMSchedule -DayOfWeek $DayOfWeek -Start $StartTime -End $EndTime -RecurCount 1
New-CMMaintenanceWindow -CollectionID $NewCollectionID -Name $MWWindowName -Schedule $schedtoken
} #schedule is one day of week
}
else {
$WeekOrder = $WeekOrderStr.Substring(0,1) #Set up for the week in the 1st character (monthly and fortnightly)
$StartTime = (Get-OccuranceOfDayOfWeek -DayOfWeek $DayOfWeek -Occurance $WeekOrder).AddHours($StartHour.Hour)
$EndTime = $StartTime.AddHours($maintDuration)
$MWWindowName = $prefix + (($WeekOrderStr.Substring(0,1)).replace("1","1st").replace("2","2nd")).replace("3","3rd").replace("4","4th") + "-$DayOfWeek@$StartTimeStr"
$StatusMessage = "Adding $MWWindowName to collection " + $NewCollectionName
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
Write-Output $StatusMessage
$schedtoken = New-CMSchedule -WeekOrder $WeekOrder -DayOfWeek $DayOfWeek -Start $StartTime -End $EndTime
New-CMMaintenanceWindow -CollectionID $NewCollectionID -Name $MWWindowName -Schedule $schedtoken
if ($WeekOrderStr.Length -eq 2){
$WeekOrder = $WeekOrderStr.Substring(1,1) #Set up for the week in the 2nd character (fortnightly)
$StartTime = (Get-OccuranceOfDayOfWeek -DayOfWeek $DayOfWeek -Occurance $WeekOrder).AddHours($StartHour.Hour)
$EndTime = $StartTime.AddHours($maintDuration)
$MWWindowName = $prefix + (($WeekOrderStr.Substring(1,1)).replace("1","1st").replace("2","2nd")).replace("3","3rd").replace("4","4th") + "-$DayOfWeek@$StartTimeStr"
$StatusMessage = "Adding $MWWindowName to collection " + $NewCollectionName
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
Write-Output $StatusMessage
$schedtoken = New-CMSchedule -WeekOrder $WeekOrder -DayOfWeek $DayOfWeek -Start $StartTime -End $EndTime
New-CMMaintenanceWindow -CollectionID $NewCollectionID -Name $MWWindowName -Schedule $schedtoken
}
}
#Include the collection in the deployment collection membership
$StatusMessage = "Adding " + $NewCollectionName + " as an include to the deployment collection"
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
Write-Output $StatusMessage
Add-CMDeviceCollectionIncludeMembershipRule -CollectionId $DeploymentCollectionID -IncludeCollectionId $NewCollectionID
}
End{
}
}
function Remove-AllCurrentMWMembership{
[CmdletBinding(DefaultParameterSetName='AllCurrentMWMembership',
SupportsShouldProcess=$true,
PositionalBinding=$false)]
[OutputType([int])]
Param(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0,
ParameterSetName='AllCurrentMWMembership')]
[string]$ComputerName,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1,
ParameterSetName='AllCurrentMWMembership')]
[string]$SiteServerName,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2,
ParameterSetName='AllCurrentMWMembership')]
[string]$SiteCode,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3,
ParameterSetName='AllCurrentMWMembership')]
[string]$Prefix
)
Begin{
$NameSpace = "root\SMS\site_" + $SiteCode
$QueryText = "SELECT SMS_Collection.* FROM SMS_FullCollectionMembership, SMS_Collection where name = '" + $ComputerName + "' and SMS_FullCollectionMembership.CollectionID = SMS_Collection.CollectionID and SMS_FullCollectionMembership.CollectionName like '" + $Prefix + "%'"
$Collections = Get-WmiObject -Query $QueryText -Namespace $NameSpace
}
Process{
foreach ($Collection in $Collections){
$CollectionName = $Collection.name
$ActivityMessage = “Removing computer from a collection.”
$StatusMessage = “Removing $ComputerName from $CollectionName”
Write-Output $StatusMessage
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
Remove-CMCollectionDirectMembershipRule -CollectionName $CollectionName -ResourceName $ComputerName -Force
}
}
End{
}
}
Import-Module -Name "$(split-path $Env:SMS_ADMIN_UI_PATH)\ConfigurationManager.psd1" #Load the Configuration Manager Module
#Initialize program variables
$Date = Get-Date -Format yyyy-MM-dd_HHmm
$StartTime = Get-Date
$SCCMMWTable = @([pscustomobject])
$CMDBMWTable = @([pscustomobject])
[Int]$OuterLoopCounter = -1
[Int]$MainCounter = -1
[Int]$InnerLoopCounter = -1
#User Variables
$TestMode = $true #Set to $false to run production - provides quick and easy switch to/from test mode.
$SiteCode = "SIT"
$SiteServer = "siteserver.yourdomain.org"
$WorkingFolder = "D:\Folder\Sub-Folder" #What is our main folder to work with. This just keeps things clean and stops stuff from ending up in places like C:\
$LogFolder = $WorkingFolder + "\Logs" #Where to put our logs
$CMDBDownloadURL = "https://sum.dum.url"
$ProxyServerURL = "http://proxyserver.yourdomain.org:8015"
$LogFile = $LogFolder + "\Update-SUPMWCollections." + $Date + ".log" #Where to put the log file and what to name it.
$LocalCMDBpathProd = $WorkingFolder + "\CMDBData.$Date.csv" #production - we download to this file and then work with it locally
$LocalCMDBpathTest = $WorkingFolder + "\CMDBData.Test.csv" #test - for testing use this instead of the downloaded file to speed things up
$CMDBExportPath = $LogFolder + "\CMDBMWs." + $Date + ".csv" #Where to put the CMDB reference list. This is so we can check the scripts work later.
$PreChangeExportPath = $LogFolder + "\Pre-UpdateMWs." + $Date + ".csv" #Where to put the MW reference list before changes have been made. This is so we can check the scripts work later.
$PostChangeExportPath = $LogFolder + "\Post-UpdateMWs." + $Date + ".csv" #Where to put the MW reference list after changes have been made This is so we can check the scripts work later.
$DeploymentCollectionIDProd = "SIT12345" #Production - ID of the collection to which the software updates are actually deployed. Maintenance window collections are "include" collections on this collection.
$DeploymentCollectionIDTest = "SIT23456" #Testing - ID of the collection to which the software updates are actually deployed. Maintenance window collections are "include" collections on this collection.
$PrefixTest = "Software Updates Maintenance Window (TEST) - " #Test - Prefix for new software update collections when created
$PrefixProd = "Software Updates Maintenance Window (PROD) - " #Prefix for new software update collections when created
$MWFolderID = 12345678 #The ID of the folder in SCCM where you would like these collections to reside, otherwise they will all end up in the root folder of your console and make it all ugly
$LimitingCollectionID = "SIT34567" #Limiting collection for new software update collections when created - usually all systems but could be something more limiting like all SCCM clients
$MaintDuration = 2 #How long do you want your software updates maintenance windows to be (in hours)
$location = $SiteCode + ":\"
set-location $SiteCode #Change to local instance of ConfigMgr
Start-Transcript -path ${LogFile}
if ($TestMode = $false){
$LocalCMDBpath = $LocalCMDBpathProd
$DeploymentCollectionID = $DeploymentCollectionIDProd
$Prefix = $PrefixProd
#Download the CMDB data file to local location
$web = New-Object System.Net.WebClient
$proxy = new-object System.Net.WebProxy
$proxy.Address = $ProxyServerURL
$proxy.useDefaultCredentials = $true #once we get access for the service account, this line can go away
$web.Credentials = Get-Credential
$web.proxy = $proxy
$web.DownloadFile($CMDBDownloadURL,$LocalCMDBpath)
}
else {
$LocalCMDBpath = $LocalCMDBpathTest
$DeploymentCollectionID = $DeploymentCollectionIDTest
$Prefix = $PrefixTest
}
#Import CMDB MW Data into an array of objects
$ActivityMessage = “Importing CMDB Data”
$StatusMessage = ""
Write-Progress -Activity $ActivityMessage
Write-Output "Importing CMDB Data"
$CMDBRawFile = Import-Csv -LiteralPath $LocalCMDBpath
$ActivityMessage = "Getting CMDB maintenance window information"
$StatusMessage = "Getting CMDB maintenance window information"
Write-Output $StatusMessage
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
$LoopCounter = -1
foreach ($CMDBComputer in $CMDBRawFile){
$LoopCounter++
if ($CMDBComputer.sch_name -ne $null -and $CMDBComputer.sch_name -ne "" -and $CMDBComputer.win_host_name -ne $null -and $CMDBComputer.win_host_name -ne ""){
$CMDBComputerName = ($CMDBComputer.win_host_name).ToUpper()
$StatusMessage = "Importing information for computer $CMDBComputerName"
$progress = (($LoopCounter / ($CMDBRawFile | Measure-Object).Count) * 100)
Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress
$CMDBMWTable += Add-CMDBArrayMember -MaintenanceWindow $CMDBComputer.sch_name -ComputerName $CMDBComputerName
}
}
$ActivityMessage = “Completed reading in the CMDB information”
$StatusMessage = "Completed reading in the CMDB information - writing the CMDB file."
Write-Output $StatusMessage
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
$CMDBMWTable | Sort-Object -Property computername | Export-Csv -Path $CMDBExportPath -NoClobber -Encoding Default -NoTypeInformation
#Import SCCM data into an array of objects
$ActivityMessage = “Getting SCCM collection information”
$StatusMessage = "Getting SCCM collection membership data"
Write-Output $StatusMessage
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
$IncludeRulesOfDeploymentCollection = Get-CMCollectionIncludeMembershipRule -CollectionId $DeploymentCollectionID
$OuterLoopCounter = -1
foreach ($IncludeRule in $IncludeRulesOfDeploymentCollection){
$OuterLoopCounter++
$SCCMCollectionID = $IncludeRule.IncludeCollectionID
$SCCMCollectionName = (Get-CMDeviceCollection -Id $SCCMCollectionID).Name
$SCCMMaintenanceWindow = $SCCMCollectionName.Replace($Prefix,"")
$StatusMessage = "Importing membership information for collection $SCCMCollectionName which is an 'include' rule member of " + (Get-CMDeviceCollection -Id $DeploymentCollectionID).Name
$progress = (($OuterLoopCounter / $IncludeRulesOfDeploymentCollection.Count) * 100)
Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress
$SCCMIncludedCollectionMembers = Get-CMCollectionMember -CollectionId $SCCMCollectionID
$InnerLoopCounter = -1
foreach ($member in $SCCMIncludedCollectionMembers){
$InnerLoopCounter++
$MainCounter++
$SCCMMWTable += Add-SCCMArrayMember -MaintenanceWindow $SCCMMaintenanceWindow -CollectionID $SCCMCollectionID -ComputerName $member.Name -ResourceID $member.ResourceID
}
}
$ActivityMessage = “Completed reading in the list of 'include' Collections from the Deployment Collection”
$StatusMessage = "Done getting SCCM collection membership information - writing the Pre-Change file."
Write-Output $StatusMessage
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
$SCCMMWTable | Sort-Object -Property ComputerName | Export-Csv -Path $PreChangeExportPath -NoClobber -Encoding Default -NoTypeInformation
#Compare the two arrays of objects
$ActivityMessage = “Comparing the SCCM data to the CMDB data”
$StatusMessage = "Comparing the SCCM data to the CMDB data and making any necessary adjustments to SCCM"
Write-Output $StatusMessage
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
$LoopCounter = -1
#Main comparison loop. This is what will take the longest amount of time in the run cycle.
foreach ($CMDBMWComputer in $CMDBMWTable){ #Check each computer in the CMDB
$LoopCounter++
$progress = (($LoopCounter / $CMDBMWTable.Count) * 100)
$CountOfSCCMMWs = 0
#Only continue if there is actually a computername in CMDB (yes, it happens)
if ($CMDBMWComputer.ComputerName -ne $null -and $CMDBMWComputer.ComputerName -ne ""){
$CountOfSCCMMWs = (($SCCMMWTable | ? { $_.computername -eq $CMDBMWComputer.ComputerName }) | Measure-Object).Count
$CheckSCCMMW = ($SCCMMWTable | ? { $_.computername -eq $CMDBMWComputer.ComputerName })
#Only continue if there is a maintenance window in CMDB (yeah, that happens too)
if($CMDBMWComputer.MaintenanceWindow -ne $null -and $CMDBMWComputer.MaintenanceWindow -ne ""){
#Only continue if the computer is also in SCCM
$SCCMComputerObject = (Get-CMDevice -Name $CMDBMWComputer.ComputerName)
if ($SCCMComputerObject){
$StatusMessage = "Checking maintenance windows for " + $CMDBMWComputer.ComputerName
Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress
#If the computer is in more than one maintenance window collection then remove it from all of them
if ($CountOfSCCMMWs -gt 1){
$StatusMessage = $CMDBMWComputer.ComputerName + "`tis in multiple maintenance window collections."
Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress
Write-Output $StatusMessage
Remove-AllCurrentMWMembership -ComputerName $CMDBMWComputer.ComputerName -SiteServerName $SiteServer -SiteCode $SiteCode -Prefix $Prefix
$CountOfSCCMMWs = 0 #Set the count to zero since the computer is now a member of no maintenance window collections
} #End - If the computer is in more than one maintenance window collection then remove it from all of them and set the count to 0
#If the computer is in only one maintenance window collection we need to check that it is the correct one
if ($CountOfSCCMMWs -eq 1){
#If the computer is not in the correct maintenance window collection then remove it from the one that it is in and set the count to 0
if ($CMDBMWComputer.MaintenanceWindow -ne ($CheckSCCMMW.MaintenanceWindow).Replace($Prefix,"")){
$StatusMessage = $CMDBMWComputer.ComputerName + "`tis in the wrong maintenance window collection.`tSCCM collection = " + $CheckSCCMMW.MaintenanceWindow + "`tCMDB Maintenance Window = " + $CMDBMWComputer.MaintenanceWindow
Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress
Write-Output $StatusMessage
Remove-AllCurrentMWMembership -ComputerName $CMDBMWComputer.ComputerName -SiteServerName $SiteServer -SiteCode $SiteCode -Prefix $Prefix
$CountOfSCCMMWs = 0 #Set the count to zero since the computer is now a member of no maintenance window collections
} #End - If the computer is not in the correct maintenance window collection then remove it from the one that it is in and set the count to 0h
else{ #If the computer is in the correct maintenance window collection then huzzah and continue
$StatusMessage = $CMDBMWComputer.ComputerName + "`tis in the correct maintenance window collection.`tSCCM collection = " + $CheckSCCMMW.MaintenanceWindow + "`t CMDB Maintenance Window = " + $CMDBMWComputer.MaintenanceWindow
Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress
Write-Output $StatusMessage
} #End - If the computer is in the correct maintenance window collection then huzzah and continue
} #End - If the computer is in only one maintenance window collection we need to check that it is the correct one
#If the computer is in no maintenance window collection the put it into the correct maintenance window collection
if ($CountOfSCCMMWs -eq 0){
$StatusMessage = $CMDBMWComputer.ComputerName + "`tis not in any maintenance window collection."
Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress
Write-Output $StatusMessage
$NewCollectionName = $Prefix + $CMDBMWComputer.MaintenanceWindow
$MWExist = (Get-CMCollection -Name $NewCollectionName)
if (-not $MWExist){
$StatusMessage = "The correct maintenance window does not exist, it should be named " + $Prefix + $CMDBMWComputer.MaintenanceWindow
Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress
Write-Output $StatusMessage
Create-NewSCCMMWCollection -CollectionName $NewCollectionName -TargetFolderID $MWFolderID -LimitingCollectionID $LimitingCollectionID -Schedule $CMDBMWComputer.MaintenanceWindow -MaintDuration $MaintDuration -DeploymentCollectionID $DeploymentCollectionID -SiteCode $SiteCode
} #End - If the correct maintenance window collection doesn't exist then create it
#Add the computer to the collection
$StatusMessage = "Adding " + $CMDBMWComputer.ComputerName + " to " + $NewCollectionName
Write-Progress -Activity $ActivityMessage -Status $StatusMessage
Write-Output $StatusMessage
Add-CMDeviceCollectionDirectMembershipRule -CollectionId (Get-CMCollection -Name $NewCollectionName).CollectionID -ResourceId (Get-CMDevice -Name $CMDBMWComputer.ComputerName).resourceid
} #End - If the computer is in no maintenance window collection the put it into the correct maintenance window collection
}#END - only continue if the computer is also in SCCM
else{ #Computer is not in SCCM
$StatusMessage = $CMDBMWComputer.ComputerName + "`tis not in SCCM."
Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress
Write-Output $StatusMessage
}#END - Computer is not in SCCM
}#END - Only continue if there is a maintenance window in CMDB (yeah, that happens too)
else{ #There was no maintenance window listed in CMDB
$StatusMessage = $CMDBMWComputer.ComputerName + "`thas no maintenance window listed in CMDB."
Write-Progress -Activity $ActivityMessage -Status $StatusMessage -PercentComplete $progress
Write-Output $StatusMessage
}#END - Only continue if there is a maintenance window in CMDB (yeah, that happens too)
} #END - Only continue if there is actually a computername in CMDB (yeah, it happens)
}#End - Check each computer in the CMDB
Stop-Transcript #End Logging-------------------------------------------------------------
-------------------------------------------------------------
Thursday, February 23, 2017
Powershell Function - Get Occurance of Days of the Week
If you are like me, you keep running into people asking you to set their maintenance windows to the 3rd Saturday of the month or to the 2nd & 4th Friday of each month. To help make it a little easier I've created this function that will return what the 3rd Saturday or the 4th Friday is. Use this to help automate creation of those Maintenance Windows that don't easily fall into SCCM's normal parameters from the console. Enjoy!
<#
.Synopsis
Get-OccuranceOfDayOfWeek returns a specific occurance of a day of the week such as 3rd Saturday
.DESCRIPTION
Get-OccuranceOfDayOfWeek returns a specific occurance of a day of the week
such as the 3rd Saturday or the 1st Friday. Useful for dealing with
maintenance windows that occur on specific occurances of days of the week.
The function only returns occurances within the current month, you will
need to modify it if you need to project further into the future.
It is possible that the 4th or 5th occurance may return a date in the
following month. This is not uncommon with the 5th occurance.
.EXAMPLE
Get-OccuranceOfDayOfWeek -DayOfWeek Tuesday -Occurance 4
Returns: Tuesday, February 28, 2017 11:28:54 PM
.EXAMPLE
Get-OccuranceOfDayOfWeek -DayOfWeek Saturday -Occurance 2
Returns: Saturday, February 11, 2017 11:39:37 PM
.INPUTS
String - Full name of a day of the week (Monday, Tuesday, etc)
Integer - Which occurance to return (1-4)
.OUTPUTS
DateTime - The date of the specified occurance within the current month
.NOTES
# Script by Mark Randol
# randoltech.blogspot.com
#>
function Get-OccuranceOfDayOfWeek{
[CmdletBinding(DefaultParameterSetName='OccuranceOfDayOfWeek',
SupportsShouldProcess=$true,
PositionalBinding=$false)]
[OutputType([DateTime])]
Param(
# Day of the Week
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=0,
ParameterSetName='OccuranceOfDayOfWeek')]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateLength(0,15)]
[ValidateSet("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")]
[Alias("day","dayname","dow")]
[String]
$DayOfWeek,
# Occurance
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=1,
ParameterSetName='OccuranceOfDayOfWeek')]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateSet(1,2,3,4)]
[Alias("occ")]
[Int]
$Occurance
)
Begin{
}
Process{
[Int]$TestDayNum = 0
[Arr]$OccuranceDates = @()
do
{
$TestDayNum = $TestDayNum + 1
$TestDayName = (Get-Date -Day $TestDayNum).DayOfWeek
}
until ($TestDayName -eq $DayOfWeek)
$OccuranceDate = $TestDayNum
do{
$OccuranceDates += @($OccuranceDate)
$OccuranceDate = $OccuranceDate + 7
}
while ($OccuranceDate -lt 32)
}
End{
[Int]$OutputInt = $Occurance - 1
[DateTime]$MyOutput = (Get-Date -Year (Get-Date).Year -Month (Get-Date).Month -Day $OccuranceDates[$OutputInt]).Date
Return $MyOutput
}
}
[DateTime]$MyDate = (Get-OccuranceOfDayOfWeek -DayOfWeek Saturday -Occurance 2)
Write-Output $MyDate
Thursday, October 1, 2015
SSRS Report: Maintenance Window Membership
So, new problem that I needed to solve. Well, the problem isn't new, me having to solve it is new.
Application and server owners want to know which SCCM maintenance window(s) their servers are in. I created an SSRS report that lists all future maintenance windows with their memberships.
Caveats that may or may not be important to you:
Link: Upcoming Maintenance Windows with Membership.rdl
Application and server owners want to know which SCCM maintenance window(s) their servers are in. I created an SSRS report that lists all future maintenance windows with their memberships.
Caveats that may or may not be important to you:
- We don't use recurring maintenance windows so this has not been tested with them. I don't know what it will do... could be an infinite loop.
- We don't use maintenance windows for our workstations, just for servers. If you use maintenance windows for workstations this report might get pretty bulky.
That said, here's the report. As always please open it up in an editor (its an XML file) before using it.
Never blindly trust things you find on the Internet
Link: Upcoming Maintenance Windows with Membership.rdl
<?xml version="1.0" encoding="utf-8"?><Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns:cl="http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition"><Description>Shows all future maintenance memberships with their collection names and full membership. Created by Mark Randol - http://randoltech.blogspot.com</Description><AutoRefresh>0</AutoRefresh><DataSources><DataSource Name="ID5C6358F24BB64a1bA16E8D96795D8602"><DataSourceReference>/ConfigMgr_DNV/{5C6358F2-4BB6-4a1b-A16E-8D96795D8602}</DataSourceReference><rd:SecurityType>None</rd:SecurityType><rd:DataSourceID>908a65b1-0e01-4914-bd30-162c7a2308a2</rd:DataSourceID></DataSource></DataSources><DataSets><DataSet Name="DataSet1"><Query><DataSourceName>ID5C6358F24BB64a1bA16E8D96795D8602</DataSourceName><CommandText>SELECTv_FullCollectionMembership.Name AS [v_FullCollectionMembership Name],v_Collection.Name AS [v_Collection Name],v_ServiceWindow.Name AS [v_ServiceWindow Name],v_ServiceWindow.StartTime,v_ServiceWindow.Duration,v_ServiceWindow.IsGMT,v_ServiceWindow.RecurrenceType,v_ServiceWindow.IsEnabled,v_ServiceWindow.ServiceWindowTypeFROMv_FullCollectionMembershipINNER JOIN v_ServiceWindowON v_FullCollectionMembership.CollectionID = v_ServiceWindow.CollectionIDINNER JOIN v_CollectionON v_Collection.CollectionID = v_FullCollectionMembership.CollectionIDWHEREv_ServiceWindow.StartTime > GETDATE()ORDER BYv_ServiceWindow.StartTime</CommandText><rd:DesignerState><QueryDefinition xmlns="http://schemas.microsoft.com/ReportingServices/QueryDefinition/Relational"><AutoJoin>False</AutoJoin><SelectedColumns><ColumnExpression ColumnOwner="v_FullCollectionMembership" ColumnName="Name" /><ColumnExpression ColumnOwner="v_Collection" ColumnName="Name" /><ColumnExpression ColumnOwner="v_ServiceWindow" ColumnName="Name" /><ColumnExpression ColumnOwner="v_ServiceWindow" ColumnName="StartTime" /><ColumnExpression ColumnOwner="v_ServiceWindow" ColumnName="Duration" /><ColumnExpression ColumnOwner="v_ServiceWindow" ColumnName="IsGMT" /><ColumnExpression ColumnOwner="v_ServiceWindow" ColumnName="RecurrenceType" /><ColumnExpression ColumnOwner="v_ServiceWindow" ColumnName="IsEnabled" /><ColumnExpression ColumnOwner="v_ServiceWindow" ColumnName="ServiceWindowType" /></SelectedColumns><Joins><Join Type="CROSS JOIN" ColumnOwner="v_FullCollectionMembership" /><Join Type="INNER JOIN" ColumnOwner="v_ServiceWindow"><On><From ColumnOwner="v_FullCollectionMembership" ColumnName="CollectionID" /><To ColumnOwner="v_ServiceWindow" ColumnName="CollectionID" /></On></Join><Join Type="INNER JOIN" ColumnOwner="v_Collection"><On><From ColumnOwner="v_Collection" ColumnName="CollectionID" /><To ColumnOwner="v_FullCollectionMembership" ColumnName="CollectionID" /></On></Join></Joins><Filters><Filter Operator=">"><ColumnExpression ColumnOwner="v_ServiceWindow" ColumnName="StartTime" /><FilterValue>01/02/2015 03:00:00</FilterValue></Filter></Filters></QueryDefinition></rd:DesignerState></Query><Fields><Field Name="v_FullCollectionMembership_Name"><DataField>v_FullCollectionMembership Name</DataField><rd:TypeName>System.String</rd:TypeName></Field><Field Name="v_Collection_Name"><DataField>v_Collection Name</DataField><rd:TypeName>System.String</rd:TypeName></Field><Field Name="v_ServiceWindow_Name"><DataField>v_ServiceWindow Name</DataField><rd:TypeName>System.String</rd:TypeName></Field><Field Name="StartTime"><DataField>StartTime</DataField><rd:TypeName>System.DateTime</rd:TypeName></Field><Field Name="Duration"><DataField>Duration</DataField><rd:TypeName>System.Int32</rd:TypeName></Field><Field Name="IsGMT"><DataField>IsGMT</DataField><rd:TypeName>System.Boolean</rd:TypeName></Field><Field Name="RecurrenceType"><DataField>RecurrenceType</DataField><rd:TypeName>System.Int32</rd:TypeName></Field><Field Name="IsEnabled"><DataField>IsEnabled</DataField><rd:TypeName>System.Boolean</rd:TypeName></Field><Field Name="ServiceWindowType"><DataField>ServiceWindowType</DataField><rd:TypeName>System.Int32</rd:TypeName></Field></Fields></DataSet></DataSets><ReportSections><ReportSection><Body><ReportItems><Tablix Name="Tablix1"><TablixBody><TablixColumns><TablixColumn><Width>1.60417in</Width></TablixColumn><TablixColumn><Width>2.125in</Width></TablixColumn><TablixColumn><Width>1.47917in</Width></TablixColumn><TablixColumn><Width>1.54166in</Width></TablixColumn><TablixColumn><Width>1.23958in</Width></TablixColumn><TablixColumn><Width>1in</Width></TablixColumn><TablixColumn><Width>1in</Width></TablixColumn></TablixColumns><TablixRows><TablixRow><Height>0.25in</Height><TablixCells><TablixCell><CellContents><Textbox Name="Textbox3"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>Collection Name</Value><Style><FontFamily>Tahoma</FontFamily><FontSize>11pt</FontSize><FontWeight>Bold</FontWeight><Color>White</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>Textbox3</rd:DefaultName><Style><Border><Color>#7292cc</Color><Style>Solid</Style></Border><BackgroundColor>#4c68a2</BackgroundColor><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="Textbox5"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>Member Name</Value><Style><FontFamily>Tahoma</FontFamily><FontSize>11pt</FontSize><FontWeight>Bold</FontWeight><Color>White</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>Textbox5</rd:DefaultName><Style><Border><Color>#7292cc</Color><Style>Solid</Style></Border><BackgroundColor>#4c68a2</BackgroundColor><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="Textbox7"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>Start Time (UTC)</Value><Style><FontFamily>Tahoma</FontFamily><FontSize>11pt</FontSize><FontWeight>Bold</FontWeight><Color>White</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>Textbox7</rd:DefaultName><Style><Border><Color>#7292cc</Color><Style>Solid</Style></Border><BackgroundColor>#4c68a2</BackgroundColor><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="Textbox1"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>Start Time (MDT)</Value><Style><FontFamily>Tahoma</FontFamily><FontSize>11pt</FontSize><FontWeight>Bold</FontWeight><Color>White</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>Textbox1</rd:DefaultName><Style><Border><Color>#7292cc</Color><Style>Solid</Style></Border><BackgroundColor>#4c68a2</BackgroundColor><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="Textbox9"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>Duration (min)</Value><Style><FontFamily>Tahoma</FontFamily><FontSize>11pt</FontSize><FontWeight>Bold</FontWeight><Color>White</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>Textbox9</rd:DefaultName><Style><Border><Color>#7292cc</Color><Style>Solid</Style></Border><BackgroundColor>#4c68a2</BackgroundColor><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="Textbox13"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>GMT</Value><Style><FontFamily>Tahoma</FontFamily><FontSize>11pt</FontSize><FontWeight>Bold</FontWeight><Color>White</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>Textbox13</rd:DefaultName><Style><Border><Color>#7292cc</Color><Style>Solid</Style></Border><BackgroundColor>#4c68a2</BackgroundColor><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="Textbox15"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>Enabled</Value><Style><FontFamily>Tahoma</FontFamily><FontSize>11pt</FontSize><FontWeight>Bold</FontWeight><Color>White</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>Textbox15</rd:DefaultName><Style><Border><Color>#7292cc</Color><Style>Solid</Style></Border><BackgroundColor>#4c68a2</BackgroundColor><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell></TablixCells></TablixRow><TablixRow><Height>0.25in</Height><TablixCells><TablixCell><CellContents><Textbox Name="v_Collection_Name"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Label>Collection Name</Label><Value>=Fields!v_Collection_Name.Value</Value><Style><FontFamily>Tahoma</FontFamily><Color>#4d4d4d</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>v_Collection_Name</rd:DefaultName><Style><Border><Color>#e5e5e5</Color><Style>Solid</Style></Border><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="v_FullCollectionMembership_Name"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Label>Member Name</Label><Value>=Fields!v_FullCollectionMembership_Name.Value</Value><Style><FontFamily>Tahoma</FontFamily><Color>#4d4d4d</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>v_FullCollectionMembership_Name</rd:DefaultName><Style><Border><Color>#e5e5e5</Color><Style>Solid</Style></Border><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="StartTime"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Label>Start Time</Label><Value>=DateAdd("h",1,Fields!StartTime.Value)</Value><Style><FontFamily>Tahoma</FontFamily><Format>dddd, MMMM dd, yyyy h:mm:ss tt</Format><Color>#4d4d4d</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>StartTime</rd:DefaultName><Style><Border><Color>#e5e5e5</Color><Style>Solid</Style></Border><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="StartTime1"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>=DateAdd("h",-5,Fields!StartTime.Value)</Value><Style><FontFamily>Tahoma</FontFamily><Format>dddd, MMMM dd, yyyy h:mm:ss tt</Format><Color>#4d4d4d</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>StartTime1</rd:DefaultName><Style><Border><Color>#e5e5e5</Color><Style>Solid</Style></Border><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="Duration"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Label>Duration</Label><Value>=Fields!Duration.Value</Value><Style><FontFamily>Tahoma</FontFamily><Color>#4d4d4d</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>Duration</rd:DefaultName><Style><Border><Color>#e5e5e5</Color><Style>Solid</Style></Border><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="IsGMT"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Label>GMT</Label><Value>=Fields!IsGMT.Value</Value><Style><FontFamily>Tahoma</FontFamily><Color>#4d4d4d</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>IsGMT</rd:DefaultName><Style><Border><Color>#e5e5e5</Color><Style>Solid</Style></Border><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell><TablixCell><CellContents><Textbox Name="IsEnabled"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Label>Enabled</Label><Value>=Fields!IsEnabled.Value</Value><Style><FontFamily>Tahoma</FontFamily><Color>#4d4d4d</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>IsEnabled</rd:DefaultName><Style><Border><Color>#e5e5e5</Color><Style>Solid</Style></Border><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixCell></TablixCells></TablixRow></TablixRows></TablixBody><TablixColumnHierarchy><TablixMembers><TablixMember /><TablixMember /><TablixMember /><TablixMember /><TablixMember /><TablixMember /><TablixMember /></TablixMembers></TablixColumnHierarchy><TablixRowHierarchy><TablixMembers><TablixMember><TablixHeader><Size>2in</Size><CellContents><Textbox Name="Textbox17"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>Service Window Name</Value><Style><FontFamily>Tahoma</FontFamily><FontSize>11pt</FontSize><FontWeight>Bold</FontWeight><Color>White</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>Textbox17</rd:DefaultName><Style><Border><Color>#7292cc</Color><Style>Solid</Style></Border><BackgroundColor>#4c68a2</BackgroundColor><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixHeader><TablixMembers><TablixMember /></TablixMembers><KeepWithGroup>After</KeepWithGroup></TablixMember><TablixMember><Group Name="v_ServiceWindow_Name"><GroupExpressions><GroupExpression>=Fields!v_ServiceWindow_Name.Value</GroupExpression></GroupExpressions></Group><SortExpressions><SortExpression><Value>=Fields!StartTime.Value</Value></SortExpression></SortExpressions><TablixHeader><Size>2in</Size><CellContents><Textbox Name="v_ServiceWindow_Name1"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Label>Service Window Name</Label><Value>=Fields!v_ServiceWindow_Name.Value</Value><Style><FontFamily>Tahoma</FontFamily><FontWeight>Bold</FontWeight><Color>#465678</Color></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:DefaultName>v_ServiceWindow_Name1</rd:DefaultName><Style><Border><Color>#c6daf8</Color><Style>Solid</Style></Border><BackgroundColor>#9eb6e4</BackgroundColor><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></CellContents></TablixHeader><TablixMembers><TablixMember><Group Name="Details" /><Visibility><ToggleItem>v_ServiceWindow_Name1</ToggleItem></Visibility></TablixMember></TablixMembers></TablixMember></TablixMembers></TablixRowHierarchy><KeepTogether>true</KeepTogether><DataSetName>DataSet1</DataSetName><SortExpressions><SortExpression><Value>=Fields!StartTime.Value</Value></SortExpression><SortExpression><Value>=Fields!v_FullCollectionMembership_Name.Value</Value></SortExpression></SortExpressions><Top>0.45556in</Top><Left>0.1875in</Left><Height>0.5in</Height><Width>11.98958in</Width><Style><Border><Style>None</Style></Border></Style></Tablix><Textbox Name="ReportTitle"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>Upcoming Maintenance Windows with Membership</Value><Style><FontFamily>Verdana</FontFamily><FontSize>20pt</FontSize></Style></TextRun></TextRuns><Style /></Paragraph></Paragraphs><rd:WatermarkTextbox>Title</rd:WatermarkTextbox><rd:DefaultName>ReportTitle</rd:DefaultName><Height>0.4in</Height><Width>7.27084in</Width><ZIndex>1</ZIndex><Style><Border><Style>None</Style></Border><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></ReportItems><Height>2.30556in</Height><Style><Border><Style>None</Style></Border></Style></Body><Width>13.03125in</Width><Page><PageFooter><Height>0.45in</Height><PrintOnFirstPage>true</PrintOnFirstPage><PrintOnLastPage>true</PrintOnLastPage><ReportItems><Textbox Name="ExecutionTime"><CanGrow>true</CanGrow><KeepTogether>true</KeepTogether><Paragraphs><Paragraph><TextRuns><TextRun><Value>=Globals!ExecutionTime</Value><Style /></TextRun></TextRuns><Style><TextAlign>Right</TextAlign></Style></Paragraph></Paragraphs><rd:DefaultName>ExecutionTime</rd:DefaultName><Top>0.2in</Top><Left>4.1875in</Left><Height>0.25in</Height><Width>2in</Width><Style><Border><Style>None</Style></Border><PaddingLeft>2pt</PaddingLeft><PaddingRight>2pt</PaddingRight><PaddingTop>2pt</PaddingTop><PaddingBottom>2pt</PaddingBottom></Style></Textbox></ReportItems><Style><Border><Style>None</Style></Border></Style></PageFooter><LeftMargin>1in</LeftMargin><RightMargin>1in</RightMargin><TopMargin>1in</TopMargin><BottomMargin>1in</BottomMargin><Style /></Page></ReportSection></ReportSections><rd:ReportUnitType>Inch</rd:ReportUnitType><rd:ReportServerUrl>http://yourserver/ReportServer</rd:ReportServerUrl><rd:ReportID>9be14d20-40dd-4d05-a4f6-ac4ed5959361</rd:ReportID></Report>
Subscribe to:
Posts (Atom)