Get ConfigMgr Collection rules

I’m in the process of installing Forefront Endpoint Protection and wanted to look at some of the collection queries that was created… but with the ConfigMgr console you cant view them…

So Powershell it is.

Did a function that you can use on any collection (with subcollections) to view the WQL.

Import-Module SCCM\SCCM-Functions -Force
Function Get-CollectionRules {
        PARAM (
                $parentCollection,
                $spacer,
                $sccm
        )

        $subCollections = Get-SCCMSubCollections -SccmServer $sccm -CollectionID $parentCollection

        if ($subCollections -ne $null) {
                $subCollections | ForEach-Object {
                        $collection = Get-SCCMCollection -Filter "CollectionID='$($_.subCollectionID)'" -SccmServer $sccm
                        Write-Host "$($spacer) Name: " -ForegroundColor Yellow -NoNewline
                        Write-Host "$($collection.CollectionID) - $($collection.Name)"

                        $collectionRule = (Get-SCCMCollectionRules -SccmServer ( Connect-SCCMServer ) -CollectionID $collection.CollectionID)
                        if ($collectionRule -ne $null) {
                                Write-Host "$($spacer)Limit: " -ForegroundColor Yellow -NoNewline
                                if ($collectionRule.LimitToCollectionID.Length -gt 0) {
                                        Write-Host "$($collectionRule.LimitToCollectionID)" -ForegroundColor White
                                } else {
                                        Write-Host "" -ForegroundColor Gray
                                }

                                Write-Host "$($spacer)  WQL: " -ForegroundColor Yellow -NoNewline
                                Write-Host "$($collectionRule.QueryExpression)"
                        } else {
                                Write-Host "$($spacer)" -ForegroundColor Gray
                        }
                        Write-Host ""

                        Get-CollectionRules -parentCollection $_.subCollectionID -spacer "   $($spacer)" -sccm $sccm
                }
        }
}

Get-CollectionRules -parentCollection "XYZ00123" -spacer "" -sccm (Connect-SCCMServer)

A small warning: It will loop all of the subcollections, and the subcollections subcollections, and so on…


SCCM PoSH

Changelog

  • 2010-10-29 (Rikard Ronnkvist)
    New functions: Update-SCCMDriverPkgSourcePath, Update-SCCMPackageSourcePath, Update-SCCMDriverSourcePath
  • 2010-10-06 (Stefan Ringler)
    New and updated functions from http://www.stefanringler.com/?p=150 (New-SCCMPackage, New-SCCMAdvertisement, New-SCCMProgram, Add-SCCMDistributionPoint)
  • 2010-09-13 (Rikard Ronnkvist)
    Bugfix: Get-SCCMCollectionMembers (Thanks to Milos)
    Bugfix: Add-SCCMCollectionRule (Thanks to Luigi)
  • 2010-03-26 (Rikard Ronnkvist)
    Separate page on snowland.se
    New function: New-SCCMPackage
  • 2010-03-23 (Rikard Ronnkvist)
    Fixed some small bugs
    Added limitToCollectionId in Add-SCCMCollectionRule
  • 2010-03-10 (Rikard Ronnkvist)
    Major makeover
    First snowland.se release
  • 2009-04-07 (Michael Niehaus)
    Original code posted at http://blogs.technet.com/mniehaus/

Usage:

  • Save the file as SCCM-Commands.psm1
  • PS:>Import-Module SCCM-Commands
  • PS:>Get-SCCMCommands

SCCM-Commands.psm1

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#                                                                                                                            Rikard Ronnkvist / snowland.se
#  Usage:
#   Save the file as SCCM-Commands.psm1
#   PS:>Import-Module SCCM-Commands
#   PS:>Get-SCCMCommands
#
#  2009-04-07   Michael Niehaus     Original code posted at http://blogs.technet.com/mniehaus/
#  2010-03-10   Rikard Ronnkvist    Major makeover and first snowland.se release
#  2010-03-23   Rikard Ronnkvist    Fixed some small bugs and added limitToCollectionId in Add-SCCMCollectionRule
#  2010-03-26   Rikard Ronnkvist    New function: New-SCCMPackage
#  2010-09-13   Rikard Ronnkvist    Bugfixes to Add-SCCMCollectionRule and Get-SCCMCollectionMembers (Thanks to comments on snowland.se from Milos and Luigi)
#  2010-10-06   Stefan Ringler      New and updated functions from http://www.stefanringler.com/?p=150 (New-SCCMPackage, New-SCCMAdvertisement, New-SCCMProgram, Add-SCCMDistributionPoint)
#  2010-10-29   Rikard Ronnkvist    New functions: Update-SCCMDriverPkgSourcePath, Update-SCCMPackageSourcePath, Update-SCCMDriverSourcePath
#
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Function Get-SCCMCommands {
        # List all SCCM-commands
        [CmdletBinding()]
        PARAM ()
        PROCESS {
                return Get-Command -Name *-SCCM* -CommandType Function  | Sort-Object Name | Format-Table Name, Module
        }
}

Function Connect-SCCMServer {
        # Connect to one SCCM server
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$false,HelpMessage="SCCM Server Name or FQDN",ValueFromPipeline=$true)][Alias("ServerName","FQDN","ComputerName")][String] $HostName = (Get-Content env:computername),
                [Parameter(Mandatory=$false,HelpMessage="Optional SCCM Site Code",ValueFromPipelineByPropertyName=$true )][String] $siteCode = $null,
                [Parameter(Mandatory=$false,HelpMessage="Credentials to use" )][System.Management.Automation.PSCredential] $credential = $null
        )

        PROCESS {
                # Get the pointer to the provider for the site code
                if ($siteCode -eq $null -or $siteCode -eq "") {
                        Write-Verbose "Getting provider location for default site on server $HostName"
                        if ($credential -eq $null) {
                                $sccmProviderLocation = Get-WmiObject -query "select * from SMS_ProviderLocation where ProviderForLocalSite = true" -Namespace "root\sms" -computername $HostName -errorAction Stop
                        } else {
                                $sccmProviderLocation = Get-WmiObject -query "select * from SMS_ProviderLocation where ProviderForLocalSite = true" -Namespace "root\sms" -computername $HostName -credential $credential -errorAction Stop
                        }
                } else {
                        Write-Verbose "Getting provider location for site $siteCode on server $HostName"
                        if ($credential -eq $null) {
                                $sccmProviderLocation = Get-WmiObject -query "SELECT * FROM SMS_ProviderLocation where SiteCode = '$siteCode'" -Namespace "root\sms" -computername $HostName -errorAction Stop
                        } else {
                                $sccmProviderLocation = Get-WmiObject -query "SELECT * FROM SMS_ProviderLocation where SiteCode = '$siteCode'" -Namespace "root\sms" -computername $HostName -credential $credential -errorAction Stop
                        }
                }

                # Split up the namespace path
                $parts = $sccmProviderLocation.NamespacePath -split "\\", 4
                Write-Verbose "Provider is located on $($sccmProviderLocation.Machine) in namespace $($parts[3])"

                # Create a new object with information
                $retObj = New-Object -TypeName System.Object
                $retObj | add-Member -memberType NoteProperty -name Machine -Value $HostName
                $retObj | add-Member -memberType NoteProperty -name Namespace -Value $parts[3]
                $retObj | add-Member -memberType NoteProperty -name SccmProvider -Value $sccmProviderLocation

                return $retObj
        }
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Function Get-SCCMObject {
        #  Generic query tool
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipelineByPropertyName=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true, HelpMessage="SCCM Class to query",ValueFromPipeline=$true)][Alias("Table","View")][String] $class,
                [Parameter(Mandatory=$false,HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                if ($Filter -eq $null -or $Filter -eq "")
                {
                        Write-Verbose "WMI Query: SELECT * FROM $class"
                        $retObj = get-wmiobject -class $class -computername $SccmServer.Machine -namespace $SccmServer.Namespace
                }
                else
                {
                        Write-Verbose "WMI Query: SELECT * FROM $class WHERE $Filter"
                        $retObj = get-wmiobject -query "SELECT * FROM $class WHERE $Filter" -computername $SccmServer.Machine -namespace $SccmServer.Namespace
                }

                return $retObj
        }
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Function Get-SCCMPackage {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_Package" -Filter $Filter
        }
}

Function Get-SCCMCollection {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_Collection" -Filter $Filter
        }
}

Function Get-SCCMAdvertisement {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_Advertisement" -Filter $Filter
        }
}

Function Get-SCCMDriver {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_Driver" -Filter $Filter
        }
}

Function Get-SCCMDriverPackage {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_DriverPackage" -Filter $Filter
        }
}

Function Get-SCCMTaskSequence {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_TaskSequence" -Filter $Filter
        }
}

Function Get-SCCMSite {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_Site" -Filter $Filter
        }
}

Function Get-SCCMImagePackage {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_ImagePackage" -Filter $Filter
        }
}

Function Get-SCCMOperatingSystemInstallPackage {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_OperatingSystemInstallPackage" -Filter $Filter
        }
}

Function Get-SCCMBootImagePackage {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Optional Filter on query")][String] $Filter = $null
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_BootImagePackage" -Filter $Filter
        }
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Get-SCCMComputer {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Filter on SCCM Resource ID",ValueFromPipelineByPropertyName=$true)][int32] $ResourceID = $false,
                [Parameter(Mandatory=$false, HelpMessage="Filter on Netbiosname on computer",ValueFromPipeline=$true)][String] $NetbiosName = "%",
                [Parameter(Mandatory=$false, HelpMessage="Filter on Domain name",ValueFromPipelineByPropertyName=$true)][Alias("Domain", "Workgroup")][String] $ResourceDomainOrWorkgroup = "%",
                [Parameter(Mandatory=$false, HelpMessage="Filter on SmbiosGuid (UUID)")][String] $SmBiosGuid = "%"
        )

        PROCESS {
                if ($ResourceID -eq $false -and $NetbiosName -eq "%" -and $ResourceDomainOrWorkgroup -eq "%" -and $SmBiosGuid -eq "%") {
                        throw "Need at least one filter..."
                }

                if ($ResourceID -eq $false) {
                        return Get-SCCMObject -sccmServer $SccmServer -class "SMS_R_System" -Filter "NetbiosName LIKE '$NetbiosName' AND ResourceDomainOrWorkgroup LIKE '$ResourceDomainOrWorkgroup' AND SmBiosGuid LIKE '$SmBiosGuid'"
                } else {
                        return Get-SCCMObject -sccmServer $SccmServer -class "SMS_R_System" -Filter "ResourceID = $ResourceID"
                }
        }
}

Function Get-SCCMUser {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Filter on SCCM Resource ID",ValueFromPipelineByPropertyName=$true)][int32] $ResourceID = $false,
                [Parameter(Mandatory=$false, HelpMessage="Filter on unique username in form DOMAIN\UserName",ValueFromPipelineByPropertyName=$true)][String] $UniqueUserName = "%",
                [Parameter(Mandatory=$false, HelpMessage="Filter on Domain name",ValueFromPipelineByPropertyName=$true)][Alias("Domain")][String] $WindowsNTDomain = "%",
                [Parameter(Mandatory=$false, HelpMessage="Filter on UserName",ValueFromPipeline=$true)][String] $UserName = "%"
        )

        PROCESS {
                if ($ResourceID -eq $false -and $UniqueUserName -eq "%" -and $WindowsNTDomain -eq "%" -and $UserName -eq "%") {
                        throw "Need at least one filter..."
                }

                if ($ResourceID -eq $false) {
                        return Get-SCCMObject -sccmServer $SccmServer -class "SMS_R_User" -Filter "UniqueUserName LIKE '$UniqueUserName' AND WindowsNTDomain LIKE '$WindowsNTDomain' AND UserName LIKE '$UserName'"
                } else {
                        return Get-SCCMObject -sccmServer $SccmServer -class "SMS_R_User" -Filter "ResourceID = $ResourceID"
                }
        }
}

Function Get-SCCMCollectionMembers {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="CollectionID", ValueFromPipeline=$true)][String] $CollectionID
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_CollectionMember_a" -Filter "CollectionID = '$CollectionID'"
        }
}

Function Get-SCCMSubCollections {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true, HelpMessage="CollectionID",ValueFromPipeline=$true)][Alias("parentCollectionID")][String] $CollectionID
        )

        PROCESS {
                return Get-SCCMObject -sccmServer $SccmServer -class "SMS_CollectToSubCollect" -Filter "parentCollectionID = '$CollectionID'"
        }
}

Function Get-SCCMParentCollection {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true, HelpMessage="CollectionID",ValueFromPipeline=$true)][Alias("subCollectionID")][String] $CollectionID
        )

        PROCESS {
                $parentCollection = Get-SCCMObject -sccmServer $SccmServer -class "SMS_CollectToSubCollect" -Filter "subCollectionID = '$CollectionID'"

                return Get-SCCMCollection -sccmServer $SccmServer -Filter "CollectionID = '$($parentCollection.parentCollectionID)'"
        }
}

Function Get-SCCMSiteDefinition {
        # Get all definitions for one SCCM site
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer
        )

        PROCESS {
                Write-Verbose "Refresh the site $($SccmServer.SccmProvider.SiteCode) control file"
                Invoke-WmiMethod -path SMS_SiteControlFile -name RefreshSCF -argumentList $($SccmServer.SccmProvider.SiteCode) -computername $SccmServer.Machine -namespace $SccmServer.Namespace

                Write-Verbose "Get the site definition object for this site"
                return get-wmiobject -query "SELECT * FROM SMS_SCI_SiteDefinition WHERE SiteCode = '$($SccmServer.SccmProvider.SiteCode)' AND FileType = 2" -computername $SccmServer.Machine -namespace $SccmServer.Namespace
        }
}

Function Get-SCCMSiteDefinitionProps {
        # Get definitionproperties for one SCCM site
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer
        )

        PROCESS {
                return Get-SCCMSiteDefinition -sccmServer $SccmServer | ForEach-Object { $_.Props }
        }
}

