<
.SYNOPSIS
Set WVD 2020 Spring Release Hostpool Max Session Limit.
.DESCRIPTION
Set WVD 2020 Spring Release Hostpool Max Session Limit, using the new Az.Desktopvirtualization PowerShell Module and WVD ARM Architecture (2020 Spring Release).
.EXAMPLE
Set-WVDHostpoolMaxSessionLimit -SessionHostName <SessionHostName>
.CONTEXT
Windows Virtual Desktops
.MODIFICATION_HISTORY
Esther Barthel, MSc - 25/05/20 - Original code
Esther Barthel, MSc - 25/05/20 - Changed the script to support WVD 2020 Spring Release (ARM Architecture update)
.LINK
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/import-clixml?view=powershell-7
.COMPONENT
Set-AzSPCredentials - The required Azure Service Principal (Subcription level) and tenantID information need to be securely stored in a Credentials File. The Set-AzSPCredentials Script Action will ensure the file is created according to ControlUp standards
Az.Desktopvirtualization PowerShell Module - The Az.Desktopvirtualization PowerShell Module must be installed on the machine running this Script Action
.NOTES
Version: 2.0
Author: Esther Barthel, MSc
Creation Date: 2020-05-25
Updated: 2020-05-25
Changed the script to support WVD 2020 Spring Release (ARM Architecture update)
Updated: 2020-06-28
Changed the script to use the ControlUp Description (ID) as input parameter
Updated: 2020-07-10
SBA rework to translate Session Host Name to HostPool ID (ControlUp WVD Script Action Integration workaround for current CU Console limitations)
Purpose: Script Action, created for ControlUp WVD Monitoring
Copyright (c) cognition IT. All rights reserved.
[CmdletBinding()]
Param
(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='SBA parameter auto entry: Session Host NetBIOS Name'
)]
[ValidateNotNullOrEmpty()]
[string] $SessionHostName,
[Parameter(
Position=1,
Mandatory=$true,
HelpMessage='Specify the Max Session Limit'
)]
[ValidateRange(0,999999)]
[int] $MaxSessionLimit
)
[string]$mainformXAML = @'
<Window x:Class="wvdSP_Input_Form.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Esther_s_Input_Form"
mc:Ignorable="d"
Title="Enter the WVD Service Principal (SP) details" Height="389.336" Width="617.103">
<Grid>
<TextBox x:Name="textboxTenantId" HorizontalAlignment="Left" Height="31" Margin="176,50,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="398"/>
<Label Content="SP Tenant ID" HorizontalAlignment="Left" Height="30" Margin="29,51,0,0" VerticalAlignment="Top" Width="117"/>
<TextBox x:Name="textboxAppId" HorizontalAlignment="Left" Height="30" Margin="176,118,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="398"/>
<Label Content="SP App ID" HorizontalAlignment="Left" Height="30" Margin="29,118,0,0" VerticalAlignment="Top" Width="117"/>
<PasswordBox x:Name="textboxAppSecret" HorizontalAlignment="Left" Height="31" Margin="176,192,0,0" VerticalAlignment="Top" Width="398"/>
<Label Content="SP App Secret" HorizontalAlignment="Left" Height="30" Margin="29,193,0,0" VerticalAlignment="Top" Width="117"/>
<Button x:Name="buttonOK" Content="OK" HorizontalAlignment="Left" Height="46" Margin="29,274,0,0" VerticalAlignment="Top" Width="175" IsDefault="True"/>
<Button x:Name="buttonCancel" Content="Cancel" HorizontalAlignment="Left" Height="46" Margin="244,274,0,0" VerticalAlignment="Top" Width="175" IsDefault="True"/>
</Grid>
</Window>
'@
Function Invoke-WVDSPCredentialsForm {
Param
(
[Parameter(Mandatory=$true)]
$inputXaml
)
$form = $null
$inputXML = $inputXaml -replace 'mc:Ignorable="d"' , '' -replace 'x:N' ,'N' -replace '^<Win.*' , '<Window'
[xml]$xaml = $inputXML
if( $xaml )
{
$reader = New-Object -TypeName Xml.XmlNodeReader -ArgumentList $xaml
try
{
$form = [Windows.Markup.XamlReader]::Load( $reader )
}
catch
{
Throw "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .NET is installed.`n$_"
}
$xaml.SelectNodes( '//*[@Name]' ) | ForEach-Object `
{
Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name) -Scope Global
}
}
else
{
Throw "Failed to convert input XAML to WPF XML"
}
$form
}
function Get-AzSPStoredCredentials {
<
.SYNOPSIS
Retrieve the Azure Service Principal Stored Credentials.
.DESCRIPTION
Retrieve the Azure Service Principal Stored Credentials from a stored credentials file.
.EXAMPLE
Get-AzSPStoredCredentials
.CONTEXT
Azure
.MODIFICATION_HISTORY
Esther Barthel, MSc - 03/03/20 - Original code
Esther Barthel, MSc - 03/03/20 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
.COMPONENT
Import-Clixml - https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/import-clixml?view=powershell-5.1
.NOTES
Version: 0.1
Author: Esther Barthel, MSc
Creation Date: 2020-03-03
Updated: 2020-03-03
Standardized the function, based on the ControlUp Standards (v0.2)
Updated: 2020-05-08
Created a separate Azure Credentials function to support ARM architecture and Az PowerShell Module scripted actions
Purpose: Script Action, created for ControlUp WVD Monitoring
Copyright (c) cognition IT. All rights reserved.
[CmdletBinding()]
Param()
$System = "AZ"
$strAzSPCredFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
$AzSPCredentials = $null
Write-Verbose ""
Write-Verbose "----------------------------- "
Write-Verbose "| Get Azure SP Credentials: | "
Write-Verbose "----------------------------- "
Write-Verbose ""
If (Test-Path -Path "$($strAzSPCredFolder)\$($env:USERNAME)_$($System)_Cred.xml")
{
try
{
$AzSPCredentials = Import-Clixml -Path "$strAzSPCredFolder\$($env:USERNAME)_$($System)_Cred.xml"
}
catch
{
Write-Error ("The required PSCredential object could not be loaded. " + $_)
}
}
Else
{
Write-Error "The Azure Service Principal Credentials file stored for this user ($($env:USERNAME)) cannot be found. `nCreate the file with the Set-AzSPCredentials script action (prerequisite)."
Exit
}
return $AzSPCredentials
}
function Set-AzSPStoredCredentials {
<
.SYNOPSIS
Store the Azure Service Principal Credentials.
.DESCRIPTION
Store the Azure Service Principal Credentials to an encrypted stored credentials file.
.EXAMPLE
Set-AzSPStoredCredentials
.CONTEXT
Azure
.MODIFICATION_HISTORY
Esther Barthel, MSc - 22/03/20 - Original code
Esther Barthel, MSc - 22/03/20 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
.COMPONENT
Export-Clixml - https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/export-clixml?view=powershell-5.1
.NOTES
Version: 0.1
Author: Esther Barthel, MSc
Creation Date: 2020-03-22
Updated: 2020-03-22
Standardized the function, based on the ControlUp Standards (v0.2)
Updated: 2020-05-08
Created a separate Azure Credentials function to support ARM architecture and Az PowerShell Module scripted actions
Purpose: Script Action, created for ControlUp WVD Monitoring
Copyright (c) cognition IT. All rights reserved.
[CmdletBinding()]
Param(
)
$System = "AZ"
$strAzSPCredFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
$AzSPCredentials = $null
Write-Verbose ""
Write-Verbose "------------------------------- "
Write-Verbose "| Store Azure SP Credentials: | "
Write-Verbose "------------------------------- "
Write-Verbose ""
If (!(Test-Path -Path "$($strAzSPCredFolder)"))
{
New-Item -ItemType Directory -Path "$($strAzSPCredFolder)"
Write-Verbose "* AzSPCredentials: Path $($strAzSPCredFolder) created"
}
try
{
Add-Type -AssemblyName PresentationFramework
if( $mainForm = Invoke-WVDSPCredentialsForm -inputXaml $mainformXAML )
{
$WPFbuttonOK.Add_Click( {
$_.Handled = $true
$mainForm.DialogResult = $true
$mainForm.Close()
})
$WPFbuttonCancel.Add_Click( {
$_.Handled = $true
$mainForm.DialogResult = $false
$mainForm.Close()
})
$null = $WPFtextboxTenantId.Focus()
if( $mainForm.ShowDialog() )
{
If ([string]::IsNullOrEmpty($($WPFtextboxTenantId.Text)))
{
Write-Error "The provided tenant ID is empty!"
Exit
}
else
{
$tenantID = $($WPFtextboxTenantId.Text)
}
If ([string]::IsNullOrEmpty($($WPFtextboxAppId.Text)))
{
Write-Error "The provided app ID is empty!"
Exit
}
else
{
$appID = $($WPFtextboxAppId.Text)
}
If ([string]::IsNullOrEmpty($($WPFtextboxAppSecret.Password)))
{
Write-Error "The provided app Secret is empty!"
Exit
}
else
{
$appSecret = $($WPFtextboxAppSecret.Password)
}
$appSecret = $($WPFtextboxAppSecret.Password)
}
else
{
Write-Error "The required tenant ID, app ID and app Secret could not be retrieved from the form."
Break
}
}
}
catch
{
Write-Error ("The required information could not be retrieved from the input form. " + $_)
Exit
}
$secureAppSecret = ConvertTo-SecureString -String $appSecret -AsPlainText -Force
$spCreds = New-Object System.Management.Automation.PSCredential($appID, $secureAppSecret)
try
{
$hashAzSPCredentials = @{
'tenantID' = $tenantID
'spCreds' = $spCreds
}
$AzSPCredentials = Export-Clixml -Path "$strAzSPCredFolder\$($env:USERNAME)_$($System)_Cred.xml" -InputObject $hashAzSPCredentials -Force
}
catch
{
Write-Error ("The required PSCredential object could not be exported. " + $_)
Exit
}
Write-Verbose "* AzSPCredentials: Exported succesfully."
return $hashAzSPCredentials
}
function Invoke-CheckInstallAndImportPSModulePrereq() {
<
.SYNOPSIS
Check, Install (if allowed) and Import the given PSModule prerequisite.
.DESCRIPTION
Check, Install (if allowed) and Import the given PSModule prerequisite.
.EXAMPLE
Invoke-CheckInstallAndImportPSModulePrereq -ModuleName Az.DesktopVirtualization
.CONTEXT
Windows Virtual Desktops
.MODIFICATION_HISTORY
Esther Barthel, MSc - 23/03/20 - Original code
Esther Barthel, MSc - 23/03/20 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
.COMPONENT
.NOTES
Version: 1.0
Author: Esther Barthel, MSc
Creation Date: 2020-03-23
Updated: 2020-03-23
Standardized the function, based on the ControlUp Standards (v0.2)
Updated: 2020-07-22
Added an extra check to the Invoke-CheckInstallAndImportPSModuleRepreq function for the required NuGet packageprovider. If minimumversion 2.8.5.201 is not found it will install the NuGet PackageProvider
Purpose: Script Action, created for ControlUp WVD Monitoring
Copyright (c) cognition IT. All rights reserved.
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the PowerShell Module name that needs to be installed and imported'
)]
[ValidateNotNullOrEmpty()]
[string] $ModuleName
)
If (-not((Get-Module -Name $($ModuleName)).Name))
{
Write-Verbose "* CheckAndInstallPSModulePrereq: PowerShell Module $($ModuleName) is not loaded in current session"
If (-not((Get-Module -Name $($ModuleName) -ListAvailable).Name))
{
[bool]$isElevated = (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if ($isElevated)
{
Write-Host ("The PowerShell Module $($ModuleName) is installed from an elevated session, Scope is set to AllUsers.") -ForegroundColor Yellow
$psScope = "AllUsers"
}
else
{
Write-Warning "The PowerShell Module $($ModuleName) is NOT installed from an elevated session, Scope is set to CurrentUser."
$psScope = "CurrentUser"
}
try
{
If (!(([string](Get-PackageProvider -Name NuGet -ListAvailable -ErrorAction SilentlyContinue).Version) -ge "2.8.5.201"))
{
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Scope $psScope -Force -Confirm:$false -WarningAction SilentlyContinue
}
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
Write-Verbose "* CheckAndInstallPSModulePrereq: The prerequired NuGet PackageProvider is installed."
try
{
Write-Verbose "* CheckAndInstallPSModulePrereq: Installing the $($ModuleName) PowerShell Module from the PSGallery."
PowerShellGet\Install-Module -Name $($ModuleName) -Confirm:$false -Force -AllowClobber -Scope $psScope -WarningAction SilentlyContinue
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
Write-Verbose "* CheckAndInstallPSModulePrereq: The $($ModuleName) PowerShell Module is installed from the PSGallery."
}
}
try
{
Import-Module -Name $($ModuleName) -Force
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
Write-Verbose "* CheckAndInstallPSModulePrereq: The $($ModuleName) PowerShell Module is imported in the current session."
}
function Invoke-NETFrameworkCheck() {
<
.SYNOPSIS
Check if the .NET Framework version is 4.7.2 or up.
.DESCRIPTION
Check if the .NET Framework version is 4.7.2 or up.
.EXAMPLE
Invoke-NETFrameworkCheck
.CONTEXT
Windows Virtual Desktops
.MODIFICATION_HISTORY
Esther Barthel, MSc - 17/05/20 - Original code
Esther Barthel, MSc - 17/05/20 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
.COMPONENT
.NOTES
Version: 0.1
Author: Esther Barthel, MSc
Creation Date: 2020-05-17
Updated: 2020-05-17
Standardized the function, based on the ControlUp Standards (v0.2)
Purpose: Script Action, created for ControlUp WVD Monitoring
Copyright (c) cognition IT. All rights reserved.
[CmdletBinding()]
Param()
If ((Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' -Name Release).Release -ge 461808)
{
# Required .NET Framework found
Write-Verbose ".NET Framework 4.7.2 or up is installed on this machine"
return $true
}
Else
{
return $false
}
#endregion Check .NET Framework
}
function Get-WVDHostpoolSessionHost () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the Subscription ID'
)]
[string] $SubscriptionID,
[Parameter(
Position=1,
Mandatory=$false,
HelpMessage='Enter the Host Pool name'
)]
[string] $HostPoolName,
[Parameter(
Position=2,
Mandatory=$false,
HelpMessage='Enter the Session Host name'
)]
[string] $SessionHostName
)
#Retrieve the WVD hostPool information for this Subscription
[array]$psobjectCollection = Get-AzWvdHostPool -SubscriptionId $($azSubscription.Id.ToString()) |
ForEach-Object {
$wvdHostPool = $_
If ($wvdHostPool.Name -like "$HostPoolName*")
{
Get-AzWvdSessionHost -HostPoolName $wvdHostpool.Name -ResourceGroupName $($wvdHostPool.Id.Split("/")[4]) |
ForEach-Object {
$wvdSessionHost = $_
If ($wvdSessionHost.Name.Split("/")[1] -like "$SessionHostName*")
{
$wvdSessionHost | Select @{Name='HostPoolName'; Expression={$wvdHostPool.Name}},
@{Name='SessionHostName'; Expression={$_.Name.Split("/")[1]}},
AgentVersion,
AllowNewSession,
@{Name='DrainMode'; Expression={if($_.AllowNewSession -eq "True"){return "Off"}else{return "On"}}},
AsignedUser,
LastHeartBeat,
LastUpdateTime,
OSVersion,
Session,
@{Name='ActiveSessions'; Expression={$_.Session}},
Status,
StatusTimestamp,
SxSStackVersion,
Type,
UpdateErrorMessage,
UpdateState,
@{Name='HostPoolApplicationGroupReference'; Expression={$wvdHostPool.ApplicationGroupReference}},
@{Name='HostPoolCustomRdpProperty'; Expression={$wvdHostPool.CustomRdpProperty}},
@{Name='HostPoolDescription'; Expression={$wvdHostPool.Description}},
@{Name='HostPoolFriendlyName'; Expression={$wvdHostPool.FriendlyName}},
@{Name='HostPoolType'; Expression={$wvdHostPool.HostPoolType}},
@{Name='HostPoolLoadBalancerType'; Expression={$wvdHostPool.LoadBalancerType}},
@{Name='HostpoolLocation'; Expression={$wvdHostPool.Location}},
@{Name='HostpoolMaxSessionLimit'; Expression={$wvdHostPool.MaxSessionLimit}},
@{Name='HostpoolResourceGroup'; Expression={$_.Id.Split("/")[4]}},
@{Name='HostPoolSsoContext'; Expression={$wvdHostPool.SsoContext}},
@{Name='HostPoolVMTemplate'; Expression={$wvdHostPool.VMTemplate}},
@{Name='HostPoolValidationEnvironment'; Expression={$wvdHostPool.ValidationEnvironment}}
}
}
}
}
return $psobjectCollection
}
function Set-WVDSessionHostDrainMode () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the Session Host Name'
)]
[string] $SessionHostName,
[Parameter(
Position=1,
Mandatory=$false,
HelpMessage='Enter the Host Pool name'
)]
[string] $HostPoolName,
[Parameter(
Position=2,
Mandatory=$false,
HelpMessage='Enter the Resource Group name'
)]
[string] $ResourceGroupName,
[Parameter(
Position=2,
Mandatory=$false,
HelpMessage='Enter the Drain Modee'
)]
[ValidateSet("ON","OFF")]
[string] $DrainMode
)
$boolDrainMode = $false
If ($DrainMode -eq "OFF")
{
$boolDrainMode = $true
}
try
{
Update-AzWvdSessionHost -HostPoolName $HostPoolName -ResourceGroupName $ResourceGroupName -Name $SessionHostName -AllowNewSession:$boolDrainMode | Out-Null
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
}
function Set-WVDHostpoolMaxSessionLimit () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the Hostpool Name'
)]
[string] $HostpoolName,
[Parameter(
Position=1,
Mandatory=$true,
HelpMessage='Enter the Resource Group name'
)]
[string] $ResourceGroupName,
[Parameter(
Position=2,
Mandatory=$false,
HelpMessage='Enter the max session limit'
)]
[int] $MaxSessionLimit
)
try
{
Update-AzWvdHostPool -Name $HostPoolName -ResourceGroupName $ResourceGroupName -MaxSessionLimit $MaxSessionLimit | Out-Null
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
}
function Set-WVDHostpoolLoadBalancerType () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the Hostpool Name'
)]
[string] $HostpoolName,
[Parameter(
Position=1,
Mandatory=$true,
HelpMessage='Enter the Resource Group name'
)]
[string] $ResourceGroupName,
[Parameter(
Position=2,
Mandatory=$false,
HelpMessage='Enter the Load Balancer Type'
)]
[ValidateSet("BreadthFirst","DepthFirst")]
[string] $LoadBalancerType
)
try
{
Update-AzWvdHostPool -Name $HostPoolName -ResourceGroupName $ResourceGroupName -LoadBalancerType $LoadBalancerType | Out-Null
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
}
function Get-WVDHostpoolRegistrationToken () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the Hostpool Name'
)]
[string] $hostpoolName,
[Parameter(
Position=1,
Mandatory=$true,
HelpMessage='Enter the Resource Group name'
)]
[string] $resourceGroupName,
[Parameter(
Position=1,
Mandatory=$true,
HelpMessage='Enter the subscriptionID'
)]
[string] $subscriptionID
)
$registrationInfo = $null
try
{
$registrationInfo = Get-AzWvdRegistrationInfo -ResourceGroupName $resourceGroupName -HostPoolName $hostpoolName -SubscriptionId $subscriptionID
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
If ($registrationInfo.Count -gt 0)
{
return $($registrationInfo.Token)
}
}
function Connect-WVDServicePrincipalAccount () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the Service Principal credentials'
)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential] $SPCredentials,
[Parameter(
Position=1,
Mandatory=$true,
HelpMessage='Enter the Tenant ID'
)]
[ValidateNotNullOrEmpty()]
[string] $TenantID
)
try
{
$wvdAzSession = Connect-AzAccount -Credential $SPCredentials -Tenant $TenantID -ServicePrincipal -WarningAction SilentlyContinue
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
return $($wvdAzSession)
}
function Get-WVDHostPool () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the Subscription ID'
)]
[ValidateNotNullOrEmpty()]
[string] $SubscriptionID,
[Parameter(
Position=1,
Mandatory=$false,
HelpMessage='Enter the Hostpool Name'
)]
[string] $HostPoolName
)
If ([string]::IsNullOrEmpty($HostPoolName))
{
$HostPoolName = ""
}
try
{
[array]$wvdHostPoolCollection = Get-AzWvdHostPool -SubscriptionId $SubscriptionID -WarningAction SilentlyContinue |
ForEach-Object {
$wvdHostPool = $_
If ($wvdHostPool.Name -like "$HostPoolName*")
{
$wvdHostPool | Select Name,
ApplicationGroupReference,
@{Name='ApplicationGroupsCount'; Expression={$_.ApplicationGroupReference.Count}},
CustomRdpProperty,
Description,
FriendlyName,
HostPoolType,
Id,
LoadBalancerType,
Location,
MaxSessionLimit,
PersonalDesktopAssignmentType,
RegistrationInfoExpirationTime,
RegistrationInfoRegistrationTokenOperation,
RegistrationInfoToken,
Ring,
SsoContext,
VMTemplate,
ValidationEnvironment,
@{Name='ResourceGroup'; Expression={$_.Id.Split("/")[4]}}
}
}
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
return $wvdHostPoolCollection
}
function Update-WVDHostpool () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the Hostpool Name'
)]
[string] $HostpoolName,
[Parameter(
Position=1,
Mandatory=$true,
HelpMessage='Enter the Resource Group name'
)]
[string] $ResourceGroupName,
[Parameter(
Position=2,
Mandatory=$false,
HelpMessage='Select whether the Hostpool needs validation or not'
)]
[ValidateSet("Yes", "No")]
[string] $ValidationEnvironment,
[Parameter(
Position=3,
Mandatory=$false,
HelpMessage='Enter a friendly name for the Hostpool'
)]
[string] $FriendlyName,
[Parameter(
Position=4,
Mandatory=$false,
HelpMessage='Enter a description for the Hostpool'
)]
[string] $Description,
[Parameter(
Position=5,
Mandatory=$false,
HelpMessage='Enter the max session limit'
)]
[int] $MaxSessionLimit,
[Parameter(
Position=6,
Mandatory=$false,
HelpMessage='Enter the load balancing algorith'
)]
[ValidateSet("BreadthFirst","DepthFirst")]
[string] $LoadBalancingAlgorithm,
[Parameter(
Position=7,
Mandatory=$false,
HelpMessage='Enter the RDP properties as a semi-colon separated list'
)]
[string] $RDPProperty
)
$objParams = @{
"Name"=$HostpoolName;
"ResourceGroupName"=$ResourceGroupName;
}
If ($ValidationEnvironment)
{
$boolValidation = $false
If ($ValidationEnvironment -eq "Yes")
{
$boolValidation = $true
}
$objParams.Add("ValidationEnvironment",$boolValidation)
}
If (-not([string]::IsNullOrWhiteSpace($FriendlyName)))
{
$objParams.Add("FriendlyName",$FriendlyName)
}
If (-not([string]::IsNullOrWhiteSpace($Description)))
{
$objParams.Add("Description",$Description)
}
If ($MaxSessionLimit)
{
$objParams.Add("MaxSessionLimit",$MaxSessionLimit)
}
If (-not([string]::IsNullOrWhiteSpace($LoadBalancingAlgorithm)))
{
$objParams.Add("LoadBalancerType",$LoadBalancingAlgorithm)
}
If ($RDPProperty)
{
$objParams.Add("CustomRdpProperty",$RDPProperty)
}
try
{
Update-AzWvdHostPool @objParams | Out-Null
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
}
function Get-WVDHostPoolSessionHost () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the Subscription ID'
)]
[ValidateNotNullOrEmpty()]
[string] $SubscriptionID,
[Parameter(
Position=1,
Mandatory=$false,
HelpMessage='Enter the Hostpool Name'
)]
[string] $HostPoolName,
[Parameter(
Position=2,
Mandatory=$false,
HelpMessage='Enter the Session Host Name'
)]
[string] $SessionHostName
)
If ([string]::IsNullOrEmpty($HostPoolName))
{
$HostPoolName = ""
}
If ([string]::IsNullOrEmpty($SessionHostName))
{
$SessionHostName = ""
}
try
{
[array]$wvdSessionHostCollection = Get-AzWvdHostPool -SubscriptionId $SubscriptionID -WarningAction SilentlyContinue |
foreach {
$wvdHostPool = $_
If ($wvdHostPool.Name -like "$HostPoolName*")
{
Get-AzWvdSessionHost -HostPoolName $($wvdHostPool.Name) -ResourceGroupName $($wvdHostPool.Id.Split("/")[4]) |
foreach {
$wvdSessionHost = $_
If ($wvdSessionHost.Name.Split("/")[1] -like "$SessionHostName*")
{
$wvdSessionHost | Select @{Name='HostPoolName'; Expression={$wvdHostPool.Name}},
@{Name='SessionHostName'; Expression={$_.Name.Split("/")[1]}},
AgentVersion,
AllowNewSession,
@{Name='DrainMode'; Expression={if($_.AllowNewSession -eq "True"){return "Off"}else{return "On"}}},
AsignedUser,
LastHeartBeat,
LastUpdateTime,
OSVersion,
Session,
@{Name='ActiveSessions'; Expression={$_.Session}},
Status,
StatusTimestamp,
SxSStackVersion,
Type,
UpdateErrorMessage,
UpdateState,
@{Name='HostPoolApplicationGroupReference'; Expression={$wvdHostPool.ApplicationGroupReference}},
@{Name='HostPoolCustomRdpProperty'; Expression={$wvdHostPool.CustomRdpProperty}},
@{Name='HostPoolDescription'; Expression={$wvdHostPool.Description}},
@{Name='HostPoolFriendlyName'; Expression={$wvdHostPool.FriendlyName}},
@{Name='HostPoolType'; Expression={$wvdHostPool.HostPoolType}},
@{Name='HostPoolLoadBalancerType'; Expression={$wvdHostPool.LoadBalancerType}},
@{Name='HostpoolLocation'; Expression={$wvdHostPool.Location}},
@{Name='HostpoolMaxSessionLimit'; Expression={$wvdHostPool.MaxSessionLimit}},
@{Name='HostpoolResourceGroup'; Expression={$_.Id.Split("/")[4]}},
@{Name='HostPoolSsoContext'; Expression={$wvdHostPool.SsoContext}},
@{Name='HostPoolVMTemplate'; Expression={$wvdHostPool.VMTemplate}},
@{Name='HostPoolValidationEnvironment'; Expression={$wvdHostPool.ValidationEnvironment}}
}
}
}
}
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
return $wvdSessionHostCollection
}
function Get-WVDSessionHostHostPool () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='Enter the Subscription ID'
)]
[ValidateNotNullOrEmpty()]
[string] $SubscriptionID,
[Parameter(
Position=1,
Mandatory=$true,
HelpMessage='Enter the Session Host Name'
)]
[ValidateNotNullOrEmpty()]
[string] $SessionHostName
)
try
{
[array]$wvdSessionHostHostpoolCollection = Get-AzWvdHostPool -SubscriptionId $SubscriptionID -WarningAction SilentlyContinue |
foreach {
$wvdHostPool = $_
Get-AzWvdSessionHost -HostPoolName $($wvdHostPool.Name) -ResourceGroupName $($wvdHostPool.Id.Split("/")[4]) |
foreach {
$wvdSessionHost = $_
If ($wvdSessionHost.Name.Split("/")[1] -like "$SessionHostName*")
{
$wvdSessionHost | Select @{Name='SessionHostName'; Expression={$wvdSessionHost.Name.Split("/")[1]}},
@{Name='SessionHostId'; Expression={$wvdSessionHost.Id}},
@{Name='HostPoolName'; Expression={$wvdHostPool.Name}},
@{Name='HostPoolId'; Expression={$wvdHostPool.Id}},
@{Name='HostpoolResourceGroup'; Expression={$_.Id.Split("/")[4]}}
}
}
}
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
return $wvdSessionHostHostpoolCollection
}
[int]$outputWidth = 400
$PSWindow = (Get-Host).UI.RawUI
$WideDimensions = $PSWindow.BufferSize
$WideDimensions.Width = $outputWidth
$PSWindow.BufferSize = $WideDimensions
If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
$ErrorActionPreference = "Stop"
Write-Host ""
Invoke-CheckInstallAndImportPSModulePrereq -ModuleName "Az.Accounts"
Invoke-CheckInstallAndImportPSModulePrereq -ModuleName "Az.DesktopVirtualization"
If (Invoke-NETFrameworkCheck)
{
If ($azSPCredentials = Get-AzSPStoredCredentials)
{
try
{
$azSPSession = Connect-WVDServicePrincipalAccount -SPCredentials $azSPCredentials.spCreds -TenantID $($azSPCredentials.tenantID).ToString()
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
$azSubscription = Get-AzSubscription
try
{
$Id = (Get-WVDSessionHostHostPool -SubscriptionID $($azSubscription.Id) -SessionHostName $SessionHostName).HostPoolId
$wvdHostPoolName = $Id.Replace("ID=","").Split("/")[8]
If ([string]::IsNullOrEmpty($wvdHostPoolName))
{
$wvdHostPoolName = ""
}
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
try
{
[array]$hostPools = Get-WVDHostPool -SubscriptionID $($azSubscription.Id) -HostPoolName $wvdHostPoolName
}
catch
{
Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
Exit
}
If ($hostPools.Count -gt 0)
{
ForEach ($hostPool in $hostPools)
{
Update-WVDHostpool -HostpoolName $($hostPool.Name) -ResourceGroupName $hostPool.Id.Split("/")[4] -MaxSessionLimit $MaxSessionLimit
Write-Host ("Hostpool '$($hostPool.Name)' max session limit updated to: ") -ForegroundColor Yellow -NoNewline
Write-Host $($MaxSessionLimit) -ForegroundColor Cyan
}
}
}
else
{
Write-Warning "No Azure Credentials could be retrieved from the stored credentials file for this user."
}
}
Else
{
Write-Warning "The Az PowerShell Module, used by this Script Action, requires a minimum version of .NET Framework version 4.7.2. Please upgrade the .NET Framework version on this machine"
}
Disconnect-AzAccount | Out-Null