Skip to content

Commit

Permalink
Refactor SqlServerNetwork to not load assembly from GAC (issue dsccom…
Browse files Browse the repository at this point in the history
  • Loading branch information
johlju committed Jul 4, 2018
1 parent 4f9abea commit 291b7a2
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 361 deletions.
164 changes: 77 additions & 87 deletions DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ function Get-TargetResource
[OutputType([System.Collections.Hashtable])]
param
(
[Parameter()]
[ValidateNotNullOrEmpty()]
[System.String]
$ServerName = $env:COMPUTERNAME,

[Parameter(Mandatory = $true)]
[System.String]
$InstanceName,
Expand All @@ -33,31 +38,24 @@ function Get-TargetResource
$ProtocolName
)

try
{
$applicationDomainObject = Register-SqlWmiManagement -SQLInstanceName $InstanceName

$managedComputerObject = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer
$sql = Connect-SQL -SQLServer $ServerName -SQLInstanceName $InstanceName

Write-Verbose -Message ($script:localizedData.GetNetworkProtocol -f $ProtocolName, $InstanceName)
$tcp = $managedComputerObject.ServerInstances[$InstanceName].ServerProtocols[$ProtocolName]
$managedComputerObject = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer

Write-Verbose -Message $script:localizedData.ReadingNetworkProperties
$returnValue = @{
InstanceName = $InstanceName
ProtocolName = $ProtocolName
IsEnabled = $tcp.IsEnabled
TcpDynamicPort = ($tcp.IPAddresses['IPAll'].IPAddressProperties['TcpDynamicPorts'].Value -ge 0)
TcpPort = $tcp.IPAddresses['IPAll'].IPAddressProperties['TcpPort'].Value
}
Write-Verbose -Message ($script:localizedData.GetNetworkProtocol -f $ProtocolName, $InstanceName)
$tcp = $managedComputerObject.ServerInstances[$InstanceName].ServerProtocols[$ProtocolName]

$returnValue.Keys | ForEach-Object {
Write-Verbose -Message "$_ = $($returnValue[$_])"
}
Write-Verbose -Message $script:localizedData.ReadingNetworkProperties
$returnValue = @{
InstanceName = $InstanceName
ProtocolName = $ProtocolName
IsEnabled = $tcp.IsEnabled
TcpDynamicPort = ($tcp.IPAddresses['IPAll'].IPAddressProperties['TcpDynamicPorts'].Value -ge 0)
TcpPort = $tcp.IPAddresses['IPAll'].IPAddressProperties['TcpPort'].Value
}
finally
{
Unregister-SqlAssemblies -ApplicationDomain $applicationDomainObject

$returnValue.Keys | ForEach-Object {
Write-Verbose -Message "$_ = $($returnValue[$_])"
}

return $returnValue
Expand Down Expand Up @@ -145,90 +143,82 @@ function Set-TargetResource

$getTargetResourceResult = Get-TargetResource -InstanceName $InstanceName -ProtocolName $ProtocolName

try
{
$applicationDomainObject = Register-SqlWmiManagement -SQLInstanceName $InstanceName

$desiredState = @{
InstanceName = $InstanceName
ProtocolName = $ProtocolName
IsEnabled = $IsEnabled
TcpDynamicPort = $TcpDynamicPort
TcpPort = $TcpPort
}

$isRestartNeeded = $false

$managedComputerObject = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer

Write-Verbose -Message ($script:localizedData.GetNetworkProtocol -f $ProtocolName, $InstanceName)
$tcp = $managedComputerObject.ServerInstances[$InstanceName].ServerProtocols[$ProtocolName]
$desiredState = @{
InstanceName = $InstanceName
ProtocolName = $ProtocolName
IsEnabled = $IsEnabled
TcpDynamicPort = $TcpDynamicPort
TcpPort = $TcpPort
}

Write-Verbose -Message ($script:localizedData.CheckingProperty -f 'IsEnabled')
if ($desiredState.IsEnabled -ine $getTargetResourceResult.IsEnabled)
{
Write-Verbose -Message ($script:localizedData.UpdatingProperty -f 'IsEnabled', $getTargetResourceResult.IsEnabled, $desiredState.IsEnabled)
$tcp.IsEnabled = $desiredState.IsEnabled
$tcp.Alter()
$isRestartNeeded = $false

$isRestartNeeded = $true
}
# Get-TargetResource makes the necessary calls so the type ManagedComputer is available.
$managedComputerObject = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer

Write-Verbose -Message ($script:localizedData.CheckingProperty -f 'TcpDynamicPort')
if ($desiredState.TcpDynamicPort -ne $getTargetResourceResult.TcpDynamicPort)
{
# Translates the current and desired state to a string for display
$dynamicPortDisplayValueTable = @{
$true = 'enabled'
$false = 'disabled'
}
Write-Verbose -Message ($script:localizedData.GetNetworkProtocol -f $ProtocolName, $InstanceName)
$tcp = $managedComputerObject.ServerInstances[$InstanceName].ServerProtocols[$ProtocolName]

# Translates the desired state to a valid value
$desiredDynamicPortValue = @{
$true = '0'
$false = ''
}
Write-Verbose -Message ($script:localizedData.CheckingProperty -f 'IsEnabled')
if ($desiredState.IsEnabled -ine $getTargetResourceResult.IsEnabled)
{
Write-Verbose -Message ($script:localizedData.UpdatingProperty -f 'IsEnabled', $getTargetResourceResult.IsEnabled, $desiredState.IsEnabled)
$tcp.IsEnabled = $desiredState.IsEnabled
$tcp.Alter()

$fromTcpDynamicPortDisplayValue = $dynamicPortDisplayValueTable[$getTargetResourceResult.TcpDynamicPort]
$toTcpDynamicPortDisplayValue = $dynamicPortDisplayValueTable[$desiredState.TcpDynamicPort]
$isRestartNeeded = $true
}

Write-Verbose -Message ($script:localizedData.UpdatingProperty -f 'TcpDynamicPorts', $fromTcpDynamicPortDisplayValue, $toTcpDynamicPortDisplayValue)
$tcp.IPAddresses['IPAll'].IPAddressProperties['TcpDynamicPorts'].Value = $desiredDynamicPortValue[$desiredState.TcpDynamicPort]
$tcp.Alter()
Write-Verbose -Message ($script:localizedData.CheckingProperty -f 'TcpDynamicPort')
if ($desiredState.TcpDynamicPort -ne $getTargetResourceResult.TcpDynamicPort)
{
# Translates the current and desired state to a string for display
$dynamicPortDisplayValueTable = @{
$true = 'enabled'
$false = 'disabled'
}

$isRestartNeeded = $true
# Translates the desired state to a valid value
$desiredDynamicPortValue = @{
$true = '0'
$false = ''
}

Write-Verbose -Message ($script:localizedData.CheckingProperty -f 'TcpPort')
if ($desiredState.TcpPort -ine $getTargetResourceResult.TcpPort)
{
$fromTcpPort = $getTargetResourceResult.TcpPort
if ($fromTcpPort -eq '')
{
$fromTcpPort = 'none'
}
$fromTcpDynamicPortDisplayValue = $dynamicPortDisplayValueTable[$getTargetResourceResult.TcpDynamicPort]
$toTcpDynamicPortDisplayValue = $dynamicPortDisplayValueTable[$desiredState.TcpDynamicPort]

$toTcpPort = $desiredState.TcpPort
if ($toTcpPort -eq '')
{
$toTcpPort = 'none'
}
Write-Verbose -Message ($script:localizedData.UpdatingProperty -f 'TcpDynamicPorts', $fromTcpDynamicPortDisplayValue, $toTcpDynamicPortDisplayValue)
$tcp.IPAddresses['IPAll'].IPAddressProperties['TcpDynamicPorts'].Value = $desiredDynamicPortValue[$desiredState.TcpDynamicPort]
$tcp.Alter()

Write-Verbose -Message ($script:localizedData.UpdatingProperty -f 'TcpPort', $fromTcpPort, $toTcpPort)
$tcp.IPAddresses['IPAll'].IPAddressProperties['TcpPort'].Value = $desiredState.TcpPort
$tcp.Alter()
$isRestartNeeded = $true
}

$isRestartNeeded = $true
Write-Verbose -Message ($script:localizedData.CheckingProperty -f 'TcpPort')
if ($desiredState.TcpPort -ine $getTargetResourceResult.TcpPort)
{
$fromTcpPort = $getTargetResourceResult.TcpPort
if ($fromTcpPort -eq '')
{
$fromTcpPort = 'none'
}

if ($RestartService -and $isRestartNeeded)
$toTcpPort = $desiredState.TcpPort
if ($toTcpPort -eq '')
{
Restart-SqlService -SQLServer $ServerName -SQLInstanceName $InstanceName -Timeout $RestartTimeout
$toTcpPort = 'none'
}

Write-Verbose -Message ($script:localizedData.UpdatingProperty -f 'TcpPort', $fromTcpPort, $toTcpPort)
$tcp.IPAddresses['IPAll'].IPAddressProperties['TcpPort'].Value = $desiredState.TcpPort
$tcp.Alter()

$isRestartNeeded = $true
}
finally

if ($RestartService -and $isRestartNeeded)
{
Unregister-SqlAssemblies -ApplicationDomain $applicationDomainObject
Restart-SqlService -SQLServer $ServerName -SQLInstanceName $InstanceName -Timeout $RestartTimeout
}
}

Expand Down
145 changes: 0 additions & 145 deletions SqlServerDscHelper.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -179,151 +179,6 @@ function Connect-SQLAnalysis
return $analysisServicesObject
}

<#
.SYNOPSIS
Creates a new application domain and loads the assemblies Microsoft.SqlServer.Smo
for the correct SQL Server major version.
An isolated application domain is used to load version specific assemblies, this needed
if there is multiple versions of SQL server in the same configuration. So that a newer
version of SQL is not using an older version of the assembly, or vice verse.
This should be unloaded using the helper function Unregister-SqlAssemblies or
using [System.AppDomain]::Unload($applicationDomainObject).
.PARAMETER SQLInstanceName
String containing the SQL Server Database Engine instance name to get the major SQL version from.
.PARAMETER ApplicationDomain
An optional System.AppDomain object to load the assembly into.
.OUTPUTS
System.AppDomain. Returns the application domain object with SQL SMO loaded.
#>
function Register-SqlSmo
{
[CmdletBinding()]
[OutputType([System.AppDomain])]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$SQLInstanceName,

[Parameter()]
[ValidateNotNullOrEmpty()]
[System.AppDomain]
$ApplicationDomain
)

$sqlMajorVersion = Get-SqlInstanceMajorVersion -SQLInstanceName $SQLInstanceName

Write-Verbose -Message ($script:localizedData.SqlMajorVersion -f $sqlMajorVersion) -Verbose

if ( -not $ApplicationDomain )
{
$applicationDomainName = $MyInvocation.MyCommand.ModuleName
Write-Verbose -Message ($script:localizedData.CreatingApplicationDomain -f $applicationDomainName) -Verbose
$applicationDomainObject = [System.AppDomain]::CreateDomain($applicationDomainName)
}
else
{
Write-Verbose -Message ($script:localizedData.ReusingApplicationDomain -f $ApplicationDomain.FriendlyName) -Verbose
$applicationDomainObject = $ApplicationDomain
}

$sqlSmoAssemblyName = "Microsoft.SqlServer.Smo, Version=$sqlMajorVersion.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
Write-Verbose -Message ($script:localizedData.LoadingAssembly -f $sqlSmoAssemblyName) -Verbose
$applicationDomainObject.Load($sqlSmoAssemblyName) | Out-Null

return $applicationDomainObject
}

<#
.SYNOPSIS
Creates a new application domain and loads the assemblies Microsoft.SqlServer.Smo and
Microsoft.SqlServer.SqlWmiManagement for the correct SQL Server major version.
An isolated application domain is used to load version specific assemblies, this needed
if there is multiple versions of SQL server in the same configuration. So that a newer
version of SQL is not using an older version of the assembly, or vice verse.
This should be unloaded using the helper function Unregister-SqlAssemblies or
using [System.AppDomain]::Unload($applicationDomainObject) preferably in a finally block.
.PARAMETER SQLInstanceName
String containing the SQL Server Database Engine instance name to get the major SQL version from.
.PARAMETER ApplicationDomain
An optional System.AppDomain object to load the assembly into.
.OUTPUTS
System.AppDomain. Returns the application domain object with SQL WMI Management loaded.
#>
function Register-SqlWmiManagement
{
[CmdletBinding()]
[OutputType([System.AppDomain])]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$SQLInstanceName,

[Parameter()]
[ValidateNotNull()]
[System.AppDomain]
$ApplicationDomain
)

$sqlMajorVersion = Get-SqlInstanceMajorVersion -SQLInstanceName $SQLInstanceName
Write-Verbose -Message ($script:localizedData.SqlMajorVersion -f $sqlMajorVersion) -Verbose

<#
Must register Microsoft.SqlServer.Smo first because that is a
dependency of Microsoft.SqlServer.SqlWmiManagement.
#>
if (-not $ApplicationDomain)
{
$applicationDomainObject = Register-SqlSmo -SQLInstanceName $SQLInstanceName
}
# Returns zero (0) objects if the assembly is not found
elseif (-not ($ApplicationDomain.GetAssemblies().FullName -match 'Microsoft.SqlServer.Smo'))
{
$applicationDomainObject = Register-SqlSmo -SQLInstanceName $SQLInstanceName -ApplicationDomain $ApplicationDomain
}

$sqlSqlWmiManagementAssemblyName = "Microsoft.SqlServer.SqlWmiManagement, Version=$sqlMajorVersion.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
Write-Verbose -Message ($script:localizedData.LoadingAssembly -f $sqlSqlWmiManagementAssemblyName) -Verbose
$applicationDomainObject.Load($sqlSqlWmiManagementAssemblyName) | Out-Null

return $applicationDomainObject
}

<#
.SYNOPSIS
Unloads all assemblies in an application domain. It unloads the application domain.
.PARAMETER ApplicationDomain
System.AppDomain object containing the SQL assemblies to unload.
#>
function Unregister-SqlAssemblies
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNull()]
[System.AppDomain]
$ApplicationDomain
)

Write-Verbose -Message ($script:localizedData.UnloadingApplicationDomain -f $ApplicationDomain.FriendlyName) -Verbose
[System.AppDomain]::Unload($ApplicationDomain)
}

<#
.SYNOPSIS
Returns the major SQL version for the specific instance.
Expand Down
Loading

0 comments on commit 291b7a2

Please sign in to comment.