Skip to content

Instantly share code, notes, and snippets.

@XPlantefeve
Last active June 13, 2016 09:15
Show Gist options
  • Select an option

  • Save XPlantefeve/62fa87fa9eefdba8451d995974b6b08e to your computer and use it in GitHub Desktop.

Select an option

Save XPlantefeve/62fa87fa9eefdba8451d995974b6b08e to your computer and use it in GitHub Desktop.
A couple of quickly done functions to handle local CCM maintenance windows.
<#
MIT License
Copyright (c) 2016 Xavier Plantefeve
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
#>
<#
.Synopsis
Outputs a new GUID, with optional curly braces.
#>
function New-Guid ([switch]$Braces) {
$Guid = [guid]::NewGuid() | Select -ExpandProperty Guid
If ( $Braces ) { return '{{{0}}}' -f $Guid }
Else { return $Guid }
}
<#
.Synopsis
Creates local SCCM Maintenance windows
.DESCRIPTION
This function creates a non-recurring maintenance window for SCCM.
The default is a two hours window starting now on the local computer,
but the target computer, size of the window and starting time can be configured.
.EXAMPLE
New-ClientMaintenanceWindow
Creates a two hours maintenance windows on the current computer, starting now.
.EXAMPLE
New-ClientMaintenanceWindow -ComputerName XAV1337 -Minutes 30
Creates a 30 minutes maintenance window on the XAV1337 computer, starting now.
.EXAMPLE
New-ClientMaintenanceWindow -Date '2020-01-01 12:00:00'
Creates a maintenance window starting at the selected time
.INPUTS
None
.OUTPUTS
WMI CCM_ServiceWindow object.
.NOTES
2016 Xavier Plantefève
https://gist.github.com/XPlantefeve/62fa87fa9eefdba8451d995974b6b08e
#>
function New-ClientMaintenanceWindow {
param
(
# Computer where you want to create the maintenance window.
[string]$ComputerName = '.',
# Date and time where the maintenance window starts. Can be either a string or a DateTime object.
[Object]$Date = (get-date),
# Duration of the maintenance window in days.
[int]$Days = 0,
# Duration of the maintenance window in hours.
[int]$Hours = 2,
# Duration of the maintenance window in minutes.
[int]$Minutes = 0,
# SCCM management point. Will default to the one set up on the current computer.
[string]$Server = ( Get-WmiObject -Class SMS_Authority -Namespace ROOT\ccm | select -ExpandProperty CurrentManagementPoint ),
# SCCM site code. Will default to the one set up on the current computer.
[string]$SiteCode = ( ( Get-WmiObject -Class SMS_Authority -Namespace ROOT\ccm | select -ExpandProperty Name ) -replace 'SMS\:','' ),
# Use UTC/GMT rather than local timezone.
[switch]$GMT
)
# We ask the server to give us an instance of SMS_ST_NonRecurring, ie. an empty object
# with the correct format, then we fill this object.
# see https://msdn.microsoft.com/en-us/library/cc143487.aspx for the SMS_ST_NonRecurring information.
$scheduleTime = ([WMIClass] "\\${Server}\root\sms\site_${SiteCode}:SMS_ST_NonRecurring").CreateInstance()
$scheduleTime.DayDuration = $Days
$scheduleTime.HourDuration = $Hours
$scheduleTime.MinuteDuration = $Minutes
$scheduleTime.IsGMT = $GMT
# See https://msdn.microsoft.com/en-us/library/jj217836.aspx for the time format.
$scheduleTime.StartTime = Get-Date -format 'yyyyMMddHHmmss.000000+***' -Date $Date
# We feed the SMS_ST_NonRecurring completed instance to the server and call the
# WriteToString method to get an encoded schedule string.
# See https://msdn.microsoft.com/en-us/library/cc143477.aspx for the SMS_ScheduleMethods
# see https://msdn.microsoft.com/en-us/library/hh948478.aspx for the schedule token format.
$WMIConnection = ([WMIClass]"\\${Server}\root\SMS\Site_${SiteCode}:SMS_ScheduleMethods")
$schedule = $WMIConnection.psbase.GetMethodParameters('WriteToString')
$schedule.TokenData = $scheduleTime
$ScheduledString = $WMIConnection.psbase.InvokeMethod('WriteToString',$schedule,$null)
# We then create an instance of CCM_ServiceWindow in the CCM requestedConfig namespace
# The target computer will then creates the new maintenance window.
# The CCM_ServiceWindow object in RequestedConfig inherits from the CCM_Policy object:
# https://msdn.microsoft.com/en-us/library/jj885614.aspx. The ServiceWindowType is
# documented at https://msdn.microsoft.com/en-us/library/jj155420.aspx
Set-WmiInstance -ComputerName $ComputerName -Class CCM_ServiceWindow -Namespace 'ROOT\ccm\Policy\Machine\RequestedConfig' -PutType 'CreateOnly' -argument @{
Schedules = $ScheduledString.StringData;
# see the last mentioned web page for information on service window type.
ServiceWindowType = 1;
PolicySource = 'Local';
PolicyVersion = '1.00';
PolicyID = New-Guid -Braces
PolicyRuleID = New-Guid -Braces
PolicyInstanceID = New-Guid -Braces
ServiceWindowID = New-Guid -Braces
};
}
<#
.Synopsis
Lists local SCCM Maintenance windows
.DESCRIPTION
This function lists the currently requested SCCM maintenance windows on
the computer.
.EXAMPLE
Get-ClientMaintenanceWindow -PolicyID '{5205742a-25c1-440d-8155-ca619b0c6f6e}'
Gets the maintenance window according to its PolicyID.
.EXAMPLE
Get-ClientMaintenanceWindow -Local -ComputerName MyComputer01
Gets all localy defined maintenance windows on the selected computer.
.INPUTS
None
.OUTPUTS
WMI CCM_ServiceWindow objects.
.NOTES
2016 Xavier Plantefève
https://gist.github.com/XPlantefeve/62fa87fa9eefdba8451d995974b6b08e
#>
Function Get-ClientMaintenanceWindow {
[CmdletBinding(DefaultParametersetName='Local')]
param
(
[Parameter(ParameterSetName = 'PolicyID',mandatory=$true)]
[string]$PolicyID,
[Parameter(ParameterSetName = 'PolicyInstanceID',mandatory=$true)]
[string]$PolicyInstanceID,
[Parameter(ParameterSetName = 'PolicyRuleID',mandatory=$true)]
[string]$PolicyRuleID,
[Parameter(ParameterSetName = 'ServiceWindowID',mandatory=$true)]
[string]$ServiceWindowID,
[Parameter(ParameterSetName = 'Local')]
[switch]$Local,
[string]$ComputerName = '.'
)
$WMISplat = @{
Class = 'CCM_ServiceWindow'
Namespace = 'ROOT\ccm\Policy\Machine\RequestedConfig'
ComputerName = $ComputerName
}
If ( $__Path ) { $WMISplat.Path = $__Path ; $WMISplat.Remove('ComputerName') }
ElseIF ( $PolicyID ) { $WMISplat.Filter = " PolicyID = '$PolicyID' " }
ElseIF ( $PolicyInstanceID ) { $WMISplat.Filter = " PolicyInstanceID = '$PolicyInstanceID' " }
ElseIF ( $PolicyRuleID ) { $WMISplat.Filter = " PolicyRuleID = '$PolicyRuleID' " }
ElseIF ( $ServiceWindowID ) { $WMISplat.Filter = " ServiceWindowID = '$ServiceWindowID' " }
ElseIF ( $Local ) { $WMISplat.Filter = " PolicySource = 'Local' " }
Get-WmiObject @WMISplat
}
<#
.Synopsis
Deletes local SCCM Maintenance windows
.DESCRIPTION
This function deletes a local SCCM maintenance window. The target computer is included in
the 'path' parameter.
.EXAMPLE
Remove-ClientMaintenanceWindow -PolicyID '{5205742a-25c1-440d-8155-ca619b0c6f6e}'
Removes the maintenance window according to its PolicyID.
.EXAMPLE
Remove-ClientMaintenanceWindow -Local -ComputerName MyComputer01
Removes all localy defined maintenance windows on the selected computer.
.INPUTS
WMI CCM_ServiceWindow
.OUTPUTS
None
.NOTES
2016 Xavier Plantefève
https://gist.github.com/XPlantefeve/62fa87fa9eefdba8451d995974b6b08e
#>
Function Remove-ClientMaintenanceWindow {
[CmdletBinding(DefaultParametersetName='Path')]
param
(
[Parameter(ValueFromPipelineByPropertyName=$true,ParameterSetName = 'Path',Mandatory=$true)]
[Alias('Path')]
[string]$__Path,
[Parameter(ParameterSetName = 'PolicyID',mandatory=$true)]
[string]$PolicyID,
[Parameter(ParameterSetName = 'PolicyInstanceID',mandatory=$true)]
[string]$PolicyInstanceID,
[Parameter(ParameterSetName = 'PolicyRuleID',mandatory=$true)]
[string]$PolicyRuleID,
[Parameter(ParameterSetName = 'ServiceWindowID',mandatory=$true)]
[string]$ServiceWindowID,
[Parameter(ParameterSetName = 'AllLocalWindows',mandatory=$true)]
[switch]$Local,
# ignored if 'Path' is used
[string]$ComputerName = '.'
)
Process {
If ( $__Path ) { Remove-WmiObject -Path $__Path }
Else {
If ( $PolicyID ) { $MaintenanceWindows = Get-ClientMaintenanceWindow -PolicyID $PolicyID -ComputerName $ComputerName }
ElseIF ( $PolicyInstanceID ) { $MaintenanceWindows = Get-ClientMaintenanceWindow -PolicyInstanceID $PolicyInstanceID -ComputerName $ComputerName }
ElseIF ( $PolicyRuleID ) { $MaintenanceWindows = Get-ClientMaintenanceWindow -PolicyRuleID $PolicyRuleID -ComputerName $ComputerName }
ElseIF ( $ServiceWindowID ) { $MaintenanceWindows = Get-ClientMaintenanceWindow -ServiceWindowID $ServiceWindowID -ComputerName $ComputerName }
ElseIF ( $Local ) { $MaintenanceWindows = Get-ClientMaintenanceWindow -Local -ComputerName $ComputerName }
foreach ( $window in $MaintenanceWindows ) { Remove-WmiObject -Path $window.__Path }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment