Sadly, Microsoft Enterprise Manager Configuration Manager (ConfigMgr) has no built-in methods to export or import boundaries and boundary groups. This shortcoming is reasonably easy to address with PowerShell though, so I did a quick search on the web and found a bunch of examples for boundaries but none for boundary groups (I didn’t look that much though). What I found, though, were longer, custom scripts that only provided export capabilities. Not liking these and thinking I could do better, I set out to create my own set of PowerShell one-liners for these tasks.
Boundaries
Import and export for boundaries are super simple using the built-in ConfigMgr cmdlets. Run these one-liners on any system with the console installed on it if you load the ConfigMgr PowerShell module first and switch to the provider for your site. Launch PowerShell directly from the ConfigMgr console using the Connect via Windows PowerShell main menu option if you don’t know how to do this manually.
Export
The following one-liner exports the name/description, the value, and the boundary type for all boundaries using the Get-CMBoundary cmdlet and saves it to a CSV at the specified location.
Get-CMBoundary | Select-Object -Property DisplayName,Value,BoundaryType | Export-CSV -Path <path>\<file>.csv -NoTypeInformation
Import
Import is as easy as export using the following one-liner and the same CSV that the above export one-liner creates. This one-liner loops through the items in the CSV and calls New-CMBoundary for each. Easy peasy.
Import-CSV -Path <path>\<file>.csv | ForEach-Object { New-CMBoundary -Name $_.DisplayName -Type $_.BoundaryType -Value $_.Value }
[su_note note_color=”#ffcb05″]Keep in mind that there is no graceful error handling here, so if the boundary already exists, you’ll get a standard, all in red, PowerShell error.[/su_note]
Boundary Groups
Boundary groups are a little more involved because the built-in cmdlets don’t list the site system associated with the boundary group and use a separate cmdlet to add boundaries to a boundary group. As with the boundary import and export one-liners above, run these one-liners on any system with the console installed on it if you load the ConfigMgr PowerShell module first and switch to the provider for your site.
Export
This long one-liner extracts the name, site assignment site code, member boundary names, and names of associated site systems and then saves all of that to a CSV at the specified location.
Get-CMBoundaryGroup | Select-Object -Property Name,DefaultSiteCode,@{Name = 'Boundaries'; Expression = { (Get-CMBoundary -BoundaryGroupName $_.Name).DisplayName -join ';'}}, @{Name='SiteSystems'; Expression = { ( (Get-WmiObject -ComputerName <SMSProvider> -Namespace root\sms\site_<sitecode> -Class SMS_BoundaryGroupSiteSystems -Filter "GroupID='$($_.GroupID)'").ServerNALPath | ForEach-Object { ($_ -split '\\\\')[2].trim('\\') }) -join ';' }} | Export-CSV -Path <path>\<file>.csv -NoTypeInformation
So, what does this crazy looking one-liner do? Let’s break it down.
Get-CMBoundaryGroup
Gets all of the boundary groups.Select-Object
Extracts certain properties including two calculated properties.@{Name = 'Boundaries'; Expression = { (Get-CMBoundary -BoundaryGroupName $_.Name).DisplayName -join ';'}}
The first calculated property gets the boundaries associated with the current boundary group, extracts their display names, and then joins them into a single string with a semi-colon separator.@{Name='SiteSystems'; Expression = { ( (Get-WmiObject -ComputerName <SMSProvider> -Namespace root\sms\site_<sitecode> -Class SMS_BoundaryGroupSiteSystems -Filter "GroupID='$($_.GroupID)'").ServerNALPath | ForEach-Object { ($_ -split '\\\\')[2].trim('\\') }) -join ';' }}
The second calculated property uses WMI to get the site systems associated with the boundary group (from the SMS_BoundaryGroupSiteSystems class). The ServerNALPath attribute stores the site systems; this attribute is processed using a split and trim to get the actual server name and then joined into a single string with a semi-colon separator.
[su_note note_color=”#ffcb05″]Make sure to replace [sitecode] with your site’s three character site code and [SMSProvider] with the name of the site system hosting your SMS Provider (which is usually the primary site server, but not always).[/su_note]
Import
Import is a two-step process that first imports the boundary group and then adds the boundaries to that boundary group. You can do these two steps using a single, complex, and long one-liner, but I decided to break it up into two smaller one-liners.
This first one-liner loops through the specified CSV file and creates the boundary groups using the New-CMBoundaryGroup and Set-CMBoundaryGroup cmdlets.
Import-CSV -Path <path>\<file>.csv | ForEach-Object { New-CMBoundaryGroup -Name $_.Name; if($_.DefaultSiteCode) { Set-CMBoundaryGroup -Name $_.Name -DefaultSiteCode $_.DefaultSiteCode }; if($_.SiteSystems) { Set-CMBoundaryGroup -Name $_.Name -AddSiteSystemServerName ($_.SiteSystems -split ';')} }
This one-liner is fairly straight-forward but does contain a couple of embedded if statements that conditionally call the Set-CMBoundaryGroup cmdlet because the New-CMBoundaryGroup cmdlet doesn’t handle blank values.
[su_note note_color=”#ffcb05″]Keep in mind that there is no graceful error handling here either so if the boundary group already exists, you’ll get a standard, all in red, PowerShell error.[/su_note]
This second one-liner once again loops through the specified CSV file and adds the boundaries to the boundary groups using the Add-BoundaryToBoundaryGroup cmdlet.
Import-CSV -Path <path>\<file>.csv | ForEach-Object { foreach($boundary in ($_.Boundaries -split ';')) { Add-CMBoundaryToGroup -BoundaryGroupName $_.Name -BoundaryName $boundary } }
The only complexity with this one-liner is that the Add-BoundaryToBoundaryGroup cmdlet only takes a single boundary at a time and so must be called for each boundary in the data file.
Summary
There you have five easy one-lines for complete boundary and boundary group import and export for backup and restore, migration, simple kicks, or whatever your purpose. Yes, these could all be made into scripts of their own or combined into one larger, master script, but part of the beauty of PowerShell is that you don’t have to, but you can if you want to.
Thanks so much for your expertise and help, this made finding which boundary groups a particular site system resided in for decommissioning some server 2008 site systems to be replaced with some server 2019.
Thank You Mate…This really helped me
You’re very welcome.
This is amazing! thanks!- Gives me an easy recovery option as I’m about to change (properly configure) all my boundaries and BGs. 🙂