Function Get-SCCMIsR2 {
        # Return $true if the SCCM server is R2 capable
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer
        )

        PROCESS {
                $result = Get-SCCMSiteDefinitionProps -sccmServer $SccmServer | ? {$_.PropertyName -eq "IsR2CapableRTM"}
                if (-not $result) {
                        return $false
                } elseif ($result.Value = 31) {
                        return $true
                } else {
                        return $false
                }
        }
}

Function Get-SCCMCollectionRules {
        # Get a set of all collectionrules
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="CollectionID", ValueFromPipeline=$true)][String] $CollectionID
        )

        PROCESS {
                Write-Verbose "Collecting rules for $CollectionID"
                $col = [wmi]"$($SccmServer.SccmProvider.NamespacePath):SMS_Collection.CollectionID='$($CollectionID)'"

                return $col.CollectionRules
        }
}

Function Get-SCCMInboxes {
        # Give a count of files in the SCCM-inboxes
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server",ValueFromPipeline=$true)][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$false, HelpMessage="Minimum number of files in directory")][int32] $minCount = 1
        )

        PROCESS {
                Write-Verbose "Reading \\$($SccmServer.Machine)\SMS_$($SccmServer.SccmProvider.SiteCode)\inboxes"
                return Get-ChildItem \\$($SccmServer.Machine)\SMS_$($SccmServer.SccmProvider.SiteCode)\inboxes -Recurse | Group-Object Directory | Where { $_.Count -gt $minCount } | Format-Table Count, Name -AutoSize
        }
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function New-SCCMCollection {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true, HelpMessage="Collection Name", ValueFromPipeline=$true)][String] $name,
                [Parameter(Mandatory=$false, HelpMessage="Collection comment")][String] $comment = "",
                [Parameter(Mandatory=$false, HelpMessage="Refresh Rate in Minutes")] [ValidateRange(0, 59)] [int] $refreshMinutes = 0,
                [Parameter(Mandatory=$false, HelpMessage="Refresh Rate in Hours")] [ValidateRange(0, 23)] [int] $refreshHours = 0,
                [Parameter(Mandatory=$false, HelpMessage="Refresh Rate in Days")] [ValidateRange(0, 31)] [int] $refreshDays = 0,
                [Parameter(Mandatory=$false, HelpMessage="Parent CollectionID")][String] $parentCollectionID = "COLLROOT"
        )

        PROCESS {
                # Build the parameters for creating the collection
                $arguments = @{Name = $name; Comment = $comment; OwnedByThisSite = $true}
                $newColl = Set-WmiInstance -class "SMS_Collection" -arguments $arguments -computername $SccmServer.Machine -namespace $SccmServer.Namespace

                # Hack - for some reason without this we don't get the CollectionID value
                $hack = $newColl.PSBase | select * | out-null

                # It's really hard to set the refresh schedule via Set-WmiInstance, so we'll set it later if necessary
                if ($refreshMinutes -gt 0 -or $refreshHours -gt 0 -or $refreshDays -gt 0)
                {
                        Write-Verbose "Create the recur interval object"
                        $intervalClass = [WMICLASS]"\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_ST_RecurInterval"
                        $interval = $intervalClass.CreateInstance()
                        if ($refreshMinutes -gt 0) {
                                $interval.MinuteSpan = $refreshMinutes
                        }
                        if ($refreshHours -gt 0) {
                                $interval.HourSpan = $refreshHours
                        }
                        if ($refreshDays -gt 0) {
                                $interval.DaySpan = $refreshDays
                        }

                        Write-Verbose "Set the refresh schedule"
                        $newColl.RefreshSchedule = $interval
                        $newColl.RefreshType=2
                        $path = $newColl.Put()
                }   

                Write-Verbose "Setting the new $($newColl.CollectionID) parent to $parentCollectionID"
                $subArguments  = @{SubCollectionID = $newColl.CollectionID}
                $subArguments += @{ParentCollectionID = $parentCollectionID}

                # Add the link
                $newRelation = Set-WmiInstance -Class "SMS_CollectToSubCollect" -arguments $subArguments -computername $SccmServer.Machine -namespace $SccmServer.Namespace

                Write-Verbose "Return the new collection with ID $($newColl.CollectionID)"
                return $newColl
        }
}

