- msdb.dbo.sysmanagement_shared_registered_servers_internal
- msdb.dbo.sysmanagement_shared_server_groups_internal
The central SQL Server is named SQL1. The database is named dba_utilities. The table called instances is used to store the instances that are automatically or manually discovered in your organization. The stored procedure called sel_registered_servers is used to show the list of servers and respective groups. Additionally, sel_registered_servers_to_drop is used to show the list of servers that are no longer in your organization.
-- table for instances
create table instances(
logical_name varchar(255) not null constraint instances_pk primary key
,physical_name varchar(255) not null
,support_code varchar(10) not null
,sql_version varchar(10) not null
)
go
-- insert instances
insert instances values('SQL1','COMPUTER3\SQL1','TEST','2012')
insert instances values('SQL2','COMPUTER1\SQL2','PROD','2008')
insert instances values('SQL3','COMPUTER1\SQL3','PROD','2008')
insert instances values('SQL4','COMPUTER2\SQL4','PROD','2012')
insert instances values('SQL5','COMPUTER3\SQL5','TEST','2012')
insert instances values('SQL6','COMPUTER3\SQL6','TEST','2014')
go
-- stored procedure to show registered servers
create proc sel_registered_servers
as
select
'Support Version' group1
,support_code group2
,sql_version group3
,logical_name
,physical_name
from instances
where logical_name <> 'SQL1' -- central server cannot be added
union
select
'Version Support' group1
,sql_version group2
,support_code group3
,logical_name
,physical_name
from instances
where logical_name <> 'SQL1' -- central server cannot be added
go
-- stored procedure to show obsolete servers
create proc sel_registered_servers_to_drop
as
select distinct name
into #temp
from msdb.dbo.sysmanagement_shared_registered_servers_internal
select t.name logical_name
from instances i
right join #temp t
on i.logical_name = t.name
where i.logical_name is null
drop table #temp
go
Output of sel_registered_servers
The PowerShell script can read the results of the stored procedures and hierarchically navigate through the directory tree and create, update, or drop server registrations
function Add-RegisteredServer ($group1, $group2, $group3, $logicalName, $physicalName)
{
$serverGroups = $registeredServer.DatabaseEngineServerGroup
$groupList = @($group1, $group2, $group3)
# navigate down the hierarchy
foreach ($group in $groupList)
{
if ($serverGroups.ServerGroups[$group] -eq $null)
{
$newGroup = New-Object Microsoft.SqlServer.Management.RegisteredServers.ServerGroup($serverGroups, $group)
$newGroup.create()
$serverGroups.refresh()
}
$serverGroups = $serverGroups.ServerGroups[$group]
}
# create or alter the registered server
if($serverGroups.RegisteredServers.name -contains $logicalName)
{
$oldServer = $serverGroups.RegisteredServers[$logicalName]
if ($oldServer.ServerName -ne $physicalName)
{
Write-Host "$group1 $group2 $group3 $logicalName Altered"
$oldServer.ServerName = $physicalName
$oldServer.Alter()
}
}
else
{
Write-Host "$group1 $group2 $group3 $logicalName Created"
$newServer = New-Object Microsoft.SqlServer.Management.RegisteredServers.RegisteredServer($serverGroups, $logicalName)
$newServer.ServerName = $physicalName
$newServer.Create()
}
}
function Drop-RegisteredServer ($logicalName)
{
$serverGroups = $registeredServer.DatabaseEngineServerGroup
$groupList1 = $serverGroups.ServerGroups.Name
foreach ($group1 in $groupList1)
{
$groupList2 = $serverGroups.ServerGroups[$group1].ServerGroups.Name
foreach ($group2 in $groupList2)
{
$groupList3 = $serverGroups.ServerGroups[$group1].ServerGroups[$group2].ServerGroups.Name
foreach ($group3 in $groupList3)
{
$oldGroup = $serverGroups.ServerGroups[$group1].ServerGroups[$group2].ServerGroups[$group3]
if($oldGroup.RegisteredServers.Name -contains $logicalName)
{
Write-Host "$group1 $group2 $group3 $logicalName Dropped"
$oldServer = $oldGroup.RegisteredServers[$logicalName]
$oldServer.Drop()
}
}
}
}
}
function Drop-RegisteredServerGroup ()
{
# Drop group3
$serverGroups = $registeredServer.DatabaseEngineServerGroup
$groupList1 = $serverGroups.ServerGroups.Name
foreach ($group1 in $groupList1)
{
$groupList2 = $serverGroups.ServerGroups[$group1].ServerGroups.Name
foreach ($group2 in $groupList2)
{
$groupList3 = $serverGroups.ServerGroups[$group1].ServerGroups[$group2].ServerGroups.Name
foreach ($group3 in $groupList3)
{
$oldGroup = $serverGroups.ServerGroups[$group1].ServerGroups[$group2].ServerGroups[$group3]
if($oldGroup.RegisteredServers.Count -eq 0)
{
Write-Host "$group1 $group2 $group3 Dropped"
$oldGroup.Drop()
}
}
}
}
# Drop group2
$serverGroups = $registeredServer.DatabaseEngineServerGroup
$groupList1 = $serverGroups.ServerGroups.Name
foreach ($group1 in $groupList1)
{
$groupList2 = $serverGroups.ServerGroups[$group1].ServerGroups.Name
foreach ($group2 in $groupList2)
{
$oldGroup = $serverGroups.ServerGroups[$group1].ServerGroups[$group2]
if($oldGroup.ServerGroups.Count -eq 0)
{
Write-Host "$group1 $group2 Dropped"
$oldGroup.Drop()
}
}
}
# Drop group2
$serverGroups = $registeredServer.DatabaseEngineServerGroup
$groupList1 = $serverGroups.ServerGroups.Name
foreach ($group1 in $groupList1)
{
$oldGroup = $serverGroups.ServerGroups[$group1]
if($oldGroup.ServerGroups.Count -eq 0)
{
Write-Host "$group1 Dropped"
$oldGroup.Drop()
}
}
}
# Main Program
$tarSrv = "COMPUTER3\SQL1"
$tarDB = "dba_utilities"
try
{
$server = New-Object Microsoft.SqlServer.Management.Smo.Server($tarSrv)
$registeredServer = New-Object Microsoft.SqlServer.Management.RegisteredServers.RegisteredServersStore($server.ConnectionContext.SqlConnectionObject)
$tarCon = New-Object System.Data.SQLClient.SQLConnection("Data Source=$tarSrv;Initial Catalog=$tarDB; Integrated Security=True;")
$tarCon.Open()
$tarCmd = New-Object system.Data.SqlClient.SqlCommand("exec sel_registered_servers", $tarCon)
$instances = $tarCmd.ExecuteReader()
while ($instances.Read())
{
$group1 = $instances.GetValue(0)
$group2 = $instances.GetValue(1)
$group3 = $instances.GetValue(2)
$logicalName = $instances.GetValue(3)
$physicalName= $instances.GetValue(4)
Add-RegisteredServer $group1 $group2 $group3 $logicalName $physicalName
}
$instances.Close()
$tarCmd.CommandText = "exec sel_registered_servers_to_drop"
$instances = $tarCmd.ExecuteReader()
while ($instances.Read())
{
$logicalName = $instances.GetValue(0)
Drop-RegisteredServer $logicalName
}
$instances.Close()
Drop-RegisteredServerGroup
$tarCon.Close()
$tarCon.Dispose()
}
catch
{
$e = $_ | select -ExpandProperty InvocationInfo
$m = $_.Exception.Message.TrimEnd().Replace("'","") + ", " + $e.ScriptLineNumber.ToString() + ", " + $e.OffsetInLine.ToString()
throw $m
}

