Skip to content

Commit 80080b3

Browse files
Move SqlPackage & XESmartTarget from bundled to installer-based dependencies (#9776)
1 parent af93ec6 commit 80080b3

19 files changed

+1309
-29
lines changed

.github/workflows/integration-tests.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ jobs:
8484
run: |
8585
gh repo clone dataplat/appveyor-lab
8686
87+
- name: Install SqlPackage for DAC tests
88+
run: |
89+
Import-Module ./dbatools.psd1 -Force
90+
Install-DbaSqlPackage -Verbose
91+
92+
- name: Install XESmartTarget for Extended Events tests
93+
run: |
94+
Import-Module ./dbatools.psd1 -Force
95+
Install-DbaXESmartTarget -Force
96+
8797
- name: Run tests
8898
env:
8999
TENANTID: ${{secrets.TENANTID}}
@@ -162,6 +172,18 @@ jobs:
162172
$PSDefaultParameterValues["*:SqlCredential"] = $cred
163173
Connect-DbaInstance
164174
175+
- name: Install SqlPackage for DAC tests (PowerShell)
176+
shell: powershell
177+
run: |
178+
Import-Module ./dbatools -Force
179+
Install-DbaSqlPackage -Verbose
180+
181+
- name: Install XESmartTarget for Extended Events tests (PowerShell)
182+
shell: powershell
183+
run: |
184+
Import-Module ./dbatools -Force
185+
Install-DbaXESmartTarget -Force
186+
165187
- name: Run PowerShell tests
166188
env:
167189
TENANTID: ${{secrets.TENANTID}}
@@ -170,6 +192,18 @@ jobs:
170192
shell: powershell
171193
run: $null = Invoke-Pester .github/scripts/gh-winactions.ps1 -Output Detailed -PassThru
172194

195+
- name: Install SqlPackage for DAC tests (pwsh)
196+
shell: pwsh
197+
run: |
198+
Import-Module ./dbatools -Force
199+
Install-DbaSqlPackage -Verbose
200+
201+
- name: Install XESmartTarget for Extended Events tests (pwsh)
202+
shell: pwsh
203+
run: |
204+
Import-Module ./dbatools -Force
205+
Install-DbaXESmartTarget -Force
206+
173207
- name: Run pwsh tests
174208
env:
175209
TENANTID: ${{secrets.TENANTID}}

dbatools.psd1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,10 @@
423423
'Install-DbaInstance',
424424
'Install-DbaMaintenanceSolution',
425425
'Install-DbaMultiTool',
426+
'Install-DbaSqlPackage',
426427
'Install-DbaSqlWatch',
427428
'Install-DbaWhoIsActive',
429+
'Install-DbaXESmartTarget',
428430
'Invoke-DbaDbAzSqlTip',
429431
'Invoke-DbaAdvancedInstall',
430432
'Invoke-DbaAdvancedRestore',

dbatools.psm1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,9 @@ if ($PSVersionTable.PSVersion.Major -lt 5) {
808808
'Get-DbaBuild',
809809
'Update-DbaBuildReference',
810810
'Install-DbaFirstResponderKit',
811+
'Install-DbaSqlPackage',
811812
'Install-DbaWhoIsActive',
813+
'Install-DbaXESmartTarget',
812814
'Update-Dbatools',
813815
'Add-DbaServerRoleMember',
814816
'Get-DbatoolsPath',
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
function Get-DbaSqlPackagePath {
2+
<#
3+
.SYNOPSIS
4+
Gets the path to SqlPackage.exe, checking installed versions and bundled versions.
5+
6+
.DESCRIPTION
7+
This function implements the logic to find SqlPackage.exe by:
8+
1. First checking if SqlPackage is available via Get-Command (system PATH)
9+
2. Then checking the dbatools data directory (installed via Install-DbaSqlPackage)
10+
3. Then checking the bundled version in the dbatools library
11+
4. If not found, suggesting to use Install-DbaSqlPackage to install it
12+
13+
.PARAMETER EnableException
14+
By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.
15+
This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting.
16+
Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch.
17+
18+
.NOTES
19+
Tags: SqlPackage, DacPac, Deployment
20+
Author: dbatools team
21+
22+
Website: https://dbatools.io
23+
Copyright: (c) 2018 by dbatools, licensed under MIT
24+
License: MIT https://opensource.org/licenses/MIT
25+
26+
.OUTPUTS
27+
System.String. The path to SqlPackage.exe if found, otherwise $null.
28+
#>
29+
[CmdletBinding()]
30+
param (
31+
[switch]$EnableException
32+
)
33+
34+
# Determine executable name based on platform
35+
if ($PSVersionTable.Platform -eq "Unix") {
36+
$executableName = "sqlpackage"
37+
} else {
38+
$executableName = "SqlPackage"
39+
}
40+
41+
# First try to find SqlPackage using Get-Command (system PATH)
42+
try {
43+
$sqlPackageCommand = Get-Command -Name $executableName -ErrorAction SilentlyContinue
44+
if ($sqlPackageCommand) {
45+
Write-Message -Level Verbose -Message "Found $executableName in system PATH at: $($sqlPackageCommand.Source)"
46+
return $sqlPackageCommand.Source
47+
}
48+
} catch {
49+
Write-Message -Level Verbose -Message "Error checking for system-installed SqlPackage: $($_.Exception.Message)"
50+
}
51+
52+
# Second, try the dbatools data directory (installed via Install-DbaSqlPackage)
53+
$dbatoolsData = Get-DbatoolsConfigValue -FullName "Path.DbatoolsData"
54+
# Normalize path to remove any trailing slashes before joining
55+
$dbatoolsData = $dbatoolsData.TrimEnd('/', '\')
56+
57+
if ($PSVersionTable.Platform -eq "Unix") {
58+
$installedExe = Join-Path -Path $dbatoolsData -ChildPath "sqlpackage" | Join-Path -ChildPath "sqlpackage"
59+
} else {
60+
$installedExe = Join-Path -Path $dbatoolsData -ChildPath "sqlpackage" | Join-Path -ChildPath "SqlPackage.exe"
61+
}
62+
63+
if (Test-Path -Path $installedExe) {
64+
Write-Message -Level Verbose -Message "Found $executableName in dbatools data directory at: $installedExe"
65+
return $installedExe
66+
}
67+
68+
# Third, try the bundled version (legacy path for backwards compatibility)
69+
if ($PSVersionTable.Platform -eq "Unix") {
70+
$bundledExe = Join-Path -Path $script:PSModuleRoot -ChildPath "bin" | Join-Path -ChildPath "sqlpackage" | Join-Path -ChildPath "sqlpackage"
71+
} else {
72+
$bundledExe = Join-Path -Path $script:PSModuleRoot -ChildPath "bin" | Join-Path -ChildPath "sqlpackage" | Join-Path -ChildPath "SqlPackage.exe"
73+
}
74+
75+
if (Test-Path -Path $bundledExe) {
76+
Write-Message -Level Verbose -Message "Found bundled $executableName at: $bundledExe"
77+
return $bundledExe
78+
}
79+
80+
# Fourth, check common installation paths (platform-specific)
81+
if ($PSVersionTable.Platform -eq "Unix") {
82+
$commonPaths = @(
83+
"/usr/local/sqlpackage/sqlpackage",
84+
"/opt/sqlpackage/sqlpackage"
85+
)
86+
} else {
87+
$commonPaths = @(
88+
"${env:ProgramFiles}\Microsoft SQL Server\*\DAC\bin\SqlPackage.exe",
89+
"${env:ProgramFiles(x86)}\Microsoft SQL Server\*\DAC\bin\SqlPackage.exe"
90+
)
91+
}
92+
93+
foreach ($pathPattern in $commonPaths) {
94+
if ($pathPattern -like "*\**") {
95+
# Handle wildcard patterns (Windows only)
96+
$foundPaths = Get-ChildItem -Path $pathPattern -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending
97+
if ($foundPaths) {
98+
$newestPath = $foundPaths[0].FullName
99+
Write-Message -Level Verbose -Message "Found system-installed $executableName at: $newestPath"
100+
return $newestPath
101+
}
102+
} else {
103+
# Handle direct paths (Unix)
104+
if (Test-Path -Path $pathPattern) {
105+
Write-Message -Level Verbose -Message "Found system-installed $executableName at: $pathPattern"
106+
return $pathPattern
107+
}
108+
}
109+
}
110+
111+
# If we get here, SqlPackage was not found
112+
$message = @"
113+
Could not find SqlPackage. SqlPackage is required for DAC operations.
114+
115+
To install SqlPackage, use:
116+
Install-DbaSqlPackage
117+
118+
This will download and install SqlPackage to your dbatools data directory, making it available for use with dbatools DAC commands.
119+
"@
120+
121+
if ($EnableException) {
122+
Stop-Function -Message $message -Target "SqlPackage"
123+
throw "SqlPackage not found"
124+
} else {
125+
Stop-Function -Message $message -Target "SqlPackage"
126+
return $null
127+
}
128+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
function Get-XESmartTargetPath {
2+
<#
3+
.SYNOPSIS
4+
Gets the path to XESmartTarget.Core.dll, checking installed versions and bundled legacy versions.
5+
6+
.DESCRIPTION
7+
This function implements the logic to find XESmartTarget.Core.dll by:
8+
1. First checking the dbatools data directory (installed via Install-DbaXESmartTarget)
9+
2. Then checking the bundled version in the dbatools library (legacy)
10+
3. If not found, checking if XESmartTarget is installed via Get-Command
11+
4. If found, looking for the DLL in the same directory as the executable
12+
5. If not found, suggesting to use Install-DbaXESmartTarget to install it
13+
14+
.PARAMETER EnableException
15+
By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.
16+
This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting.
17+
Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch.
18+
19+
.NOTES
20+
Tags: ExtendedEvent, XE, XEvent, SmartTarget
21+
Author: dbatools team
22+
23+
Website: https://dbatools.io
24+
Copyright: (c) 2018 by dbatools, licensed under MIT
25+
License: MIT https://opensource.org/licenses/MIT
26+
27+
.OUTPUTS
28+
System.String. The path to XESmartTarget.Core.dll if found, otherwise $null.
29+
#>
30+
[CmdletBinding()]
31+
param (
32+
[switch]$EnableException
33+
)
34+
35+
# First try the dbatools data directory (installed via Install-DbaXESmartTarget)
36+
$dbatoolsData = Get-DbatoolsConfigValue -FullName "Path.DbatoolsData"
37+
$installedDll = Join-DbaPath -Path $dbatoolsData -ChildPath "XESmartTarget", "XESmartTarget.Core.dll"
38+
if (Test-Path -Path $installedDll) {
39+
Write-Message -Level Verbose -Message "Found XESmartTarget.Core.dll in dbatools data directory at: $installedDll"
40+
return $installedDll
41+
}
42+
43+
# Second, try the bundled version (legacy path for backwards compatibility)
44+
$bundledDll = Join-DbaPath -Path $script:libraryroot -ChildPath "third-party", "XESmartTarget", "XESmartTarget.Core.dll"
45+
if (Test-Path -Path $bundledDll) {
46+
Write-Message -Level Verbose -Message "Found bundled XESmartTarget.Core.dll at: $bundledDll"
47+
return $bundledDll
48+
}
49+
50+
# Third, check if XESmartTarget is installed system-wide via Get-Command
51+
try {
52+
$xeCommand = Get-Command -Name "XESmartTarget" -ErrorAction SilentlyContinue
53+
if ($xeCommand) {
54+
# Get the directory where the executable is located
55+
$xeDirectory = Split-Path -Parent $xeCommand.Source
56+
$systemInstalledDll = Join-Path -Path $xeDirectory -ChildPath "XESmartTarget.Core.dll"
57+
58+
if (Test-Path -Path $systemInstalledDll) {
59+
Write-Message -Level Verbose -Message "Found system-installed XESmartTarget.Core.dll at: $systemInstalledDll"
60+
return $systemInstalledDll
61+
} else {
62+
Write-Message -Level Warning -Message "Found XESmartTarget executable at '$($xeCommand.Source)' but could not find XESmartTarget.Core.dll in the same directory."
63+
}
64+
}
65+
} catch {
66+
Write-Message -Level Verbose -Message "Error checking for system-installed XESmartTarget: $($_.Exception.Message)"
67+
}
68+
69+
# If we get here, XESmartTarget.Core.dll was not found
70+
$message = @"
71+
Could not find XESmartTarget.Core.dll. XESmartTarget is no longer bundled with dbatools.
72+
73+
To install XESmartTarget, use:
74+
Install-DbaXESmartTarget
75+
76+
This will download and install XESmartTarget to your dbatools data directory, making it available for use with dbatools XE commands.
77+
"@
78+
79+
if ($EnableException) {
80+
Stop-Function -Message $message -Target "XESmartTarget"
81+
throw "XESmartTarget.Core.dll not found"
82+
} else {
83+
Stop-Function -Message $message -Target "XESmartTarget"
84+
return $null
85+
}
86+
}

public/Export-DbaDacPackage.ps1

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,29 @@ function Export-DbaDacPackage {
116116
)
117117
begin {
118118
$null = Test-ExportDirectory -Path $Path
119+
120+
# Check if sqlpackage is available
121+
$sqlPackagePath = Get-DbaSqlPackagePath
122+
if (-not $sqlPackagePath) {
123+
$installChoice = Read-Host "SqlPackage is required but not found. Would you like to install it now using Install-DbaSqlPackage? (Y/N)"
124+
if ($installChoice -match '^[Yy]') {
125+
try {
126+
Install-DbaSqlPackage
127+
Write-Message -Level Output -Message "SqlPackage installed successfully. Continuing with export..."
128+
$sqlPackagePath = Get-DbaSqlPackagePath
129+
if (-not $sqlPackagePath) {
130+
Stop-Function -Message "Failed to locate SqlPackage after installation. Please verify the installation." -EnableException:$EnableException
131+
return
132+
}
133+
} catch {
134+
Stop-Function -Message "Failed to install SqlPackage. Please install manually or use Install-DbaSqlPackage." -EnableException:$EnableException
135+
return
136+
}
137+
} else {
138+
Stop-Function -Message "SqlPackage is required for this operation. Please install SqlPackage manually or use Install-DbaSqlPackage." -EnableException:$EnableException
139+
return
140+
}
141+
}
119142
}
120143
process {
121144
if (Test-FunctionInterrupt) { return }
@@ -241,23 +264,11 @@ function Export-DbaDacPackage {
241264
try {
242265
$startprocess = New-Object System.Diagnostics.ProcessStartInfo
243266

244-
$sqlpackage = (Get-Command sqlpackage -ErrorAction Ignore).Source
267+
$sqlpackage = Get-DbaSqlPackagePath
245268
if ($sqlpackage) {
246269
$startprocess.FileName = $sqlpackage
247270
} else {
248-
if ($IsLinux) {
249-
$startprocess.FileName = "$(Get-DbatoolsLibraryPath)/lib/dac/linux/sqlpackage"
250-
} elseif ($IsMacOS) {
251-
$startprocess.FileName = "$(Get-DbatoolsLibraryPath)/lib/dac/mac/sqlpackage"
252-
} else {
253-
# if core then get the parent of lib path and then use the desktop location
254-
if ($PsVersionTable.PSEdition -eq 'Core') {
255-
$startprocess.FileName = "$(Get-DbatoolsLibraryPath)/lib/dac/windows/sqlpackage.exe"
256-
} else {
257-
# otherwise use the lib path
258-
$startprocess.FileName = "$(Get-DbatoolsLibraryPath)\lib\dac\SqlPackage.exe"
259-
}
260-
}
271+
Stop-Function -Message "SqlPackage not found. Please install SqlPackage using Install-DbaSqlPackage or ensure it's available in PATH." -Continue
261272
}
262273
$startprocess.Arguments = $sqlPackageArgs
263274
$startprocess.RedirectStandardError = $true

public/Export-DbaXECsv.ps1

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,14 @@ function Export-DbaXECsv {
5454
)
5555
begin {
5656
$null = Test-ExportDirectory -Path $Path
57+
$xedll = Get-XESmartTargetPath -EnableException:$EnableException
58+
if (-not $xedll) {
59+
return
60+
}
5761
try {
58-
$xedll = Join-DbaPath -Path $script:libraryroot -ChildPath lib, third-party, XESmartTarget, XESmartTarget.Core.dll
5962
Add-Type -Path $xedll -ErrorAction Stop
6063
} catch {
61-
Stop-Function -Message "Could not load XESmartTarget.Core.dll" -ErrorRecord $_ -Target "XESmartTarget"
64+
Stop-Function -Message "Could not load XESmartTarget.Core.dll from: $xedll" -ErrorRecord $_ -Target "XESmartTarget"
6265
return
6366
}
6467

0 commit comments

Comments
 (0)