powershell 禁用指定集合的SCCM推送安装。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了powershell 禁用指定集合的SCCM推送安装。相关的知识,希望对你有一定的参考价值。
<#
.SYNOPSIS
Disables SCCM push install for a specified collection.
.DESCRIPTION
Disables SCCM push install for a specified collection using the ExcludeServers registry key.
.PARAMETER CMSiteServer
Specifies the NetBIOS name of the SCCM Site Server.
.PARAMETER CMCollection
Specifies the Collection Name to exclude from Push Install.
.PARAMETER DeleteAllCollectionMembers
Optional switch used to Delete all Collection Device Members and their discovery data using CIM (blazing fast :P).
.EXAMPLE
Disable-CMPushDeviceCollection.ps1 -CMSiteServer 'SiteServerName' -CMCollection 'Exclude from Push Collection' -DeleteAllCollectionMembers
.INPUTS
System.String.
.OUTPUTS
System.String.
.NOTES
Created by Ioan Popovici
Requirements
Configuration Manager
Important
This script can be run using SCCM status filter rules, on collection membership change.
DeleteAllCollectionMembers switch does not remove collection queries.
.LINK
https://SCCM.Zone/Disable-CMDeviceCollectionPush
.LINK
https://SCCM.Zone/Disable-CMDeviceCollectionPush-CHANGELOG
.LINK
https://SCCM.Zone/Disable-CMDeviceCollectionPush-GIT
.LINK
https://SCCM.Zone/Issues
.COMPONENT
CM
.FUNCTIONALITY
Disable push install for a CM collection
#>
## Set script requirements
#Requires -Version 3.0
##*=============================================
##* VARIABLE DECLARATION
##*=============================================
#region VariableDeclaration
## Getting variables from pipeline
Param (
[Parameter(Mandatory=$True,Position=0)]
[Alias('CMServer')]
[String]$CMSiteServer,
[Parameter(Mandatory=$True,Position=1)]
[Alias('CMCollection')]
[String]$CMCollectionName,
[Parameter(Mandatory=$False,Position=3)]
[Alias('DeleteAll')]
[Switch]$DeleteAllCollectionMembers
)
## Get script path and name
[String]$ScriptPath = [System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Definition)
[String]$ScriptName = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Definition)
## CSV and log files initialization
# Set the CSV Settings and Data file name
[String]$csvDataFileName = $ScriptName
[String]$csvSettingsFileName = $ScriptName+'Settings'
# Get CSV Settings and Data file name with extension
[String]$csvDataFileNameWithExtension = $csvDataFileName+'.csv'
[String]$csvSettingsFileNameWithExtension = $csvSettingsFileName+'.csv'
# Assemble CSV Settings and Data file path
[String]$csvDataFilePath = (Join-Path -Path $ScriptPath -ChildPath $csvDataFileName)+'.csv'
[String]$csvSettingsFilePath = (Join-Path -Path $ScriptPath -ChildPath $csvSettingsFileName)+'.csv'
# Assemble log file Path
[String]$LogFilePath = (Join-Path -Path $ScriptPath -ChildPath $ScriptName)+'.log'
## Setting registry connection properties
$RegProps = @{
'Path' = 'HKLM:\Software\Microsoft\SMS\Components\SMS_DISCOVERY_DATA_MANAGER'
'Name' = 'ExcludeServers'
'ErrorAction' = 'Stop'
}
## Global error result array list
[System.Collections.ArrayList]$Global:ErrorResult = @()
#endregion
##*=============================================
##* END VARIABLE DECLARATION
##*=============================================
##*=============================================
##* FUNCTION LISTINGS
##*=============================================
#region FunctionListings
#region Function Write-Log
Function Write-Log {
<#
.SYNOPSIS
Writes data to log.
.DESCRIPTION
Writes data to file log, event log and console.
.PARAMETER EventLogEntryMessage
The event log entry message.
.PARAMETER EventLogName
The event log to write to.
.PARAMETER FileLogName
The file log name to write to.
.PARAMETER EventLogEntrySource
The event log entry source.
.PARAMETER EventLogEntryID
The event log entry ID.
.PARAMETER EventLogEntryType
The event log entry type (Error | Warning | Information | SuccessAudit | FailureAudit).
.PARAMETER SkipEventLog
Skip writing to event log.
.EXAMPLE
Write-Log -EventLogEntryMessage 'Operation was successful' -EventLogName 'Configuration Manager' -EventLogEntrySource 'Script' -EventLogEntryID '1' -EventLogEntryType 'Information'
.NOTES
This is an internal script function and should typically not be called directly.
.LINK
https://SCCM.Zone
.LINK
https://SCCM.Zone/GIT
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$False,Position=0)]
[Alias('Message')]
[String]$EventLogEntryMessage,
[Parameter(Mandatory=$False,Position=1)]
[Alias('EName')]
[String]$EventLogName = 'Configuration Manager',
[Parameter(Mandatory=$False,Position=2)]
[Alias('Source')]
[String]$EventLogEntrySource = $ScriptName,
[Parameter(Mandatory=$False,Position=3)]
[Alias('ID')]
[int32]$EventLogEntryID = 1,
[Parameter(Mandatory=$False,Position=4)]
[Alias('Type')]
[String]$EventLogEntryType = 'Information',
[Parameter(Mandatory=$False,Position=5)]
[Alias('SkipEL')]
[Switch]$SkipEventLog
)
## Initialization
# Getting the date and time
[String]$LogTime = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss').ToString()
# Archive log file if it exists and it's larger than 50 KB
If ((Test-Path $LogFilePath) -and (Get-Item $LogFilePath).Length -gt 50KB) {
Get-ChildItem -Path $LogFilePath | Rename-Item -NewName { $_.Name -Replace '.log','.lo_' } -Force
}
# Create event log and event source if they do not exist
If (-not ([System.Diagnostics.EventLog]::Exists($EventLogName)) -or (-not ([System.Diagnostics.EventLog]::SourceExists($EventLogEntrySource)))) {
# Create new event log and/or source
New-EventLog -LogName $EventLogName -Source $EventLogEntrySource
}
## Error logging
If ($_.Exception) {
# Write to log
Write-EventLog -LogName $EventLogName -Source $EventLogEntrySource -EventId $EventLogEntryID -EntryType 'Error' -Message "$EventLogEntryMessage `n$_"
# Write to console
Write-Host `n$EventLogEntryMessage -BackgroundColor 'Red' -ForegroundColor 'White'
Write-Host $_.Exception -BackgroundColor 'Red' -ForegroundColor 'White'
# Assemble log file line
[String]$LogLine = "$LogTime : $_.Exception"
# Write to log file
$LogLine | Out-File -FilePath $LogFilePath -Append -NoClobber -Force -Encoding 'UTF8' -ErrorAction 'Continue'
# Add to error result array
$Global:ErrorResult.Add($LogLine)
# Breaking Cycle so we don't get stuck in a loop :)
Break
}
Else {
# Skip event log if requested
If ($SkipEventLog) {
# Write to console
Write-Host $EventLogEntryMessage -BackgroundColor 'White' -ForegroundColor 'Blue'
}
Else {
# Write to event log
Write-EventLog -LogName $EventLogName -Source $EventLogEntrySource -EventId $EventLogEntryID -EntryType $EventLogEntryType -Message $EventLogEntryMessage
# Write to console
Write-Host $EventLogEntryMessage -BackgroundColor 'White' -ForegroundColor 'Blue'
}
}
## Assemble log file line
[String]$LogLine = "$LogTime : $EventLogEntryMessage"
## Write to log file
$LogLine | Out-File -FilePath $LogFilePath -Append -NoClobber -Force -Encoding 'UTF8' -ErrorAction 'Continue'
}
#endregion
#region Function Send-Mail
Function Send-Mail {
<#
.SYNOPSIS
Send E-Mail to specified address.
.DESCRIPTION
Send E-Mail body to specified address.
.PARAMETER From
Source.
.PARAMETER To
Destination.
.PARAMETER CC
Carbon copy.
.PARAMETER Body
E-Mail body.
.PARAMETER Attachments
E-Mail Attachments.
.PARAMETER SMTPServer
E-Mail SMTPServer.
.PARAMETER SMTPPort
E-Mail SMTPPort.
.EXAMPLE
Send-Mail -From 'test@test.com' -To "test@test.com" -Subject "test" -Body 'Test' -CC 'test@test.com' -Attachments 'C:\Temp\test.log'
.NOTES
This is an internal script function and should typically not be called directly.
.LINK
https://SCCM.Zone
.LINK
https://SCCM.Zone/Git
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True,Position=0)]
[String]$From,
[Parameter(Mandatory=$True,Position=1)]
[String]$To,
[Parameter(Mandatory=$False,Position=2)]
[String]$CC,
[Parameter(Mandatory=$True,Position=3)]
[String]$Subject,
[Parameter(Mandatory=$True,Position=4)]
[String]$Body,
[Parameter(Mandatory=$False,Position=5)]
$Attachments = $LogFilePath,
[Parameter(Mandatory=$True,Position=6)]
[String]$SMTPServer,
[Parameter(Mandatory=$True,Position=7)]
[String]$SMTPPort
)
## Send mail with error handling
Try {
# With CC
If ($CC -ne [String]::Empty -and $CC -ne 'NO') {
Send-MailMessage -From $From -To $To -Subject $Subject -CC $CC -Body $Body -Attachments $Attachments -SmtpServer $SMTPServer -Port $SMTPPort -ErrorAction 'Stop'
}
# Without CC
ElseIf ($CC -eq [String]::Empty -or $CC -eq 'NO') {
Send-MailMessage -From $From -To $To -Subject $Subject -Body $Body -Attachments $Attachments -SmtpServer $SMTPServer -Port $SMTPPort -ErrorAction 'Stop'
}
}
Catch {
Write-Log -Message 'Send Mail - Failed!'
}
}
#endregion
#region Function Get-SMSProviderLocation
Function Get-SMSProviderLocation {
<#
.SYNOPSIS
Used to get SMS Provider Location.
.DESCRIPTION
Used to get SMS Provider Location from WMI using CIM.
.PARAMETER SiteServer
Set the Site Server name for which to the SMS Provider Location.
.EXAMPLE
Get-SMSProviderLocation -SiteServer 'ComputerName'
.NOTES
This is an internal script function and should typically not be called directly.
.LINK
https://SCCM.Zone
.LINK
https://SCCM.Zone/GIT
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True,Position=0)]
[Alias('CMServer')]
[String]$SiteServer
)
## Get SMS provider location
Try {
$SMSProvider = Get-CimInstance -Query 'Select * From SMS_ProviderLocation Where ProviderForLocalSite = True' -Namespace 'ROOT\SMS' -ComputerName $SiteServer -ErrorAction 'Stop'
}
# Write to log in case of failure
Catch {
Write-Log -Message "Getting SMS Provider Location - Failed!"
}
## Setting Cim connection properties, getting namespace using regex
$CimProps = @{
'ComputerName' = $SMSProvider.Machine
'Namespace' = ($SMSProvider.NamespacePath | Select-String -Pattern 'root\\\S+').Matches.Value
'ErrorAction' = 'Stop'
}
## Returning Cim props
Return $CimProps
}
#endregion
#region Function Get-CimCollectionMembers
Function Get-CimCollectionMembers {
<#
.SYNOPSIS
Get device collection members.
.DESCRIPTION
Get device collection members NetBIOS name.
.PARAMETER CollectionName
Set the collection name for which to get device collection members.
.EXAMPLE
Get-CimCollectionMembers -CollectionName 'Computer Collection'
.NOTES
This is an internal script function and should typically not be called directly.
.LINK
https://SCCM.Zone
.LINK
https://SCCM.Zone/GIT
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True,Position=0)]
[Alias('Collection')]
[String]$CollectionName
)
## Get SMS provider location
$CimProps = Get-SMSProviderLocation -SiteServer $CMSiteServer
## Getting collection class name
Try {
$CollectionClassName = (Get-CimInstance -ClassName SMS_Collection -Filter "Name=`"$CollectionName`"" @CimProps).MemberClassName
}
# Write to log in case of failure
Catch {
Write-Log -Message "Getting CollectionClassName for $CollectionName - Failed!"
}
## Getting servers from collection and sort them by name
Try {
$DeviceCollectionMembers = (Get-CimInstance -Query "Select Name From $CollectionClassName" @CimProps).Name | Sort-Object 'Name'
}
# Write to log in case of failure
Catch {
Write-Log -Message "Getting Device Collection Members from $CollectionName - Failed!"
}
## Return device collection members
Return $DeviceCollectionMembers
}
#endregion
#region Function Remove-CimCollectionMembers
Function Remove-CimCollectionMembers {
<#
.SYNOPSIS
Delete all device collection members.
.DESCRIPTION
Delete all device members of a specific collection and their discovery data from SCCM.
.PARAMETER CollectionName
Set the collection name for which to delete all device collection members.
.EXAMPLE
Remove-CimCollectionMembers -Collection 'Computer Collection'
.NOTES
This is an internal script function and should typically not be called directly.
.LINK
https://SCCM.Zone
.LINK
https://SCCM.Zone/GIT
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True,Position=0)]
[Alias('Collection')]
[String]$CollectionName
)
## Get SMS provider location
$CimProps = Get-SMSProviderLocation -SiteServer $CMSiteServer
## Deleting all devices and their discovery data from a collection
Try {
Get-CimInstance -ClassName SMS_Collection -Filter "Name=`"$CollectionName`"" @CimProps | Invoke-CimMethod -MethodName 'DeleteAllMembers'
Write-Log "Deleting all Device Members from $CollectionName - Successful!"
}
# Write to log in case of failure
Catch {
Write-Log -Message "Deleting all Devices from $CollectionName - Failed!"
}
}
#endregion
#endregion
##*=============================================
##* END FUNCTION LISTINGS
##*=============================================
##*=============================================
##* SCRIPT BODY
##*=============================================
#region ScriptBody
## Import the Settings CSV file
Try {
$csvSettingsData = Import-Csv -Path $csvSettingsFilePath -Encoding 'UTF8' -ErrorAction 'Stop'
}
Catch {
# Write to log in case of failure
Write-Log -Message 'Importing Settings CSV Data - Failed!'
}
## Making sure we send report
Try {
## Getting devices from registry
Try {
$DevicesRegistry = (Get-ItemProperty @RegProps).ExcludeServers
}
# Write to log in case of failure
Catch {
Write-Log -Message "Getting Devices from Registry - Failed!"
}
## Getting devices from collection
$DevicesCollection = Get-CimCollectionMembers -CollectionName $CMCollectionName
## If collection is not empty start comparison
If ($DevicesCollection) {
# Check if there are devices in collection but not in registry
$DeviceDifference = (Compare-Object -ReferenceObject $DevicesRegistry -DifferenceObject $DevicesCollection | Where-Object { $_.SideIndicator -eq '=>' } | Sort-Object InputObject).InputObject
# If there are differences between registry and collection write the merged list to registry
If ($DeviceDifference) {
# Merging servers from registry and collection, eliminate duplicates
$DevicesMerged = (Compare-Object -ReferenceObject $DevicesRegistry -DifferenceObject $DevicesCollection -IncludeEqual | Sort-Object InputObject –Unique).InputObject
# Write merged list to registry
Try {
Set-ItemProperty -Value $DevicesMerged @RegProps
}
# Write to log in case of failure
Catch {
Write-Log -Message 'Write Merged Device List to Registry - Failed!'
}
# Write merged list to csv and log
Try {
$DevicesMerged | ConvertFrom-Csv -Header 'Devices Excluded from Push Install' | Export-Csv -Path $csvDataFilePath -Delimiter ',' -Encoding 'UTF8' -NoTypeInformation -Force
# Initialize result array
[Array]$Result = @()
# Adding differences device list result header
$Result+= "`nListing New Devices to be Added:`n"
# Parsing differences device list and add formatting
$DeviceDifference | ForEach-Object { $Result+= " "+$_ }
# Adding merged device list result header
$Result+= "`nListing All Devices Excluded from Push Install:`n"
# Parsing merged device list and add formatting
$DevicesMerged | ForEach-Object { $Result+= " "+$_ }
# Convert the result to string and write it to log
[String]$ResultString = Out-String -InputObject $Result
Write-Log -Message $ResultString
}
# Write to log in case of failure
Catch {
Write-Log -Message "Write Merged Device List to $csvDataFilePath - Failed!"
}
# Remove all collection member devices from SCCM (optional switch)
If ($DeleteAllCollectionMembers) { Remove-CimCollectionMembers -CollectionName $CMCollectionName }
}
# Write to log
Else { Write-Log 'Devices already Excluded!' }
}
}
Catch {
## Not needed, empty
}
Finally {
## Send Mail Report if needed
If ($csvSettingsData.SendMail -eq 'YES' -and -not $Global:ErrorResult -and $DeviceDifference) {
# Write to log
Write-Log -Message 'Sending Mail Report...' -SkipEventLog
# Send mail, attach both log and merged device list
Send-Mail -Subject 'Info: Exclude Devices from Push Install - Success!' -Body $ResultString -From $csvSettingsData.From -To $csvSettingsData.To -CC $csvSettingsData.CC -SMTPServer $csvSettingsData.SMTPServer -SMTPPort $csvSettingsData.SMTPPort -Attachments @($LogFilePath,$csvDataFilePath)
}
If ($csvSettingsData.SendMail -eq 'YES' -and $Global:ErrorResult) {
# Write to log in case of failure
Write-Log 'CSV Data Processing - Failed!'
# Write to log
Write-Log -Message "Sending Error Mail Report..."
# Send mail, attach only log
Send-Mail -Subject 'Warning: Exclude Devices from Push Install - Failed!' -Body "Errors: `n $Global:ErrorResult" -From $csvSettingsData.From -To $csvSettingsData.To -CC $csvSettingsData.CC -SMTPServer $csvSettingsData.SMTPServer -SMTPPort $csvSettingsData.SMTPPort
}
}
#endregion
##*=============================================
##* END SCRIPT BODY
##*=============================================
以上是关于powershell 禁用指定集合的SCCM推送安装。的主要内容,如果未能解决你的问题,请参考以下文章
powershell PowerShell:SCCM添加到集合
powershell 将设备从txt文件添加到SCCM设备集合。