Function Add-SCCMCollectionRule {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true,  HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true,  HelpMessage="CollectionID", ValueFromPipelineByPropertyName=$true)] $collectionID,
                [Parameter(Mandatory=$false, HelpMessage="Computer name to add (direct)", ValueFromPipeline=$true)] [String] $name,
                [Parameter(Mandatory=$false, HelpMessage="WQL Query Expression", ValueFromPipeline=$true)] [String] $queryExpression = $null,
                [Parameter(Mandatory=$false, HelpMessage="Limit to collection (Query)", ValueFromPipeline=$false)] [String] $limitToCollectionId = $null,
                [Parameter(Mandatory=$true,  HelpMessage="Rule Name", ValueFromPipeline=$true)] [String] $queryRuleName
        )

        PROCESS {
                # Get the specified collection (to make sure we have the lazy properties)
                $coll = [wmi]"$($SccmServer.SccmProvider.NamespacePath):SMS_Collection.CollectionID='$collectionID'"

                # Build the new rule
                if ($queryExpression.Length -gt 0) {
                        # Create a query rule
                        $ruleClass = [WMICLASS]"$($SccmServer.SccmProvider.NamespacePath):SMS_CollectionRuleQuery"
                        $newRule = $ruleClass.CreateInstance()
                        $newRule.RuleName = $queryRuleName
                        $newRule.QueryExpression = $queryExpression
                        if ($limitToCollectionId -ne $null) {
                                $newRule.LimitToCollectionID = $limitToCollectionId
                        }

                        $null = $coll.AddMembershipRule($newRule)
                } else {
                        $ruleClass = [WMICLASS]"$($SccmServer.SccmProvider.NamespacePath):SMS_CollectionRuleDirect"

                        # Find each computer
                        $computer = Get-SCCMComputer -sccmServer $SccmServer -NetbiosName $name
                        # See if the computer is already a member
                        $found = $false
                        if ($coll.CollectionRules -ne $null) {
                                foreach ($member in $coll.CollectionRules) {
                                        if ($member.ResourceID -eq $computer.ResourceID) {
                                                $found = $true
                                        }
                                }
                        }
                        if (-not $found) {
                                Write-Verbose "Adding new rule for computer $name"
                                $newRule = $ruleClass.CreateInstance()
                                $newRule.RuleName = $name
                                $newRule.ResourceClassName = "SMS_R_System"
                                $newRule.ResourceID = $computer.ResourceID

                                $null = $coll.AddMembershipRule($newRule)
                        } else {
                                Write-Verbose "Computer $name is already in the collection"
                        }
                }
        }
}

Function Add-SCCMDirUserCollectionRule {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(ValueFromPipelineByPropertyName=$true)][String] $CollectionID,
                [Parameter(ValueFromPipeline=$true)][String] $UserName
        )

        PROCESS {
                $coll = [wmi]"\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_Collection.CollectionID='$CollectionID'"
                $ruleClass = [WMICLASS]"\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_CollectionRuleDirect"

                $RuleClass
                $UserRule=Get-User "userName='$UserName'"
                $NewRuleName=$UserRule.name
                $NewRuleResourceID = $UserRule.ResourceID
                $newRule = $ruleClass.CreateInstance()

                $newRule.RuleName = $NewRuleName
                $newRule.ResourceClassName = "SMS_R_User"
                $newRule.ResourceID = $NewRuleResourceID

                $null = $coll.AddMembershipRule($newRule)
                $coll.requestrefresh()
                Clear-Variable -name oldrule -errorAction SilentlyContinue
                Clear-Variable -name Coll -errorAction SilentlyContinue
        }
}

Function New-SCCMPackage {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true, HelpMessage="Package Name", ValueFromPipeline=$true)][String] $Name,

                [Parameter(Mandatory=$false, HelpMessage="Package Version")][String] $Version = "",
                [Parameter(Mandatory=$false, HelpMessage="Package Manufacturer")][String] $Manufacturer = "",
                [Parameter(Mandatory=$false, HelpMessage="Package Language")][String] $Language = "",
                [Parameter(Mandatory=$false, HelpMessage="Package Description")][String] $Description = "",
                [Parameter(Mandatory=$false, HelpMessage="Package Data Source Path")][String] $PkgSourcePath = "",
                [Parameter(Mandatory=$false, HelpMessage="Package Sharename")][String] $PkgShareName = ""
        )

        PROCESS {
                $packageClass = [WMICLASS]"\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_Package"
                $newPackage = $packageClass.createInstance() 

                $newPackage.Name = $Name
                if ($Version -ne "")          { $newPackage.Version = $Version }
                if ($Manufacturer -ne "")     { $newPackage.Manufacturer = $Manufacturer }
                if ($Language -ne "")                 { $newPackage.Language = $Language }
                if ($Description -ne "")      { $newPackage.Description = $Description }

                if ($PkgSourcePath -ne "") {
                        $newPackage.PkgSourceFlag = 2  # Direct (3 = Compressed)
                        $newPackage.PkgSourcePath = $PkgSourcePath
                        if ($PkgShareName -ne "") {
                                $newPackage.ShareName = $PkgShareName
                                $newPackage.ShareType = 2
                        }
                } else {
                        $newPackage.PkgSourceFlag = 1  # No source
                        $newPackage.PkgSourcePath = $null
                }
                $newPackage.Put()

                $newPackage.Get()
                Write-Verbose "Return the new package with ID $($newPackage.PackageID)"
                return $newPackage
        }
}

