Skip to content
Merged
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- `Invoke-ReportServerSetupAction`
- Now uses `Format-Path` with `-ExpandEnvironmentVariable` to expand environment
variables in all path parameters (`MediaPath`, `LogPath`, `InstallFolder`)
([issue #2085](https://github.com/dsccommunity/SqlServerDsc/issues/2085)).
- Added public command `Get-SqlDscServerProtocolTcpIp` to retrieve TCP/IP address
group information for SQL Server instances. Returns `ServerIPAddress` objects
containing port configuration including `TcpPort`, `TcpDynamicPorts`, `Enabled`,
Expand Down
24 changes: 21 additions & 3 deletions source/Private/Invoke-ReportServerSetupAction.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,26 @@ function Invoke-ReportServerSetupAction

$ErrorActionPreference = $previousErrorActionPreference

# Normalize paths: expand environment variables, ensure drive letter root, and remove trailing separators.
$formatPathParameters = @{
EnsureDriveLetterRoot = $true
NoTrailingDirectorySeparator = $true
ExpandEnvironmentVariable = $true
ErrorAction = 'Stop'
}

$MediaPath = Format-Path @formatPathParameters -Path $MediaPath

if ($PSBoundParameters.ContainsKey('LogPath'))
{
$LogPath = Format-Path @formatPathParameters -Path $LogPath
}

if ($PSBoundParameters.ContainsKey('InstallFolder'))
{
$InstallFolder = Format-Path @formatPathParameters -Path $InstallFolder
}

# Sensitive values.
$sensitiveValue = @()

Expand Down Expand Up @@ -318,10 +338,8 @@ function Invoke-ReportServerSetupAction

if ($PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage))
{
$expandedMediaPath = [System.Environment]::ExpandEnvironmentVariables($MediaPath)

$startProcessParameters = @{
FilePath = $expandedMediaPath
FilePath = $MediaPath
ArgumentList = $setupArgument
Timeout = $Timeout
}
Expand Down
128 changes: 128 additions & 0 deletions tests/Unit/Private/Invoke-ReportServerSetupAction.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,134 @@ Describe 'Invoke-ReportServerSetupAction' -Tag 'Private' {
}
}
}

Context 'When path parameters contain environment variables' {
BeforeAll {
# Mock Test-Path to return $true for all paths in this context
Mock -CommandName Test-Path -MockWith {
return $true
}

Mock -CommandName Start-SqlSetupProcess -MockWith {
return 0
} -RemoveParameterValidation 'FilePath'

Mock -CommandName Format-Path -MockWith {
# Return expanded path for testing
return 'C:\Logs\Test\setup.log'
} -ParameterFilter {
$Path -eq '%TEMP%\setup.log'
}

Mock -CommandName Format-Path -MockWith {
return 'C:\Program Files\ReportServer'
} -ParameterFilter {
$Path -eq '%ProgramFiles%\ReportServer'
}

Mock -CommandName Format-Path -MockWith {
return 'C:\SqlMedia\setup.exe'
} -ParameterFilter {
$Path -eq '%SystemDrive%\SqlMedia\setup.exe'
}

InModuleScope -ScriptBlock {
$script:mockDefaultParameters = @{
Install = $true
AcceptLicensingTerms = $true
MediaPath = '%SystemDrive%\SqlMedia\setup.exe'
Force = $true
}
}
}

It 'Should call Format-Path for MediaPath parameter' {
InModuleScope -ScriptBlock {
Invoke-ReportServerSetupAction @mockDefaultParameters

Should -Invoke -CommandName Format-Path -ParameterFilter {
$Path -eq '%SystemDrive%\SqlMedia\setup.exe' -and
$EnsureDriveLetterRoot -eq $true -and
$NoTrailingDirectorySeparator -eq $true -and
$ExpandEnvironmentVariable -eq $true
} -Exactly -Times 1 -Scope It
}
}

It 'Should call Format-Path for LogPath parameter when specified' {
InModuleScope -ScriptBlock {
$installParameters = $mockDefaultParameters.Clone()
$installParameters.LogPath = '%TEMP%\setup.log'

Invoke-ReportServerSetupAction @installParameters

Should -Invoke -CommandName Format-Path -ParameterFilter {
$Path -eq '%TEMP%\setup.log' -and
$EnsureDriveLetterRoot -eq $true -and
$NoTrailingDirectorySeparator -eq $true -and
$ExpandEnvironmentVariable -eq $true
} -Exactly -Times 1 -Scope It
}
}

It 'Should call Format-Path for InstallFolder parameter when specified' {
InModuleScope -ScriptBlock {
$installParameters = $mockDefaultParameters.Clone()
$installParameters.InstallFolder = '%ProgramFiles%\ReportServer'

Invoke-ReportServerSetupAction @installParameters

Should -Invoke -CommandName Format-Path -ParameterFilter {
$Path -eq '%ProgramFiles%\ReportServer' -and
$EnsureDriveLetterRoot -eq $true -and
$NoTrailingDirectorySeparator -eq $true -and
$ExpandEnvironmentVariable -eq $true
} -Exactly -Times 1 -Scope It
}
}

It 'Should pass the expanded path to Start-SqlSetupProcess for MediaPath' {
InModuleScope -ScriptBlock {
Invoke-ReportServerSetupAction @mockDefaultParameters

Should -Invoke -CommandName Start-SqlSetupProcess -ParameterFilter {
$FilePath -eq 'C:\SqlMedia\setup.exe'
} -Exactly -Times 1 -Scope It
}
}

It 'Should pass the expanded path in ArgumentList for LogPath' {
InModuleScope -ScriptBlock {
$installParameters = $mockDefaultParameters.Clone()
$installParameters.LogPath = '%TEMP%\setup.log'

Invoke-ReportServerSetupAction @installParameters

Should -Invoke -CommandName Start-SqlSetupProcess -ParameterFilter {
$ArgumentList | Should -MatchExactly '\/log "C:\\Logs\\Test\\setup\.log"'

# Return $true if none of the above throw.
$true
} -Exactly -Times 1 -Scope It
}
}

It 'Should pass the expanded path in ArgumentList for InstallFolder' {
InModuleScope -ScriptBlock {
$installParameters = $mockDefaultParameters.Clone()
$installParameters.InstallFolder = '%ProgramFiles%\ReportServer'

Invoke-ReportServerSetupAction @installParameters

Should -Invoke -CommandName Start-SqlSetupProcess -ParameterFilter {
$ArgumentList | Should -MatchExactly '\/InstallFolder="C:\\Program Files\\ReportServer"'

# Return $true if none of the above throw.
$true
} -Exactly -Times 1 -Scope It
}
}
}
}

Context 'When setup action is ''Uninstall''' {
Expand Down
Loading