-
Notifications
You must be signed in to change notification settings - Fork 225
/
Copy pathImport-SqlDscPreferredModule.ps1
189 lines (157 loc) · 6.92 KB
/
Import-SqlDscPreferredModule.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
<#
.SYNOPSIS
Imports the module SqlServer (preferred) or SQLPS in a standardized way.
.DESCRIPTION
Imports the module SqlServer (preferred) or SQLPS in a standardized way.
The module is always imported globally.
.PARAMETER PreferredModule
Specifies the name of the preferred module. Defaults to 'SqlServer'.
.PARAMETER Force
Forces the removal of the previous SQL module, to load the same or newer
version fresh. This is meant to make sure the newest version is used, with
the latest assemblies.
.EXAMPLE
Import-SqlDscPreferredModule
Imports the default preferred module (SqlServer) if it exist, otherwise
it will try to import the module SQLPS.
.EXAMPLE
Import-SqlDscPreferredModule -Force
Removes any already loaded module of the default preferred module (SqlServer)
and the module SQLPS, then it will forcibly import the default preferred
module if it exist, otherwise it will try to import the module SQLPS.
.EXAMPLE
Import-SqlDscPreferredModule -PreferredModule 'OtherSqlModule'
Imports the specified preferred module OtherSqlModule if it exist, otherwise
it will try to import the module SQLPS.
#>
function Import-SqlDscPreferredModule
{
[CmdletBinding()]
param
(
[Parameter()]
[System.String]
$PreferredModule = 'SqlServer',
[Parameter()]
[System.Management.Automation.SwitchParameter]
$Force
)
if ($Force.IsPresent)
{
Write-Verbose -Message $script:localizedData.PreferredModule_ForceRemoval
Remove-Module -Name @(
$PreferredModule,
'SQLPS',
'SQLASCmdlets' # cSpell: disable-line
) -Force -ErrorAction 'SilentlyContinue'
}
else
{
<#
Check if either of the modules are already loaded into the session.
Prefer to use the first one (in order found).
NOTE: There should actually only be either SqlServer or SQLPS loaded,
otherwise there can be problems with wrong assemblies being loaded.
#>
$loadedModuleName = (Get-Module -Name @($PreferredModule, 'SQLPS') | Select-Object -First 1).Name
if ($loadedModuleName)
{
Write-Verbose -Message ($script:localizedData.PreferredModule_AlreadyImported -f $loadedModuleName)
return
}
}
$availableModuleName = $null
# Get the newest SqlServer module if more than one exist
$availableModule = Get-Module -FullyQualifiedName $PreferredModule -ListAvailable |
Sort-Object -Property 'Version' -Descending |
Select-Object -First 1 -Property 'Name', 'Path', 'Version'
if ($availableModule)
{
$availableModuleName = $availableModule.Name
Write-Verbose -Message ($script:localizedData.PreferredModule_ModuleFound -f $availableModuleName)
}
else
{
Write-Verbose -Message ($script:localizedData.PreferredModule_ModuleNotFound)
# Only run on Windows that has Machine state.
if (-not ($IsLinux -or $IsMacOS))
{
<#
After installing SQL Server the current PowerShell session doesn't know
about the new path that was added for the SQLPS module. This reloads
PowerShell session environment variable PSModulePath to make sure it
contains all paths.
#>
<#
Get the environment variables from all targets session, user and machine.
Casts the value to System.String to convert $null values to empty string.
#>
$modulePathSession = [System.String] [System.Environment]::GetEnvironmentVariable('PSModulePath')
$modulePathUser = [System.String] [System.Environment]::GetEnvironmentVariable('PSModulePath', 'User')
$modulePathMachine = [System.String] [System.Environment]::GetEnvironmentVariable('PSModulePath', 'Machine')
$modulePath = $modulePathSession + ';' + $modulePathUser + ';' + $modulePathMachine
$modulePathArray = $modulePath -split ';' |
Where-Object -FilterScript {
-not [System.String]::IsNullOrEmpty($_)
} |
Sort-Object -Unique
$modulePath = $modulePathArray -join ';'
Set-PSModulePath -Path $modulePath
}
# Get the newest SQLPS module if more than one exist.
$availableModule = Get-Module -FullyQualifiedName 'SQLPS' -ListAvailable |
Select-Object -Property Name, Path, @{
Name = 'Version'
Expression = {
# Parse the build version number '120', '130' from the Path.
(Select-String -InputObject $_.Path -Pattern '\\([0-9]{3})\\' -List).Matches.Groups[1].Value
}
} |
Sort-Object -Property 'Version' -Descending |
Select-Object -First 1
if ($availableModule)
{
# This sets $availableModuleName to the Path of the module to be loaded.
$availableModuleName = Split-Path -Path $availableModule.Path -Parent
}
}
if ($availableModuleName)
{
try
{
Write-Debug -Message ($script:localizedData.PreferredModule_PushingLocation)
Push-Location
<#
SQLPS has unapproved verbs, disable checking to ignore Warnings.
Suppressing verbose so all cmdlet is not listed.
#>
$importedModule = Import-Module -Name $availableModuleName -DisableNameChecking -Verbose:$false -Force:$Force -Global -PassThru -ErrorAction 'Stop'
<#
SQLPS returns two entries, one with module type 'Script' and another with module type 'Manifest'.
Only return the object with module type 'Manifest'.
SqlServer only returns one object (of module type 'Script'), so no need to do anything for SqlServer module.
#>
if ($availableModuleName -ne $PreferredModule)
{
$importedModule = $importedModule | Where-Object -Property 'ModuleType' -EQ -Value 'Manifest'
}
Write-Verbose -Message ($script:localizedData.PreferredModule_ImportedModule -f $importedModule.Name, $importedModule.Version, $importedModule.Path)
}
finally
{
Write-Debug -Message ($script:localizedData.PreferredModule_PoppingLocation)
Pop-Location
}
}
else
{
$PSCmdlet.ThrowTerminatingError(
[System.Management.Automation.ErrorRecord]::new(
($script:localizedData.PreferredModule_FailedFinding -f $PreferredModule),
'ISDPM0001', # cspell: disable-line
[System.Management.Automation.ErrorCategory]::ObjectNotFound,
'PreferredModule'
)
)
}
}