Function New-SCCMAdvertisement {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true)] $AdvertisementName,
                [Parameter(Mandatory=$true)] $collectionID,
                [Parameter(Mandatory=$true)] $PackageID,
                [Parameter(Mandatory=$true)] $ProgramName,
                [Switch] $Download,
                [Parameter(Mandatory=$false, HelpMessage="YYYYMMDDhhmm")] $StartTime,
                [Parameter(Mandatory=$false, HelpMessage="YYYYMMDDhhmm")] $EndTime,
                [Parameter(Mandatory=$false, HelpMessage="YYYYMMDDhhmm")] $MandatoryTime
        )
        PROCESS {
                $strServer = $SccmServer.machine
                $strNamespace= $SccmServer.namespace
                $AdvClass = [WmiClass]("\\$strServer\" + "$strNameSpace" + ":SMS_Advertisement")
                if ($Download) {
                        $RemoteClientFlags = "3152"
                } else {
                        $RemoteClientFlags = "3208"
                }
                if ($StartTime -ne $null) {
                        $PresentTime = $StartTime + "00.000000+***"
                } else {
                        $PresentTime = "20200110000000.000000+***"
                }
                if ($EndTime -ne $null) {
                        $ExpirationTime = $Endtime + "00.000000+***"
                        $ExpirationTimeEnabled = $true
                } else {
                        $ExpirationTime = "20200113000000.000000+***"
                        $ExpirationTimeEnabled = $false
                }
                if ($MandatoryTime -ne $null) {
                        $Deadline = $MandatoryTime + "00.000000+***"
                } else {
                        $Deadline = $null
                }

                # Get the all the Advertisement Properties
                $newAdvertisement = $AdvClass.CreateInstance()
                $newAdvertisement.AdvertisementName = $AdvertisementName
                $newAdvertisement.CollectionID = $collectionID
                $newAdvertisement.PackageID = $PackageID
                $newAdvertisement.ProgramName = $ProgramName
                $newAdvertisement.RemoteClientFlags = $RemoteClientFlags
                $newAdvertisement.PresentTime = $PresentTime
                $newAdvertisement.ExpirationTime = $ExpirationTime
                $newAdvertisement.ExpirationTimeEnabled = $ExpirationTimeEnabled
                $newAdvertisement.Priority = "2"
                $newAdvertisement.IncludeSubCollection = $false

                # Create Advertisement
                $retval = $newAdvertisement.psbase.Put()
                if ($Deadline -ne $null) {
                        # Create Mandatory Schedule
                        $wmiClassSchedule = [WmiClass]("\\$strServer\" + "$strNameSpace" + ":SMS_ST_NonRecurring")
                        $AssignedSchedule = $wmiClassSchedule.psbase.createinstance()
                        $AssignedSchedule.starttime = $Deadline
                        if ($Download) {
                                $newAdvertisement.RemoteClientFlags = "9296"
                        } else {
                                $newAdvertisement.RemoteClientFlags = "9352"
                        }
                        $newAdvertisement.AssignedSchedule = $AssignedSchedule
                        $newAdvertisement.AssignedScheduleEnabled = $true
                        $newAdvertisement.psbase.put()
                        $NewAdvertisementProperties = $newAdvertisement.AssignedSchedule
                        foreach ($Adv in $NewAdvertisementProperties) {
                                write-verbose "Created Advertisement. Name = $($newAdvertisement.AdvertisementName)"
                                write-verbose "Created Advertisement. ID = $newAdvertisement"
                                Write-Verbose "Mandatory Deadline created: $($Adv.StartTime)"
                        }
                } else {
                        write-verbose "Created Advertisement. Name = $($newAdvertisement.AdvertisementName)"
                        write-verbose "Created Advertisement. ID = $newAdvertisement"
                        write-verbose "No Mandatory-Deadline defined"
                }
        }
}

Function New-SCCMProgram {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true, HelpMessage="Program Name")][String] $PrgName = "",
                [Parameter(Mandatory=$true, HelpMessage="Program PackageID")]$PrgPackageID,
                [Parameter(Mandatory=$false, HelpMessage="Program Comment")][String] $PrgComment = "",
                [Parameter(Mandatory=$false, HelpMessage="Program CommandLine")][String] $PrgCommandLine = "",
                [Parameter(Mandatory=$false, HelpMessage="Program MaxRunTime")]$PrgMaxRunTime,
                [Parameter(Mandatory=$false, HelpMessage="Program Diskspace Requirement")]$PrgSpaceReq,
                [Parameter(Mandatory=$false, HelpMessage="Program Working Directory")][String] $PrgWorkDir = "",
                [Parameter(Mandatory=$false, HelpMessage="Program Flags")] $PrgFlags
        )
        PROCESS {
                $programClass = [WMICLASS]"\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_Program"
                $newProgram = $programClass.createInstance()
                $newProgram.ProgramName = $PrgName
                $newProgram.PackageID = $PrgPackageID
                if ($PrgComment -ne "") { $newProgram.Comment = $PrgComment }
                if ($PrgCommandLine -ne "") { $newProgram.CommandLine = $PrgCommandLine }
                if ($PrgMaxRunTime -ne $null) { $newProgram.Duration = $PrgMaxRunTime} else { $newProgram.Duration = "0" }
                if ($PrgSpaceReq -ne $null) { $newProgram.DiskSpaceReq = $PrgSpaceReq }
                if ($PrgWorkDir -ne "") { $newProgram.WorkingDirectory = $PrgWorkDir }
                if ($PrgFlags -ne $null) { $newProgram.ProgramFlags = $PrgFlags} else { $newProgram.ProgramFlags = "135290880" }
                $newProgram.Put()
                $newProgram.Get()
                Write-Verbose "Return the new program for Package $($newProgram.PackageID)"
                return $newProgram
        }
}

