Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d818f58
Add functions to manage report server database creation and permissions
johlju Jan 3, 2026
b9a3a66
Add System.ComponentModel.TypeConverter to referenced assemblies in S…
johlju Jan 3, 2026
7204a62
Fix comment-based help formatting and enhance QA tests for example co…
johlju Jan 3, 2026
a62b1a9
Fix comment-based help formatting by removing blank lines in example …
johlju Jan 3, 2026
ab8d82c
Fix comment-based help formatting by removing blank lines in example …
johlju Jan 3, 2026
ab908e1
Fix Reporting Services integration test tags and update README for cl…
johlju Jan 3, 2026
2b06005
Fix error handling in Invoke-RsCimMethod to provide descriptive fallb…
johlju Jan 3, 2026
d5f56cf
Fix error handling in Set-SqlDscRSDatabaseConnection by adding -Error…
johlju Jan 4, 2026
8a4938c
Refactor comment-based help structure tests by removing unused variab…
johlju Jan 4, 2026
c4fe9bf
Merge branch 'main' into f/issue-#2021
johlju Jan 4, 2026
6173d16
Add Get-HResultMessage function for translating HRESULT codes and enh…
johlju Jan 4, 2026
a077d47
Add Import-SqlDscPreferredModule to ensure SMO types are loaded in in…
johlju Jan 4, 2026
ed17306
Add "HRESULT" to cSpell words list for improved spell checking
johlju Jan 4, 2026
2cff608
Add notes to Get-HResultMessage function regarding error message reli…
johlju Jan 4, 2026
008e0fb
Enhance Request-SqlDscRSDatabaseScript to check if Reporting Services…
johlju Jan 4, 2026
3aa8e07
Refactor Request-SqlDscRSDatabaseRightsScript and related tests to re…
johlju Jan 4, 2026
a999afc
Refactor tests for Set-SqlDscRSDatabaseConnection to simplify asserti…
johlju Jan 4, 2026
4ce933b
Merge branch 'main' into f/issue-#2021
johlju Jan 4, 2026
a52e4f5
Refactor Set-TargetResource to use public commands for database scrip…
johlju Jan 4, 2026
3c854db
Enhance SqlRS tests by adding WindowsServiceIdentityActual property a…
johlju Jan 5, 2026
c8fbb1b
Update WindowsServiceIdentityActual property in Set-TargetResource te…
johlju Jan 5, 2026
695f3a0
Merge branch 'main' into f/issue-#2021
johlju Jan 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@
"varchar",
"maxdop",
"hotfixes",
"checkpointing"
"checkpointing",
"HRESULT"
],
"cSpell.ignorePaths": [
".git"
Expand Down
81 changes: 78 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added public command `Request-SqlDscRSDatabaseScript` to generate T-SQL scripts
for creating report server databases. Wraps the `GenerateDatabaseCreationScript`
CIM method and supports configuring database name, language (LCID), and
SharePoint mode ([issue #2017](https://github.com/dsccommunity/SqlServerDsc/issues/2017)).
- Added public command `Request-SqlDscRSDatabaseRightsScript` to generate T-SQL
scripts for granting permissions on report server databases. Wraps the
`GenerateDatabaseRightsScript` CIM method and supports configuring database
name, user name, remote connections, and Windows/SQL authentication types
([issue #2019](https://github.com/dsccommunity/SqlServerDsc/issues/2019)).
- Added public command `Set-SqlDscRSDatabaseConnection` to set
the report server database connection for SQL Server Reporting Services or
Power BI Report Server. Wraps the `SetDatabaseConnection` CIM method and
supports Windows, SQL Server, and Service Account authentication types
([issue #2021](https://github.com/dsccommunity/SqlServerDsc/issues/2021)).
- Added public command `Set-SqlDscRSVirtualDirectory` to set the virtual directory
for Reporting Services applications. Wraps the `SetVirtualDirectory` CIM method
and supports ReportServerWebService, ReportServerWebApp, and ReportManager
Expand Down Expand Up @@ -47,6 +61,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Services configuration instances with consistent error handling. This function
is used by `Enable-SqlDscRsSecureConnection`, `Disable-SqlDscRsSecureConnection`,
and the `SqlRS` resource.
- Added private function `Get-HResultMessage` to translate common Windows HRESULT
error codes into human-readable messages. Used by `Invoke-RsCimMethod` to
provide actionable error messages when Reporting Services CIM methods fail
without detailed error information.
- `Invoke-ReportServerSetupAction`
- Now uses `Format-Path` with `-ExpandEnvironmentVariable` to expand environment
variables in all path parameters (`MediaPath`, `LogPath`, `InstallFolder`)
Expand Down Expand Up @@ -185,6 +203,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Refactored to use the public command `Set-SqlDscRSVirtualDirectory` for
setting virtual directories instead of calling the CIM method directly
([issue #2015](https://github.com/dsccommunity/SqlServerDsc/issues/2015)).
- Refactored to use the public commands `Request-SqlDscRSDatabaseScript`,
`Request-SqlDscRSDatabaseRightsScript`, and `Set-SqlDscRSDatabaseConnection`
for creating and configuring the report server database instead of calling
the CIM methods directly
([issue #2017](https://github.com/dsccommunity/SqlServerDsc/issues/2017))
([issue #2019](https://github.com/dsccommunity/SqlServerDsc/issues/2019))
([issue #2021](https://github.com/dsccommunity/SqlServerDsc/issues/2021)).
- `Assert-SetupActionProperties`
- Refactored to use the command `Get-FileVersion` from the DscResource.Common
module instead of the private function `Get-FileVersionInformation`
Expand All @@ -201,6 +226,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- `Invoke-RsCimMethod`
- Enhanced error messages to include human-readable translations of common
HRESULT error codes. When Reporting Services CIM methods fail without
detailed error information, the error message now includes actionable
guidance based on the HRESULT code (e.g., service not running, access
denied, logon type not granted).
- Fixed error handling to properly surface error details. Previously, when
the `ExtendedErrors` property existed but was empty, the error message
would show an empty error description. Now it correctly falls back to
the `Error` property and provides a descriptive fallback message if
neither property contains error details.
- Prerequisites Integration Tests
- Fixed missing RS (Reporting Services) integration test tags on Context blocks
that create local Windows users, service accounts, and groups. Added tags
`Integration_SQL2017_RS`, `Integration_SQL2019_RS`, and `Integration_SQL2022_RS`
to ensure these prerequisites run before Reporting Services integration tests.
- `New-SqlDscFileGroup`
- Fixed comment-based help example formatting by moving inline comment
to the description text.
- QA Tests
- Added new test to detect comments within multi-line example code blocks
in comment-based help. Comments in the code portion of `.EXAMPLE` blocks
cause PlatyPS documentation generation to fail with "Expect Heading" errors.
- Added new test to detect blank lines within multi-line example code blocks
in comment-based help. Blank lines within the code portion of `.EXAMPLE`
blocks cause similar issues with documentation generation.
- `Deny-SqlDscServerPermission`
- Fixed comment-based help example formatting by removing blank lines
within code blocks that would cause documentation generation issues.
- `Get-SqlDscServerPermission`
- Fixed comment-based help example formatting by removing blank lines
within code blocks that would cause documentation generation issues.
- `Grant-SqlDscServerPermission`
- Fixed comment-based help example formatting by removing blank lines
within code blocks that would cause documentation generation issues.
- `New-SqlDscDatabase`
- Fixed comment-based help example formatting by removing blank lines
within code blocks.
- `New-SqlDscDatabaseSnapshot`
- Fixed comment-based help example formatting by removing blank lines
within code blocks.
- `Revoke-SqlDscServerPermission`
- Fixed comment-based help example formatting by removing blank lines
within code blocks.
- `Set-SqlDscDatabasePermission`
- Fixed comment-based help example formatting by removing blank lines
within code blocks.
- `Set-SqlDscServerPermission`
- Fixed comment-based help example formatting by removing blank lines
within code blocks.
- `Test-SqlDscServerPermission`
- Fixed comment-based help example formatting by removing blank lines
within code blocks.
- Unit Tests
- Fixed PowerShell class type identity issues that caused "Cannot convert
'Type' to 'Type'" errors when running multiple test files in the same
Expand Down Expand Up @@ -260,9 +338,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `Set-SqlDscDatabaseProperty`
- Updated comment-based help to reference correct enum values.
- Added SQL Server version requirements to version-specific parameter help.

### Fixed

- `DatabasePermission`
- Fixed `Equals()` method to compare both `State` and `Permission` properties.
Previously, the method incorrectly referenced a non-existent `Grant` property,
Expand Down
8 changes: 8 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ stages:
# Run the integration tests in a specific group order.
# Group 0
'tests/Integration/Commands/Prerequisites.Integration.Tests.ps1'
'tests/Integration/Commands/Prerequisites.RSDB.Integration.Tests.ps1'
'tests/Integration/Commands/Save-SqlDscSqlServerMediaFile.Integration.Tests.ps1'
'tests/Integration/Commands/Import-SqlDscPreferredModule.Integration.Tests.ps1'
# Group 1
Expand All @@ -539,6 +540,8 @@ stages:
'tests/Integration/Commands/Get-SqlDscRSPackage.Integration.Tests.ps1'
'tests/Integration/Commands/Get-SqlDscRSSetupConfiguration.Integration.Tests.ps1'
'tests/Integration/Commands/Test-SqlDscRSInstalled.Integration.Tests.ps1'
'tests/Integration/Commands/Request-SqlDscRSDatabaseScript.Integration.Tests.ps1'
'tests/Integration/Commands/Request-SqlDscRSDatabaseRightsScript.Integration.Tests.ps1'
# Group 3
'tests/Integration/Commands/Get-SqlDscRSConfiguration.Integration.Tests.ps1'
'tests/Integration/Commands/Enable-SqlDscRsSecureConnection.Integration.Tests.ps1'
Expand All @@ -548,6 +551,7 @@ stages:
'tests/Integration/Commands/Add-SqlDscRSUrlReservation.Integration.Tests.ps1'
'tests/Integration/Commands/Remove-SqlDscRSUrlReservation.Integration.Tests.ps1'
'tests/Integration/Commands/Set-SqlDscRSUrlReservation.Integration.Tests.ps1'
'tests/Integration/Commands/Set-SqlDscRSDatabaseConnection.Integration.Tests.ps1'
# Group 8
'tests/Integration/Commands/Repair-SqlDscReportingService.Integration.Tests.ps1'
# Group 9
Expand Down Expand Up @@ -605,6 +609,7 @@ stages:
# Run the integration tests in a specific group order.
# Group 0
'tests/Integration/Commands/Prerequisites.Integration.Tests.ps1'
'tests/Integration/Commands/Prerequisites.RSDB.Integration.Tests.ps1'
'tests/Integration/Commands/Save-SqlDscSqlServerMediaFile.Integration.Tests.ps1'
'tests/Integration/Commands/Import-SqlDscPreferredModule.Integration.Tests.ps1'
# Group 1
Expand All @@ -614,6 +619,8 @@ stages:
'tests/Integration/Commands/Get-SqlDscRSPackage.Integration.Tests.ps1'
'tests/Integration/Commands/Get-SqlDscRSSetupConfiguration.Integration.Tests.ps1'
'tests/Integration/Commands/Test-SqlDscRSInstalled.Integration.Tests.ps1'
'tests/Integration/Commands/Request-SqlDscRSDatabaseScript.Integration.Tests.ps1'
'tests/Integration/Commands/Request-SqlDscRSDatabaseRightsScript.Integration.Tests.ps1'
# Group 3
'tests/Integration/Commands/Get-SqlDscRSConfiguration.Integration.Tests.ps1'
'tests/Integration/Commands/Enable-SqlDscRsSecureConnection.Integration.Tests.ps1'
Expand All @@ -623,6 +630,7 @@ stages:
'tests/Integration/Commands/Add-SqlDscRSUrlReservation.Integration.Tests.ps1'
'tests/Integration/Commands/Remove-SqlDscRSUrlReservation.Integration.Tests.ps1'
'tests/Integration/Commands/Set-SqlDscRSUrlReservation.Integration.Tests.ps1'
'tests/Integration/Commands/Set-SqlDscRSDatabaseConnection.Integration.Tests.ps1'
# Group 8
'tests/Integration/Commands/Repair-SqlDscPowerBIReportServer.Integration.Tests.ps1'
# Group 9
Expand Down
79 changes: 16 additions & 63 deletions source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -396,37 +396,14 @@ function Set-TargetResource

Write-Verbose -Message "Generate database creation script on $DatabaseServerName\$DatabaseInstanceName for database '$reportingServicesDatabaseName'."

$invokeRsCimMethodParameters = @{
CimInstance = $rsConfiguration
MethodName = 'GenerateDatabaseCreationScript'
Arguments = @{
DatabaseName = $reportingServicesDatabaseName
IsSharePointMode = $false
Lcid = $language
}
}
$reportingServicesDatabaseScript = $rsConfiguration | Request-SqlDscRSDatabaseScript -DatabaseName $reportingServicesDatabaseName -Lcid $language -ErrorAction 'Stop'

$reportingServicesDatabaseScript = Invoke-RsCimMethod @invokeRsCimMethodParameters -ErrorAction 'Stop'

# Determine RS service account
$reportingServicesServiceAccountUserName = (Get-CimInstance -ClassName Win32_Service | Where-Object -FilterScript {
$_.Name -eq $reportingServicesServiceName
}).StartName
# The WindowsServiceIdentityActual property contains the actual account name actively used by the service.
$reportingServicesServiceAccountUserName = $rsConfiguration.WindowsServiceIdentityActual

Write-Verbose -Message "Generate database rights script on $DatabaseServerName\$DatabaseInstanceName for database '$reportingServicesDatabaseName' and user '$reportingServicesServiceAccountUserName'."

$invokeRsCimMethodParameters = @{
CimInstance = $rsConfiguration
MethodName = 'GenerateDatabaseRightsScript'
Arguments = @{
DatabaseName = $reportingServicesDatabaseName
UserName = $reportingServicesServiceAccountUserName
IsRemote = $false
IsWindowsUser = $true
}
}

$reportingServicesDatabaseRightsScript = Invoke-RsCimMethod @invokeRsCimMethodParameters -ErrorAction 'Stop'
$reportingServicesDatabaseRightsScript = $rsConfiguration | Request-SqlDscRSDatabaseRightsScript -DatabaseName $reportingServicesDatabaseName -UserName $reportingServicesServiceAccountUserName -ErrorAction 'Stop'

Import-SqlDscPreferredModule

Expand All @@ -444,49 +421,25 @@ function Set-TargetResource
$invokeSqlDscQueryParameters.Encrypt = $true
}

Invoke-SqlDscQuery @invokeSqlDscQueryParameters -Query $reportingServicesDatabaseScript.Script
Invoke-SqlDscQuery @invokeSqlDscQueryParameters -Query $reportingServicesDatabaseRightsScript.Script
Invoke-SqlDscQuery @invokeSqlDscQueryParameters -Query $reportingServicesDatabaseScript
Invoke-SqlDscQuery @invokeSqlDscQueryParameters -Query $reportingServicesDatabaseRightsScript

Write-Verbose -Message "Set database connection on $DatabaseServerName\$DatabaseInstanceName to database '$reportingServicesDatabaseName'."

if ( $DatabaseInstanceName -eq 'MSSQLSERVER' )
{
$reportingServicesConnection = $DatabaseServerName
$setSqlDscRSDatabaseConnectionParameters = @{
ServerName = $DatabaseServerName
DatabaseName = $reportingServicesDatabaseName
Type = 'ServiceAccount'
Force = $true
ErrorAction = 'Stop'
}
else

if ($DatabaseInstanceName -ne 'MSSQLSERVER')
{
$reportingServicesConnection = "$DatabaseServerName\$DatabaseInstanceName"
}

$invokeRsCimMethodParameters = @{
CimInstance = $rsConfiguration
MethodName = 'SetDatabaseConnection'
Arguments = @{
Server = $reportingServicesConnection
DatabaseName = $reportingServicesDatabaseName
Username = ''
Password = ''

<#
Can be set to either:
0 = Windows
1 = Sql Server
2 = Windows Service (Integrated Security)

When set to 2 the Reporting Server Web service will use
either the ASP.NET account or an application pool’s account
and the Windows service account to access the report server
database.

See more in the article
https://docs.microsoft.com/en-us/sql/reporting-services/wmi-provider-library-reference/configurationsetting-method-setdatabaseconnection#remarks

#>
CredentialsType = 2
}
$setSqlDscRSDatabaseConnectionParameters.InstanceName = $DatabaseInstanceName
}

Invoke-RsCimMethod @invokeRsCimMethodParameters -ErrorAction 'Stop'
$rsConfiguration | Set-SqlDscRSDatabaseConnection @setSqlDscRSDatabaseConnectionParameters

<#
When initializing SSRS 2019, the call to InitializeReportServer
Expand Down
102 changes: 102 additions & 0 deletions source/Private/Get-HResultMessage.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<#
.SYNOPSIS
Gets a human-readable message for a given HRESULT code.

.DESCRIPTION
Translates common Windows HRESULT error codes into human-readable
messages. This is particularly useful when CIM methods return an
HRESULT code without detailed error information in ExtendedErrors
or Error properties.

.PARAMETER HResult
The HRESULT code to translate. This is typically a 32-bit signed
integer returned from a Windows API or CIM method call.

.OUTPUTS
`System.String`

Returns a descriptive message for known HRESULT codes, or a generic
message with the hexadecimal code for unknown values.

.EXAMPLE
Get-HResultMessage -HResult -2147023181

Returns: The account has not been granted the requested logon type at
this computer. Verify that the service account has the required
permissions to interact with the Reporting Services WMI provider.

.EXAMPLE
Get-HResultMessage -HResult -2147024891

Returns: Access is denied. Verify that the current user has administrator
rights on the Reporting Services instance.

.NOTES
This function is used internally by other commands to provide actionable
error messages when Reporting Services CIM methods fail without detailed
error information. These codes have not been verified against any official
Microsoft documentation, and based on the common HRESULT values in
https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values.
#>
function Get-HResultMessage
{
[CmdletBinding()]
[OutputType([System.String])]
param
(
[Parameter(Mandatory = $true)]
[System.Int32]
$HResult
)

<#
HRESULT values are 32-bit signed integers. Negative values indicate
errors. The HRESULT is composed of:
- Bit 31: Severity (0 = success, 1 = error)
- Bits 16-30: Facility code
- Bits 0-15: Error code

Common HRESULT values are documented at:
https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
#>
$hResultMessages = @{
# cSpell: ignore ACCESSDENIED LOGON
# E_ACCESSDENIED (0x80070005) - General access denied error
-2147024891 = $script:localizedData.HResult_AccessDenied

# ERROR_LOGON_TYPE_NOT_GRANTED (0x80070533) - Account lacks logon rights
-2147023181 = $script:localizedData.HResult_LogonTypeNotGranted

# E_FAIL (0x80004005) - Unspecified failure
-2147467259 = $script:localizedData.HResult_UnspecifiedFailure

# E_INVALIDARG (0x80070057) - One or more arguments are invalid
-2147024809 = $script:localizedData.HResult_InvalidArgument

# E_OUTOFMEMORY (0x8007000E) - Out of memory
-2147024882 = $script:localizedData.HResult_OutOfMemory

# RPC_E_DISCONNECTED (0x80010108) - The object invoked has disconnected
-2147417848 = $script:localizedData.HResult_RpcDisconnected

# RPC_S_SERVER_UNAVAILABLE (0x800706BA) - The RPC server is unavailable
-2147023174 = $script:localizedData.HResult_RpcServerUnavailable

# ERROR_SERVICE_NOT_ACTIVE (0x80070426) - The service has not been started
-2147023834 = $script:localizedData.HResult_ServiceNotActive
}

if ($hResultMessages.ContainsKey($HResult))
{
return $hResultMessages[$HResult]
}

<#
Return a generic message with the hexadecimal representation for unknown codes.
Convert to hex using bitwise operation to handle negative values that would
overflow when casting directly to UInt32 (e.g., Int32.MinValue = -2147483648).
#>
$hexValue = '0x{0:X8}' -f ($HResult -band 0xFFFFFFFF)

return ($script:localizedData.HResult_Unknown -f $hexValue)
}
Loading