HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

How does the PowerShell SQLPS SQLSERVER provider detect central management servers in SQLRegistration\Central Management Server Group

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
theprovidergroupserverscentralsqlserverpowershellsqlregistrationserverdoes

Problem

I'm experiencing odd behavior with the PowerShell SQLSERVER provider and the SQLRegistration\Central Management Server Group directory. Below are the behaviors. I would like to know how the SQLSERVER provider knows what CMS's are registered so that I can understand why it doesn't seem to notice the registration when done in SSMS 2014 (see below for detailed behavior). Also, why my connection fails when I know the instance is online.

Setup

Machine

  • localhost



Instances

  • localhost\SQL2012



  • localhost\SQL2014



  • localhost\SQL2014_1



Behavior 1

Using SSMS 2014, I registered localhost\SQL2012 as a CMS. Executing this code returns no items.

PS SQLSERVER:\SQLRegistration\Central Management Server Group> dir


Open and closing the PowerShell console and SSMS does not change the results. If I open SSMS 2012 and register localhost\SQL2012 as a CMS and re-run the above command, I see localhost\SQL2012 registered as expected.

Behavior 2

After getting the server to list successfully...


Directory: Microsoft.SqlServer.Management.PSProvider\SqlServer::SQLSERVER:\SQLRegistration\Central Management
Server Group


Mode Name





  • localhost\SQL2012




And running the below command to try and navigate to my registered server groups fails with the below error, even though the instance is online and available.

PS SQLSERVER:\SQLRegistration\Central Management Server Group> Set-Location "localhost\SQL2012\"



Set-Location : Cannot find path 'SQLSERVER:\SQLRegistration\Central Management Server Group\localhost\SQL2012\'
because it does not exist.
At line:1 char:1
+ Set-Location "localhost\SQL2012\"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (SQLSERVER:\SQLR...alhost\SQL2012:String) [Set-Location], ItemNotFoundE
xception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand

Update 1

SMO seems to work fine. The below code successful

Solution

Shawn's explanation about discrepancies between SQL Server version seems on target. For this reason, I believe the SMO is a more stable method. I'm going forward using the below code.

Import-Module SQLPS -DisableNameChecking

Function Parse-ServerGroup($serverGroup)
{
    $results = $serverGroup.RegisteredServers;
    foreach($group in $serverGroup.ServerGroups)
    {
        $results += Parse-ServerGroup -serverGroup $group;
    }
    return $results;
}

Function Get-ServerList ([string]$cmsName, [string]$serverGroup, [switch]$recurse)
{

    $connectionString = "data source=$cmsName;initial catalog=master;integrated security=sspi;"
$sqlConnection = New-Object ("System.Data.SqlClient.SqlConnection") $connectionstring
    $conn = New-Object ("Microsoft.SQLServer.Management.common.serverconnection") $sqlconnection
    $cmsStore = New-Object Microsoft.SqlServer.Management.RegisteredServers.RegisteredServersStore($conn)
    $cmsRootGroup = $cmsStore.ServerGroups["DatabaseEngineServerGroup"].ServerGroups[$serverGroup]

    if($recurse)
    {
        return Parse-ServerGroup -serverGroup $cmsRootGroup | select ServerName
    }
    else
    {
        return $cmsRootGroup.RegisteredServers | select ServerName
    }
}

Get-ServerList -cmsName "localhost\SQL2012" -serverGroup "Production" -recurse | Format-Table

Code Snippets

Import-Module SQLPS -DisableNameChecking

Function Parse-ServerGroup($serverGroup)
{
    $results = $serverGroup.RegisteredServers;
    foreach($group in $serverGroup.ServerGroups)
    {
        $results += Parse-ServerGroup -serverGroup $group;
    }
    return $results;
}

Function Get-ServerList ([string]$cmsName, [string]$serverGroup, [switch]$recurse)
{

    $connectionString = "data source=$cmsName;initial catalog=master;integrated security=sspi;"
$sqlConnection = New-Object ("System.Data.SqlClient.SqlConnection") $connectionstring
    $conn = New-Object ("Microsoft.SQLServer.Management.common.serverconnection") $sqlconnection
    $cmsStore = New-Object Microsoft.SqlServer.Management.RegisteredServers.RegisteredServersStore($conn)
    $cmsRootGroup = $cmsStore.ServerGroups["DatabaseEngineServerGroup"].ServerGroups[$serverGroup]

    if($recurse)
    {
        return Parse-ServerGroup -serverGroup $cmsRootGroup | select ServerName
    }
    else
    {
        return $cmsRootGroup.RegisteredServers | select ServerName
    }
}

Get-ServerList -cmsName "localhost\SQL2012" -serverGroup "Production" -recurse | Format-Table

Context

StackExchange Database Administrators Q#77872, answer score: 2

Revisions (0)

No revisions yet.