Function Add-SCCMDistributionPoint {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true, HelpMessage="PackageID")][String] $DPPackageID,
                [Parameter(Mandatory=$false, HelpMessage="DistributionPoint Servername")][String]$DPName = "",
                [Parameter(Mandatory=$false, HelpMessage="All DistributionPoints of SiteCode")][String] $DPsSiteCode = "",
                [Parameter(Mandatory=$false, HelpMessage="Distribution Point Group")][String] $DPGroupName = "",
                [Switch] $AllDPs
        )
        PROCESS {
                if ($DPName -ne "") {
                        $Resource = Get-SCCMObject -SccmServer $SccmServer -class SMS_SystemResourceList -Filter "RoleName = 'SMS Distribution Point' and Servername = '$DPName'"
                        $DPClass = [WMICLASS]"\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_DistributionPoint"
                        $newDistributionPoint = $DPClass.createInstance()
                        $newDistributionPoint.PackageID = $DPPackageID
                        $newDistributionPoint.ServerNALPath = $Resource.NALPath
                        $newDistributionPoint.SiteCode = $Resource.SiteCode
                        $newDistributionPoint.Put()
                        $newDistributionPoint.Get()
                        Write-Verbose "Assigned Package: $($newDistributionPoint.PackageID)"
                }
                if ($DPsSiteCode -ne "") {
                        $ListOfResources = Get-SCCMObject -SccmServer $SccmServer -class SMS_SystemResourceList -Filter "RoleName = 'SMS Distribution Point' and SiteCode = '$DPsSiteCode'"
                        $DPClass = [WMICLASS]"\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_DistributionPoint"
                        $newDistributionPoint = $DPClass.createInstance()
                        $newDistributionPoint.PackageID = $DPPackageID
                        foreach ($resource in $ListOfResources) {
                                $newDistributionPoint.ServerNALPath = $Resource.NALPath
                                $newDistributionPoint.SiteCode = $Resource.SiteCode
                                $newDistributionPoint.Put()
                                $newDistributionPoint.Get()
                                Write-Verbose "Assigned Package: $($newDistributionPoint.PackageID)"
                        }
                }
                if ($DPGroupName -ne "") {
                        $DPGroup = Get-SCCMObject -sccmserver $SccmServer -class SMS_DistributionPointGroup -Filter "sGroupName = '$DPGroupName'"
                        $DPGroupNALPaths = $DPGroup.arrNALPath
                        $DPClass = [WMICLASS]"\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_DistributionPoint"
                        $newDistributionPoint = $DPClass.createInstance()
                        $newDistributionPoint.PackageID = $DPPackageID
                        foreach ($DPGroupNALPath in $DPGroupNALPaths) {
                                $DPResource = Get-SCCMObject -SccmServer $SccmServer -class SMS_SystemResourceList -Filter "RoleName = 'SMS Distribution Point'" | Where-Object {$_.NALPath -eq $DPGroupNALPath}
                                if ($DPResource -ne $null) {
                                        Write-Verbose "$DPResource"
                                        $newDistributionPoint.ServerNALPath = $DPResource.NALPath
                                        Write-Verbose "ServerNALPath = $($newDistributionPoint.ServerNALPath)"
                                        $newDistributionPoint.SiteCode = $DPResource.SiteCode
                                        Write-Verbose "SiteCode = $($newDistributionPoint.SiteCode)"
                                        $newDistributionPoint.Put()
                                        $newDistributionPoint.Get()
                                        Write-Host "Assigned Package: $($newDistributionPoint.PackageID) to $($DPResource.ServerName)"
                                } else {
                                        Write-Host "DP not found = $DPGroupNALPath"
                                }
                        }
                }
                if ($AllDPs) {
                        $ListOfResources = Get-SCCMObject -SccmServer $SccmServer -class SMS_SystemResourceList -Filter "RoleName = 'SMS Distribution Point'"
                        $DPClass = [WMICLASS]"\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_DistributionPoint"
                        $newDistributionPoint = $DPClass.createInstance()
                        $newDistributionPoint.PackageID = $DPPackageID
                        foreach ($resource in $ListOfResources) {
                                $newDistributionPoint.ServerNALPath = $Resource.NALPath
                                $newDistributionPoint.SiteCode = $Resource.SiteCode
                                $newDistributionPoint.Put()
                                $newDistributionPoint.Get()
                                Write-Verbose "Assigned Package: $($newDistributionPoint.PackageID) $($newDistributionPoint.ServerNALPath)"
                        }
                }
        }
}

