Skip to content

Commit 36e0b3e

Browse files
authored
Get-SqlDscSetupLog: Retrieve SQL Server setup bootstrap log (#2314)
1 parent 5454f55 commit 36e0b3e

10 files changed

+507
-90
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
### Added
99

10+
- Added public command `Get-SqlDscSetupLog` to retrieve SQL Server setup bootstrap
11+
logs (Summary.txt) from the most recent setup operation. This command can be used
12+
interactively for troubleshooting or within integration tests to help diagnose
13+
setup failures. Integration tests have been updated to use this command instead
14+
of duplicated error handling code [issue #2311](https://github.com/dsccommunity/SqlServerDsc/issues/2311).
1015
- Added script `Remove-SqlServerFromCIImage.ps1` to remove pre-installed SQL Server
1116
components from Microsoft Hosted agents that conflict with PrepareImage operations.
1217
The script is now run automatically in the CI pipeline before PrepareImage tests

azure-pipelines.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ stages:
293293
# Group 2
294294
'tests/Integration/Commands/PostInstallationConfiguration.Integration.Tests.ps1'
295295
# Group 3
296+
'tests/Integration/Commands/Get-SqlDscSetupLog.Integration.Tests.ps1'
296297
'tests/Integration/Commands/Connect-SqlDscDatabaseEngine.Integration.Tests.ps1'
297298
'tests/Integration/Commands/Disconnect-SqlDscDatabaseEngine.Integration.Tests.ps1'
298299
'tests/Integration/Commands/Invoke-SqlDscQuery.Integration.Tests.ps1'
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<#
2+
.SYNOPSIS
3+
Get SQL Server setup bootstrap log.
4+
5+
.DESCRIPTION
6+
This command retrieves the SQL Server setup bootstrap log (Summary.txt)
7+
from the most recent setup operation. The log is typically located in
8+
the Setup Bootstrap\Log directory under the SQL Server installation path.
9+
10+
This command is useful for diagnosing SQL Server setup failures or
11+
understanding what occurred during the installation, upgrade, or rebuild
12+
operations.
13+
14+
.PARAMETER Path
15+
Specifies the root SQL Server installation path to search for the setup log
16+
file. Defaults to 'C:\Program Files\Microsoft SQL Server'.
17+
18+
.EXAMPLE
19+
Get-SqlDscSetupLog
20+
21+
Retrieves the most recent SQL Server setup log from the default location.
22+
23+
.EXAMPLE
24+
Get-SqlDscSetupLog -Path 'D:\SQLServer'
25+
26+
Retrieves the most recent SQL Server setup log from a custom installation path.
27+
28+
.EXAMPLE
29+
Get-SqlDscSetupLog -Verbose | Select-String -Pattern 'Error'
30+
31+
Retrieves the setup log and filters for lines containing 'Error'.
32+
33+
.INPUTS
34+
None. This command does not accept pipeline input.
35+
36+
.OUTPUTS
37+
`[System.String[]]`
38+
39+
Returns the content of the setup log file, or null if no log file is found.
40+
#>
41+
function Get-SqlDscSetupLog
42+
{
43+
[CmdletBinding()]
44+
[OutputType([System.String[]])]
45+
param
46+
(
47+
[Parameter()]
48+
[System.String]
49+
$Path = 'C:\Program Files\Microsoft SQL Server'
50+
)
51+
52+
$setupLogFileName = 'Summary.txt'
53+
54+
Write-Verbose -Message ($script:localizedData.Get_SqlDscSetupLog_SearchingForFile -f $setupLogFileName, $Path)
55+
56+
# Check if the path exists before attempting to search for files
57+
if (-not (Test-Path -Path $Path -PathType 'Container'))
58+
{
59+
$writeErrorParameters = @{
60+
Message = $script:localizedData.Get_SqlDscSetupLog_PathNotFound -f $Path
61+
Category = 'ObjectNotFound'
62+
ErrorId = 'GSDSL0006'
63+
TargetObject = $Path
64+
}
65+
66+
Write-Error @writeErrorParameters
67+
68+
return $null
69+
}
70+
71+
<#
72+
Find the most recent Summary.txt file from Setup Bootstrap\Log directories.
73+
Summary.txt is the standard SQL Server setup diagnostic log that records the outcome
74+
of installation, upgrade, or rebuild operations. Both the 'Summary.txt' filename and
75+
'Setup Bootstrap\Log' directory pattern are hardcoded as they are fixed SQL Server
76+
structures and should not be user-configurable. The -Path parameter allows users to
77+
specify the root search path for cases where SQL Server is installed in non-standard locations.
78+
#>
79+
$summaryFile = Get-ChildItem -Path $Path -Filter $setupLogFileName -Recurse -ErrorAction 'SilentlyContinue' |
80+
Where-Object -FilterScript { $_.FullName -match '\\Setup Bootstrap\\Log\\' } |
81+
Sort-Object -Property 'LastWriteTime' -Descending |
82+
Select-Object -First 1
83+
84+
$output = @()
85+
86+
if ($summaryFile)
87+
{
88+
Write-Verbose -Message ($script:localizedData.Get_SqlDscSetupLog_FileFound -f $summaryFile.FullName)
89+
90+
$output += $script:localizedData.Get_SqlDscSetupLog_Header -f $setupLogFileName, $summaryFile.FullName
91+
$output += Get-Content -Path $summaryFile.FullName
92+
$output += $script:localizedData.Get_SqlDscSetupLog_Footer -f $setupLogFileName
93+
94+
return $output
95+
}
96+
else
97+
{
98+
Write-Verbose -Message ($script:localizedData.Get_SqlDscSetupLog_FileNotFound -f $setupLogFileName)
99+
100+
return $null
101+
}
102+
}

source/en-US/SqlServerDsc.strings.psd1

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,4 +526,12 @@ ConvertFrom-StringData @'
526526
527527
## ConvertTo-FormattedParameterDescription
528528
ConvertTo_FormattedParameterDescription_NoParametersToUpdate = (no parameters to update)
529+
530+
## Get-SqlDscSetupLog
531+
Get_SqlDscSetupLog_SearchingForFile = Searching for '{0}' in path '{1}'. (GSDSL0001)
532+
Get_SqlDscSetupLog_FileFound = Found setup log file at '{0}'. (GSDSL0002)
533+
Get_SqlDscSetupLog_FileNotFound = Setup log file '{0}' not found. (GSDSL0003)
534+
Get_SqlDscSetupLog_Header = ==== SQL Server Setup {0} (from {1}) ==== (GSDSL0004)
535+
Get_SqlDscSetupLog_Footer = ==== End of {0} ==== (GSDSL0005)
536+
Get_SqlDscSetupLog_PathNotFound = Path '{0}' does not exist. (GSDSL0006)
529537
'@

tests/Integration/Commands/Complete-SqlDscImage.Integration.Tests.ps1

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,7 @@ Describe 'Complete-SqlDscImage' -Tag @('Integration_SQL2017', 'Integration_SQL20
7878
catch
7979
{
8080
# Output Summary.txt if it exists to help diagnose the failure
81-
$summaryFiles = Get-ChildItem -Path 'C:\Program Files\Microsoft SQL Server' -Filter 'Summary.txt' -Recurse -ErrorAction SilentlyContinue |
82-
Where-Object { $_.FullName -match '\\Setup Bootstrap\\Log\\' } |
83-
Sort-Object -Property LastWriteTime -Descending |
84-
Select-Object -First 1
85-
86-
if ($summaryFiles)
87-
{
88-
Write-Verbose "==== SQL Server Setup Summary.txt (from $($summaryFiles.FullName)) ====" -Verbose
89-
Get-Content -Path $summaryFiles.FullName | Write-Verbose -Verbose
90-
Write-Verbose "==== End of Summary.txt ====" -Verbose
91-
}
92-
else
93-
{
94-
Write-Verbose 'No Summary.txt file found.' -Verbose
95-
}
81+
Get-SqlDscSetupLog -Verbose | Write-Verbose -Verbose
9682

9783
# Re-throw the original error
9884
throw $_
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')]
2+
param ()
3+
4+
BeforeDiscovery {
5+
try
6+
{
7+
if (-not (Get-Module -Name 'DscResource.Test'))
8+
{
9+
# Assumes dependencies have been resolved, so if this module is not available, run 'noop' task.
10+
if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable))
11+
{
12+
# Redirect all streams to $null, except the error stream (stream 2)
13+
& "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
14+
}
15+
16+
# If the dependencies have not been resolved, this will throw an error.
17+
Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop'
18+
}
19+
}
20+
catch [System.IO.FileNotFoundException]
21+
{
22+
throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.'
23+
}
24+
}
25+
26+
BeforeAll {
27+
$script:moduleName = 'SqlServerDsc'
28+
29+
Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop'
30+
}
31+
32+
Describe 'Get-SqlDscSetupLog' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') {
33+
Context 'When retrieving SQL Server setup log' {
34+
It 'Should retrieve the setup log from the most recent installation' {
35+
# This test verifies that Get-SqlDscSetupLog can successfully retrieve the
36+
# SQL Server setup log (Summary.txt) from the CI test instance installation
37+
# Using ErrorAction Stop to ensure the command does not throw on valid path
38+
$setupLog = Get-SqlDscSetupLog -ErrorAction 'Stop'
39+
40+
# The log should not be null if SQL Server is installed
41+
$setupLog | Should -Not -BeNullOrEmpty
42+
43+
# Each line in the log should be a string
44+
$setupLog | Should -BeOfType ([System.String])
45+
46+
# The log content should contain typical SQL Server setup log information
47+
# We check for common patterns that appear in Summary.txt
48+
$logContent = $setupLog -join "`n"
49+
$logContent | Should -Match '(Setup completed|Installation|SQL Server|Feature)'
50+
51+
Write-Verbose -Message "Retrieved setup log with $($setupLog.Count) lines" -Verbose
52+
}
53+
54+
It 'Should throw when setup log path does not exist' {
55+
# Test that the command throws a terminating error for non-existent paths
56+
# when using ErrorAction Stop
57+
{
58+
Get-SqlDscSetupLog -Path 'C:\NonExistentPath' -ErrorAction 'Stop'
59+
} | Should -Throw
60+
}
61+
62+
It 'Should support custom Path parameter' {
63+
# Test that a custom path parameter works
64+
# Using ErrorAction Stop to ensure the command does not throw on valid path
65+
$result = Get-SqlDscSetupLog -Path 'C:\Program Files\Microsoft SQL Server' -ErrorAction 'Stop'
66+
67+
# Using the standard path should return results
68+
$result | Should -Not -BeNullOrEmpty
69+
}
70+
71+
It 'Should include header and footer in the output' {
72+
# Verify that the output includes the formatted header and footer
73+
# that Get-SqlDscSetupLog adds to the raw log content
74+
# Using ErrorAction Stop to ensure the command does not throw on valid path
75+
$setupLog = Get-SqlDscSetupLog -ErrorAction 'Stop'
76+
77+
$setupLog | Should -Not -BeNullOrEmpty
78+
79+
# The command adds a header line and footer line to the output
80+
# Verify the output contains multiple lines (header + content + footer)
81+
$setupLog.Count | Should -BeGreaterThan 2
82+
83+
# The first line should be a header containing "Summary.txt"
84+
$setupLog[0] | Should -Match 'Summary\.txt'
85+
86+
# The last line should be a footer
87+
$setupLog[-1] | Should -Match 'Summary\.txt'
88+
}
89+
}
90+
}

tests/Integration/Commands/Initialize-SqlDscRebuildDatabase.Integration.Tests.ps1

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,7 @@ Describe 'Initialize-SqlDscRebuildDatabase' -Tag @('Integration_SQL2017', 'Integ
9999
catch
100100
{
101101
# Output Summary.txt if it exists to help diagnose the failure
102-
$summaryFiles = Get-ChildItem -Path 'C:\Program Files\Microsoft SQL Server' -Filter 'Summary.txt' -Recurse -ErrorAction SilentlyContinue |
103-
Where-Object { $_.FullName -match '\\Setup Bootstrap\\Log\\' } |
104-
Sort-Object -Property LastWriteTime -Descending |
105-
Select-Object -First 1
106-
107-
if ($summaryFiles)
108-
{
109-
Write-Verbose "==== SQL Server Setup Summary.txt (from $($summaryFiles.FullName)) ====" -Verbose
110-
Get-Content -Path $summaryFiles.FullName | Write-Verbose -Verbose
111-
Write-Verbose "==== End of Summary.txt ====" -Verbose
112-
}
113-
else
114-
{
115-
Write-Verbose 'No Summary.txt file found.' -Verbose
116-
}
102+
Get-SqlDscSetupLog -Verbose | Write-Verbose -Verbose
117103

118104
# Re-throw the original error
119105
throw $_
@@ -173,21 +159,7 @@ Describe 'Initialize-SqlDscRebuildDatabase' -Tag @('Integration_SQL2017', 'Integ
173159
catch
174160
{
175161
# Output Summary.txt if it exists to help diagnose the failure
176-
$summaryFiles = Get-ChildItem -Path 'C:\Program Files\Microsoft SQL Server' -Filter 'Summary.txt' -Recurse -ErrorAction SilentlyContinue |
177-
Where-Object { $_.FullName -match '\\Setup Bootstrap\\Log\\' } |
178-
Sort-Object -Property LastWriteTime -Descending |
179-
Select-Object -First 1
180-
181-
if ($summaryFiles)
182-
{
183-
Write-Verbose "==== SQL Server Setup Summary.txt (from $($summaryFiles.FullName)) ====" -Verbose
184-
Get-Content -Path $summaryFiles.FullName | Write-Verbose -Verbose
185-
Write-Verbose "==== End of Summary.txt ====" -Verbose
186-
}
187-
else
188-
{
189-
Write-Verbose 'No Summary.txt file found.' -Verbose
190-
}
162+
Get-SqlDscSetupLog -Verbose | Write-Verbose -Verbose
191163

192164
# Re-throw the original error
193165
throw $_
@@ -243,21 +215,7 @@ Describe 'Initialize-SqlDscRebuildDatabase' -Tag @('Integration_SQL2017', 'Integ
243215
catch
244216
{
245217
# Output Summary.txt if it exists to help diagnose the failure
246-
$summaryFiles = Get-ChildItem -Path 'C:\Program Files\Microsoft SQL Server' -Filter 'Summary.txt' -Recurse -ErrorAction SilentlyContinue |
247-
Where-Object { $_.FullName -match '\\Setup Bootstrap\\Log\\' } |
248-
Sort-Object -Property LastWriteTime -Descending |
249-
Select-Object -First 1
250-
251-
if ($summaryFiles)
252-
{
253-
Write-Verbose "==== SQL Server Setup Summary.txt (from $($summaryFiles.FullName)) ====" -Verbose
254-
Get-Content -Path $summaryFiles.FullName | Write-Verbose -Verbose
255-
Write-Verbose "==== End of Summary.txt ====" -Verbose
256-
}
257-
else
258-
{
259-
Write-Verbose 'No Summary.txt file found.' -Verbose
260-
}
218+
Get-SqlDscSetupLog -Verbose | Write-Verbose -Verbose
261219

262220
# Re-throw the original error
263221
throw $_

tests/Integration/Commands/Install-SqlDscServer.Integration.PrepareImage.Tests.ps1

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,7 @@ Describe 'Install-SqlDscServer - PrepareImage' -Tag @('Integration_SQL2017', 'In
6060
catch
6161
{
6262
# Output Summary.txt if it exists to help diagnose the failure
63-
$summaryFiles = Get-ChildItem -Path 'C:\Program Files\Microsoft SQL Server' -Filter 'Summary.txt' -Recurse -ErrorAction SilentlyContinue |
64-
Where-Object { $_.FullName -match '\\Setup Bootstrap\\Log\\' } |
65-
Sort-Object -Property LastWriteTime -Descending |
66-
Select-Object -First 1
67-
68-
if ($summaryFiles)
69-
{
70-
Write-Verbose "==== SQL Server Setup Summary.txt (from $($summaryFiles.FullName)) ====" -Verbose
71-
Get-Content -Path $summaryFiles.FullName | Write-Verbose -Verbose
72-
Write-Verbose "==== End of Summary.txt ====" -Verbose
73-
}
74-
else
75-
{
76-
Write-Verbose 'No Summary.txt file found.' -Verbose
77-
}
63+
Get-SqlDscSetupLog -Verbose | Write-Verbose -Verbose
7864

7965
# Re-throw the original error
8066
throw $_

tests/Integration/Commands/Repair-SqlDscServer.Integration.Tests.ps1

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -157,21 +157,7 @@ Describe 'Repair-SqlDscServer' -Tag @('Integration_SQL2017', 'Integration_SQL201
157157
catch
158158
{
159159
# Output Summary.txt if it exists to help diagnose the failure
160-
$summaryFiles = Get-ChildItem -Path 'C:\Program Files\Microsoft SQL Server' -Filter 'Summary.txt' -Recurse -ErrorAction SilentlyContinue |
161-
Where-Object { $_.FullName -match '\\Setup Bootstrap\\Log\\' } |
162-
Sort-Object -Property LastWriteTime -Descending |
163-
Select-Object -First 1
164-
165-
if ($summaryFiles)
166-
{
167-
Write-Verbose "==== SQL Server Setup Summary.txt (from $($summaryFiles.FullName)) ====" -Verbose
168-
Get-Content -Path $summaryFiles.FullName | Write-Verbose -Verbose
169-
Write-Verbose "==== End of Summary.txt ====" -Verbose
170-
}
171-
else
172-
{
173-
Write-Verbose 'No Summary.txt file found.' -Verbose
174-
}
160+
Get-SqlDscSetupLog -Verbose | Write-Verbose -Verbose
175161

176162
# Check if this is the known LocalDB MSI missing issue
177163
if ($_.Exception.Message -match 'SqlLocalDB\.msi')

0 commit comments

Comments
 (0)