Skip to content

Add Get-SqlDscServerProtocol public command with CIM support #2108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions source/Private/Get-ServerProtocolObjectByCim.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<#
.SYNOPSIS
Gets server protocol information using CIM instances.

.DESCRIPTION
This is a helper function that retrieves server protocol information
using CIM instances for better performance and compatibility.

.PARAMETER ServerName
Specifies the name of the server where the SQL Server instance is running.

.PARAMETER InstanceName
Specifies the name of the SQL Server instance.

.PARAMETER ProtocolName
Specifies the name of the network protocol.

.NOTES
This function tries multiple SQL Server CIM namespaces to find the
appropriate one for the SQL Server version installed.
#>
function Get-ServerProtocolObjectByCim
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$ServerName,

[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$InstanceName,

[Parameter(Mandatory = $true)]
[ValidateSet('TcpIp', 'NamedPipes', 'SharedMemory')]
[System.String]
$ProtocolName
)

Write-Verbose -Message (
$script:localizedData.ServerProtocol_UsingCimApproach -f $ProtocolName, $InstanceName, $ServerName
)

$protocolNameProperties = Get-ProtocolNameProperties -ProtocolName $ProtocolName

# Try to find the appropriate SQL Server version namespace
$sqlServerNamespaces = @(
'ROOT\Microsoft\SqlServer\ComputerManagement16', # SQL Server 2022
'ROOT\Microsoft\SqlServer\ComputerManagement15', # SQL Server 2019
'ROOT\Microsoft\SqlServer\ComputerManagement14', # SQL Server 2017
'ROOT\Microsoft\SqlServer\ComputerManagement13', # SQL Server 2016
'ROOT\Microsoft\SqlServer\ComputerManagement12', # SQL Server 2014
'ROOT\Microsoft\SqlServer\ComputerManagement11', # SQL Server 2012
'ROOT\Microsoft\SqlServer\ComputerManagement10' # SQL Server 2008
)

$serverProtocolObject = $null

foreach ($namespace in $sqlServerNamespaces)
{
try
{
Write-Verbose -Message (
$script:localizedData.ServerProtocol_TryingNamespace -f $namespace
)

$cimInstances = Get-CimInstance -ComputerName $ServerName -Namespace $namespace -ClassName 'ServerNetworkProtocol' -ErrorAction 'Stop'

$serverProtocolObject = $cimInstances | Where-Object -FilterScript {
$_.InstanceName -eq $InstanceName -and $_.ProtocolName -eq $protocolNameProperties.Name
}

if ($serverProtocolObject)
{
Write-Verbose -Message (
$script:localizedData.ServerProtocol_FoundProtocol -f $ProtocolName, $InstanceName, $namespace
)
break
}
}
catch
{
Write-Verbose -Message (
$script:localizedData.ServerProtocol_NamespaceNotFound -f $namespace, $_.Exception.Message
)
continue
}
}

if (-not $serverProtocolObject)
{
$errorMessage = $script:localizedData.ServerProtocol_CimProtocolNotFound -f $ProtocolName, $InstanceName, $ServerName
New-InvalidOperationException -Message $errorMessage
}

return $serverProtocolObject
}
83 changes: 83 additions & 0 deletions source/Private/Get-ServerProtocolObjectBySmo.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<#
.SYNOPSIS
Gets server protocol information using SMO objects.

.DESCRIPTION
This is a helper function that retrieves server protocol information
using SMO (SQL Server Management Objects) for backward compatibility.

.PARAMETER ServerName
Specifies the name of the server where the SQL Server instance is running.

.PARAMETER InstanceName
Specifies the name of the SQL Server instance.

.PARAMETER ProtocolName
Specifies the name of the network protocol.

.NOTES
This function uses the existing SMO approach that was originally implemented
in the Get-ServerProtocolObject private function.
#>
function Get-ServerProtocolObjectBySmo
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$ServerName,

[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$InstanceName,

[Parameter(Mandatory = $true)]
[ValidateSet('TcpIp', 'NamedPipes', 'SharedMemory')]
[System.String]
$ProtocolName
)

Write-Verbose -Message (
$script:localizedData.ServerProtocol_UsingSmoApproach -f $ProtocolName, $InstanceName, $ServerName
)

$serverProtocolObject = $null

$newObjectParameters = @{
TypeName = 'Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer'
ArgumentList = @($ServerName)
}

$managedComputerObject = New-Object @newObjectParameters

$serverInstance = $managedComputerObject.ServerInstances[$InstanceName]

if ($serverInstance)
{
$protocolNameProperties = Get-ProtocolNameProperties -ProtocolName $ProtocolName

$serverProtocolObject = $serverInstance.ServerProtocols[$protocolNameProperties.Name]

if ($serverProtocolObject)
{
Write-Verbose -Message (
$script:localizedData.ServerProtocol_FoundProtocol -f $ProtocolName, $InstanceName, 'SMO'
)
}
else
{
$errorMessage = $script:localizedData.ServerProtocol_SmoProtocolNotFound -f $ProtocolName, $InstanceName, $ServerName
New-InvalidOperationException -Message $errorMessage
}
}
else
{
$errorMessage = $script:localizedData.ServerProtocol_InstanceNotFound -f $InstanceName, $ServerName
New-InvalidOperationException -Message $errorMessage
}

return $serverProtocolObject
}
115 changes: 115 additions & 0 deletions source/Public/Get-SqlDscServerProtocol.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<#
.SYNOPSIS
Returns server protocol information for a SQL Server instance.

.DESCRIPTION
Returns server protocol information for a SQL Server instance using
either CIM instances or SMO (SQL Server Management Objects) depending
on availability. The command supports getting information for TcpIp,
NamedPipes, and SharedMemory protocols.

.PARAMETER ServerName
Specifies the name of the server where the SQL Server instance is running.
Defaults to the local computer name.

.PARAMETER InstanceName
Specifies the name of the SQL Server instance for which to return protocol
information.

.PARAMETER ProtocolName
Specifies the name of the network protocol to return information for.
Valid values are 'TcpIp', 'NamedPipes', and 'SharedMemory'.

.PARAMETER UseCim
Specifies to use CIM instances instead of SMO objects. This parameter
is optional and will be automatically determined based on availability.

.EXAMPLE
Get-SqlDscServerProtocol -InstanceName 'MSSQLSERVER' -ProtocolName 'TcpIp'

Returns TcpIp protocol information for the default SQL Server instance
on the local computer.

.EXAMPLE
Get-SqlDscServerProtocol -ServerName 'MyServer' -InstanceName 'MyInstance' -ProtocolName 'NamedPipes'

Returns NamedPipes protocol information for the MyInstance SQL Server
instance on the MyServer computer.

.EXAMPLE
Get-SqlDscServerProtocol -InstanceName 'MSSQLSERVER' -ProtocolName 'SharedMemory' -UseCim

Returns SharedMemory protocol information for the default SQL Server
instance using CIM instances.

.OUTPUTS
System.Object

.NOTES
This command supports both CIM and SMO approaches for retrieving server
protocol information. The CIM approach is preferred when available as
it provides better performance and compatibility.
#>
function Get-SqlDscServerProtocol
{
[CmdletBinding()]
param
(
[Parameter()]
[ValidateNotNullOrEmpty()]
[System.String]
$ServerName = (Get-ComputerName),

[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$InstanceName,

[Parameter(Mandatory = $true)]
[ValidateSet('TcpIp', 'NamedPipes', 'SharedMemory')]
[System.String]
$ProtocolName,

[Parameter()]
[System.Management.Automation.SwitchParameter]
$UseCim
)

Write-Verbose -Message (
$script:localizedData.ServerProtocol_GetState -f $ProtocolName, $InstanceName, $ServerName
)

$serverProtocolObject = $null

try
{
# Try CIM approach first if requested or if SMO is not available
if ($UseCim.IsPresent -or $script:preferCimOverSmo)
{
$serverProtocolObject = Get-ServerProtocolObjectByCim -ServerName $ServerName -InstanceName $InstanceName -ProtocolName $ProtocolName
}
else
{
# Fall back to SMO approach
$serverProtocolObject = Get-ServerProtocolObjectBySmo -ServerName $ServerName -InstanceName $InstanceName -ProtocolName $ProtocolName
}
}
catch
{
# If CIM fails and we haven't tried SMO, try SMO approach
if ($UseCim.IsPresent -or $script:preferCimOverSmo)
{
Write-Verbose -Message (
$script:localizedData.ServerProtocol_CimFallbackToSmo -f $ProtocolName, $InstanceName, $ServerName
)

$serverProtocolObject = Get-ServerProtocolObjectBySmo -ServerName $ServerName -InstanceName $InstanceName -ProtocolName $ProtocolName
}
else
{
throw
}
}

return $serverProtocolObject
}
12 changes: 12 additions & 0 deletions source/en-US/SqlServerDsc.strings.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,16 @@ ConvertFrom-StringData @'
## ConvertTo-SqlDscEditionName
ConvertTo_EditionName_ConvertingEditionId = Converting EditionId '{0}' to Edition name.
ConvertTo_EditionName_UnknownEditionId = The EditionId '{0}' is unknown and could not be converted.

## Get-SqlDscServerProtocol
ServerProtocol_GetState = Getting server protocol '{0}' information for instance '{1}' on server '{2}'.
ServerProtocol_UsingCimApproach = Using CIM approach to get server protocol '{0}' information for instance '{1}' on server '{2}'.
ServerProtocol_UsingSmoApproach = Using SMO approach to get server protocol '{0}' information for instance '{1}' on server '{2}'.
ServerProtocol_CimFallbackToSmo = CIM approach failed for protocol '{0}' on instance '{1}' on server '{2}', falling back to SMO approach.
ServerProtocol_TryingNamespace = Trying to connect to namespace '{0}'.
ServerProtocol_FoundProtocol = Found server protocol '{0}' for instance '{1}' using '{2}'.
ServerProtocol_NamespaceNotFound = Namespace '{0}' is not available: {1}
ServerProtocol_CimProtocolNotFound = Could not find server protocol '{0}' for instance '{1}' on server '{2}' using CIM approach.
ServerProtocol_SmoProtocolNotFound = Could not find server protocol '{0}' for instance '{1}' on server '{2}' using SMO approach.
ServerProtocol_InstanceNotFound = Could not find SQL Server instance '{0}' on server '{1}'.
'@
3 changes: 3 additions & 0 deletions source/prefix.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ $script:sqlServerDscCommonModulePath = Join-Path -Path $PSScriptRoot -ChildPath
Import-Module -Name $script:sqlServerDscCommonModulePath

$script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US'

# Preference variable for CIM over SMO approach
$script:preferCimOverSmo = $false
Loading
Loading