Function Update-SCCMDriverPkgSourcePath {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true, HelpMessage="Current Path", ValueFromPipeline=$true)][String] $currentPath,
                [Parameter(Mandatory=$true, HelpMessage="New Path", ValueFromPipeline=$true)][String] $newPath
        )

        PROCESS {
                Get-SCCMDriverPackage -sccmserver $SccmServer | Where-Object {$_.PkgSourcePath -ilike "*$($currentPath)*" } | Foreach-Object {
                        $newSourcePath = ($_.PkgSourcePath -ireplace [regex]::Escape($currentPath), $newPath)
                        Write-Verbose "Changing from '$($_.PkgSourcePath)' to '$($newSourcePath)' on $($_.PackageID)"
                        $_.PkgSourcePath = $newSourcePath
                        $_.Put() | Out-Null
                }
        }
}

Function Update-SCCMPackageSourcePath {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true, HelpMessage="Current Path", ValueFromPipeline=$true)][String] $currentPath,
                [Parameter(Mandatory=$true, HelpMessage="New Path", ValueFromPipeline=$true)][String] $newPath
        )

        PROCESS {
                Get-SCCMPackage -sccmserver $SccmServer | Where-Object {$_.PkgSourcePath -ilike "*$($currentPath)*" } | Foreach-Object {
                        $newSourcePath = ($_.PkgSourcePath -ireplace [regex]::Escape($currentPath), $newPath)
                        Write-Verbose "Changing from '$($_.PkgSourcePath)' to '$($newSourcePath)' on $($_.PackageID)"
                        $_.PkgSourcePath = $newSourcePath
                        $_.Put() | Out-Null
                }
        }
}

Function Update-SCCMDriverSourcePathnotepad {
        [CmdletBinding()]
        PARAM (
                [Parameter(Mandatory=$true, HelpMessage="SCCM Server")][Alias("Server","SmsServer")][System.Object] $SccmServer,
                [Parameter(Mandatory=$true, HelpMessage="Current Path", ValueFromPipeline=$true)][String] $currentPath,
                [Parameter(Mandatory=$true, HelpMessage="New Path", ValueFromPipeline=$true)][String] $newPath
        )

        PROCESS {
                Get-SCCMDriver -sccmserver $SccmServer | Where-Object {$_.ContentSourcePath -ilike "*$($currentPath)*" } | Foreach-Object {
                        $newSourcePath = ($_.ContentSourcePath -ireplace [regex]::Escape($currentPath), $newPath)
                        Write-Verbose "Changing from '$($_.ContentSourcePath)' to '$($newSourcePath)' on $($_.PackageID)"
                        $_.ContentSourcePath = $newSourcePath
                        $_.Put() | Out-Null
                }
        }
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# EOF

Examples

# List all available SCCM commands
Get-SCCMCommands

# Create an SCCM-Connection to the local server
$sccm = Connect-SCCMServer -Verbose

# Create a new collection with a querybased collection rule and a direct member
$newCollection = New-SCCMCollection -SccmServer $sccm -name "Some Collection Name" -Verbose
Add-SCCMCollectionRule -Server $sccm -collectionID $newRoot.CollectionId -queryExpression "SELECT * FROM SMS_R_System" -queryRuleName "All Systems" -Verbose
Add-SCCMCollectionRule -Server $sccm -collectionID $newRoot.CollectionId -name "COMPUTER123" -Verbose

# Count files in the inboxes
$sccm | Get-SCCMInboxes

# Get a package
$MyPackage = Get-SCCMPackage -server $sccm -filter "Name = 'Some Package Name'"