DSCResources/MSFT_xRDSessionCollectionConfiguration/MSFT_xRDSessionCollectionConfiguration.psm1
|
$modulePath = Join-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -ChildPath 'Modules' # Import the Common Modules Import-Module -Name (Join-Path -Path $modulePath -ChildPath 'xRemoteDesktopSessionHost.Common') Import-Module -Name (Join-Path -Path $modulePath -ChildPath 'DscResource.Common') if (-not (Test-xRemoteDesktopSessionHostOsRequirement)) { throw 'The minimum OS requirement was not met.' } ####################################################################### # The Get-TargetResource cmdlet. ####################################################################### function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [ValidateLength(1, 256)] [System.String] $CollectionName, [Parameter()] [System.UInt32] $ActiveSessionLimitMin, [Parameter()] [System.Boolean] $AuthenticateUsingNLA, [Parameter()] [System.Boolean] $AutomaticReconnectionEnabled, [Parameter()] [System.String] $BrokenConnectionAction, [Parameter()] [System.String] $ClientDeviceRedirectionOptions, [Parameter()] [System.Boolean] $ClientPrinterAsDefault, [Parameter()] [System.Boolean] $ClientPrinterRedirected, [Parameter()] [System.String] $CollectionDescription, [Parameter()] [System.String] $ConnectionBroker, [Parameter()] [System.String] $CustomRdpProperty, [Parameter()] [System.UInt32] $DisconnectedSessionLimitMin, [Parameter()] [System.String] $EncryptionLevel, [Parameter()] [System.UInt32] $IdleSessionLimitMin, [Parameter()] [System.UInt32] $MaxRedirectedMonitors, [Parameter()] [System.Boolean] $RDEasyPrintDriverEnabled, [Parameter()] [System.String] $SecurityLayer, [Parameter()] [System.Boolean] $TemporaryFoldersDeletedOnExit, [Parameter()] [System.String[]] $UserGroup, [Parameter()] [System.String] $DiskPath, [Parameter()] [System.Boolean] $EnableUserProfileDisk, [Parameter()] [System.UInt32] $MaxUserProfileDiskSizeGB, [Parameter()] [System.String[]] $IncludeFolderPath, [Parameter()] [System.String[]] $ExcludeFolderPath, [Parameter()] [System.String[]] $IncludeFilePath, [Parameter()] [System.String[]] $ExcludeFilePath ) Assert-Module -ModuleName 'RemoteDesktop' -ImportModule Write-Verbose "Getting currently configured RDSH Collection properties for collection $CollectionName" $collectionGeneral = Get-RDSessionCollectionConfiguration -CollectionName $CollectionName $collectionClient = Get-RDSessionCollectionConfiguration -CollectionName $CollectionName -Client $collectionConnection = Get-RDSessionCollectionConfiguration -CollectionName $CollectionName -Connection $collectionSecurity = Get-RDSessionCollectionConfiguration -CollectionName $CollectionName -Security $collectionUserGroup = Get-RDSessionCollectionConfiguration -CollectionName $CollectionName -UserGroup $result = @{ CollectionName = $collectionGeneral.CollectionName CollectionDescription = $collectionGeneral.CollectionDescription # For whatever reason this value gets returned with a trailing carriage return CustomRdpProperty = ([System.String]$collectionGeneral.CustomRdpProperty).Trim() ClientDeviceRedirectionOptions = $collectionClient.ClientDeviceRedirectionOptions ClientPrinterAsDefault = $collectionClient.ClientPrinterAsDefault ClientPrinterRedirected = $collectionClient.ClientPrinterRedirected MaxRedirectedMonitors = $collectionClient.MaxRedirectedMonitors RDEasyPrintDriverEnabled = $collectionClient.RDEasyPrintDriverEnabled ActiveSessionLimitMin = $collectionConnection.ActiveSessionLimitMin AutomaticReconnectionEnabled = $collectionConnection.AutomaticReconnectionEnabled BrokenConnectionAction = $collectionConnection.BrokenConnectionAction DisconnectedSessionLimitMin = $collectionConnection.DisconnectedSessionLimitMin IdleSessionLimitMin = $collectionConnection.IdleSessionLimitMin TemporaryFoldersDeletedOnExit = $collectionConnection.TemporaryFoldersDeletedOnExit AuthenticateUsingNLA = $collectionSecurity.AuthenticateUsingNLA EncryptionLevel = $collectionSecurity.EncryptionLevel SecurityLayer = $collectionSecurity.SecurityLayer UserGroup = $collectionUserGroup.UserGroup } # This part of the configuration only applies to Win 2016+ if ((Get-xRemoteDesktopSessionHostOsVersion).Major -ge 10) { Write-Verbose 'Running on W2016+, get UserProfileDisk configuration' $collectionUserProfileDisk = Get-RDSessionCollectionConfiguration -CollectionName $CollectionName -UserProfileDisk $null = $result.Add('DiskPath', $collectionUserProfileDisk.DiskPath) $null = $result.Add('EnableUserProfileDisk', $collectionUserProfileDisk.EnableUserProfileDisk) $null = $result.Add('MaxUserProfileDiskSizeGB', $collectionUserProfileDisk.MaxUserProfileDiskSizeGB) $null = $result.Add('IncludeFolderPath', $collectionUserProfileDisk.IncludeFolderPath) $null = $result.Add('ExcludeFolderPath', $collectionUserProfileDisk.ExcludeFolderPath) $null = $result.Add('IncludeFilePath', $collectionUserProfileDisk.IncludeFilePath) $null = $result.Add('ExcludeFilePath', $collectionUserProfileDisk.ExcludeFilePath) } $result } ######################################################################## # The Set-TargetResource cmdlet. ######################################################################## function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateLength(1, 256)] [System.String] $CollectionName, [Parameter()] [System.UInt32] $ActiveSessionLimitMin, [Parameter()] [System.Boolean] $AuthenticateUsingNLA, [Parameter()] [System.Boolean] $AutomaticReconnectionEnabled, [Parameter()] [System.String] $BrokenConnectionAction, [Parameter()] [System.String] $ClientDeviceRedirectionOptions, [Parameter()] [System.Boolean] $ClientPrinterAsDefault, [Parameter()] [System.Boolean] $ClientPrinterRedirected, [Parameter()] [System.String] $CollectionDescription, [Parameter()] [System.String] $ConnectionBroker, [Parameter()] [System.String] $CustomRdpProperty, [Parameter()] [System.UInt32] $DisconnectedSessionLimitMin, [Parameter()] [System.String] $EncryptionLevel, [Parameter()] [System.UInt32] $IdleSessionLimitMin, [Parameter()] [System.UInt32] $MaxRedirectedMonitors, [Parameter()] [System.Boolean] $RDEasyPrintDriverEnabled, [Parameter()] [System.String] $SecurityLayer, [Parameter()] [System.Boolean] $TemporaryFoldersDeletedOnExit, [Parameter()] [System.String[]] $UserGroup, [Parameter()] [System.String] $DiskPath, [Parameter()] [System.Boolean] $EnableUserProfileDisk, [Parameter()] [System.UInt32] $MaxUserProfileDiskSizeGB, [Parameter()] [System.String[]] $IncludeFolderPath, [Parameter()] [System.String[]] $ExcludeFolderPath, [Parameter()] [System.String[]] $IncludeFilePath, [Parameter()] [System.String[]] $ExcludeFilePath ) Write-Verbose 'Setting DSC collection properties' Assert-Module -ModuleName 'RemoteDesktop' -ImportModule try { $null = Get-RDSessionCollection -CollectionName $CollectionName -ErrorAction Stop } catch { throw "Failed to lookup RD Session Collection $CollectionName. Error: $_" } # By default we do not configure the UserProfileDisk (this is in a different parameter set and we could be running on W2012 R2) $null = $PSBoundParameters.Remove('DiskPath') $null = $PSBoundParameters.Remove('EnableUserProfileDisk') $null = $PSBoundParameters.Remove('ExcludeFilePath') $null = $PSBoundParameters.Remove('ExcludeFolderPath') $null = $PSBoundParameters.Remove('IncludeFilePath') $null = $PSBoundParameters.Remove('IncludeFolderPath') $null = $PSBoundParameters.Remove('MaxUserProfileDiskSizeGB') if ((Get-xRemoteDesktopSessionHostOsVersion).Major -ge 10) { Write-Verbose 'Running on W2016 or higher, prepare to set UserProfileDisk configuration' # First set the initial configuration before trying to modify the UserProfileDisk Configuration Set-RDSessionCollectionConfiguration @PSBoundParameters if ($EnableUserProfileDisk) { Write-Verbose 'EnableUserProfileDisk is True - a DiskPath and MaxUserProfileDiskSizeGB are now mandatory' if ($DiskPath) { if (-not(Test-Path -Path $DiskPath -ErrorAction SilentlyContinue)) { New-ArgumentException -ArgumentName 'DiskPath' -Message ('To enable UserProfileDisk we need a valid DiskPath. Path {0} not found' -f $DiskPath) } else { Write-Verbose "EnableUserProfileDisk: Validated diskPath: $DiskPath" } } else { New-ArgumentException -ArgumentName 'DiskPath' -Message 'No value found for parameter DiskPath. This is a mandatory parameter if EnableUserProfileDisk is set to True' } if ($MaxUserProfileDiskSizeGB -gt 0) { Write-Verbose "EnableUserProfileDisk: Validated MaxUserProfileDiskSizeGB size: $MaxUserProfileDiskSizeGB" } else { New-ArgumentException -ArgumentName 'MaxUserProfileDiskSizeGB' -Message ( 'To enable UserProfileDisk we need a setting for MaxUserProfileDiskSizeGB that is greater than 0. Current value {0} is not valid' -f $MaxUserProfileDiskSizeGB ) } $enableUserProfileDiskSplat = @{ CollectionName = $CollectionName DiskPath = $DiskPath EnableUserProfileDisk = $EnableUserProfileDisk ExcludeFilePath = $ExcludeFilePath ExcludeFolderPath = $ExcludeFolderPath IncludeFilePath = $IncludeFilePath IncludeFolderPath = $IncludeFolderPath MaxUserProfileDiskSizeGB = $MaxUserProfileDiskSizeGB } # 2>&1 redirects the error stream to output stream. This for us to be able to ignore certain errors that popup in Set-RDSessionCollectionConfiguration. $null = Set-RDSessionCollectionConfiguration @enableUserProfileDiskSplat -ErrorAction SilentlyContinue -ErrorVariable setRDSessionCollectionErrors 2>&1 # This is a workaround for the buggy Set-RDSessionCollectionConfiguration. This command starts the functions in the Microsoft.windows.servermanagerworkflows configuration. # In this configuration, the C:\Windows\system32\WindowsPowerShell\v1.0\Modules\RemoteDesktop\Utility.psm1 module cannot call the RemoteDesktop module functions as they seem to load without the -RD prefix. # Here, we work around the errors thrown by Test-UserVhdPathInUse (the function in the Utility.psm1 module which calls the RemoteDesktop module functions) foreach ($setRDSessionCollectionError in $setRDSessionCollectionErrors) { if ($SetRDSessionCollectionError.FullyQualifiedErrorId -eq 'CommandNotFoundException') { Write-Verbose "Set-RDSessionCollectionConfiguration: trapped erroneous CommandNotFoundException errors, that's ok, continuing..." # ignore & continue } else { Write-Error "Set-RDSessionCollectionConfiguration error: $setRDSessionCollectionError" } } } else { Set-RDSessionCollectionConfiguration -CollectionName $CollectionName -DisableUserProfileDisk } } else { Set-RDSessionCollectionConfiguration @PSBoundParameters } } ####################################################################### # The Test-TargetResource cmdlet. ####################################################################### function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateLength(1, 256)] [System.String] $CollectionName, [Parameter()] [System.UInt32] $ActiveSessionLimitMin, [Parameter()] [System.Boolean] $AuthenticateUsingNLA, [Parameter()] [System.Boolean] $AutomaticReconnectionEnabled, [Parameter()] [System.String] $BrokenConnectionAction, [Parameter()] [System.String] $ClientDeviceRedirectionOptions, [Parameter()] [System.Boolean] $ClientPrinterAsDefault, [Parameter()] [System.Boolean] $ClientPrinterRedirected, [Parameter()] [System.String] $CollectionDescription, [Parameter()] [System.String] $ConnectionBroker, [Parameter()] [System.String] $CustomRdpProperty, [Parameter()] [System.UInt32] $DisconnectedSessionLimitMin, [Parameter()] [System.String] $EncryptionLevel, [Parameter()] [System.UInt32] $IdleSessionLimitMin, [Parameter()] [System.UInt32] $MaxRedirectedMonitors, [Parameter()] [System.Boolean] $RDEasyPrintDriverEnabled, [Parameter()] [System.String] $SecurityLayer, [Parameter()] [System.Boolean] $TemporaryFoldersDeletedOnExit, [Parameter()] [System.String[]] $UserGroup, [Parameter()] [System.String] $DiskPath, [Parameter()] [System.Boolean] $EnableUserProfileDisk, [Parameter()] [System.UInt32] $MaxUserProfileDiskSizeGB, [Parameter()] [System.String[]] $IncludeFolderPath, [Parameter()] [System.String[]] $ExcludeFolderPath, [Parameter()] [System.String[]] $IncludeFilePath, [Parameter()] [System.String[]] $ExcludeFilePath ) Write-Verbose 'Testing DSC collection properties' $null = $PSBoundParameters.Remove('Verbose') $null = $PSBoundParameters.Remove('Debug') $null = $PSBoundParameters.Remove('ConnectionBroker') if ((Get-xRemoteDesktopSessionHostOsVersion).Major -lt 10) { Write-Verbose 'Running on W2012R2 or lower, removing properties that are not compatible' $null = $PSBoundParameters.Remove('CollectionName') $null = $PSBoundParameters.Remove('EnableUserProfileDisk') $null = $PSBoundParameters.Remove('DiskPath') $null = $PSBoundParameters.Remove('ExcludeFilePath') $null = $PSBoundParameters.Remove('ExcludeFolderPath') $null = $PSBoundParameters.Remove('IncludeFilePath') $null = $PSBoundParameters.Remove('IncludeFolderPath') $null = $PSBoundParameters.Remove('MaxUserProfileDiskSizeGB') } if (-not($EnableUserProfileDisk)) { Write-Verbose 'Running on W2016+ and UserProfileDisk is disabled. Removing properties from compare' $null = $PSBoundParameters.Remove('DiskPath') $null = $PSBoundParameters.Remove('ExcludeFilePath') $null = $PSBoundParameters.Remove('ExcludeFolderPath') $null = $PSBoundParameters.Remove('IncludeFilePath') $null = $PSBoundParameters.Remove('IncludeFolderPath') $null = $PSBoundParameters.Remove('MaxUserProfileDiskSizeGB') } $testDscParameterStateSplat = @{ CurrentValues = Get-TargetResource -CollectionName $CollectionName DesiredValues = $PSBoundParameters TurnOffTypeChecking = $true SortArrayValues = $true Verbose = $VerbosePreference } Test-DscParameterState @testDscParameterStateSplat } Export-ModuleMember -Function *-TargetResource |