Virtualization, technology, and random rantings with a focus on Citrix and VMware.

Category: PowerShell Page 3 of 4

Looking For The Missing Plink: Using Plink To Get Information From ADC

Simple little script that you can modify the commands you want to run against a Citrix ADC. I’ve included using the “show ha node,” “show version,” and “show ip.” You can blank the commands and leave ” to have it skip the command. I ran into an issue with trying to send the password to the ADC so I had to use GetNetworkCredential().password on the $credential variable ($credential.GetNetworkCredential().password). This allowed the password to be passed without issue.

If you run the commands to query against the secondary node in an HA pair, you will get this error and it can be ignored: plink : Warning: You are connected to a secondary node; configuration changes made in this session will not be propagated to, or saved on, other nodes.(If you want to make changes via the commands, you will need to target the primary node)

# Script to use PuTTY Plink to access Citrix ADC to run commands remotely and get output to text file. This is using PowerShell ISE 5.1 and having PuTTY / Plink in the system path to being able to access.
$credential     = Get-Credential
$sessionHost    = "nodeip"
$pw             = $credential.GetNetworkCredential().password
$user           = $credential.UserName

$date           = Get-Date -Format MMddyyyy
$reportName     = "netscaler.txt"
$reportLocation = "c:\scripts\logs"
$report         = @()

# Commands
$cmd1           = 'show ha node'
$cmd2           = 'show version'
$cmd3           = 'show ip'

if($cmd1 -ne ''){

  $log1 = Echo Y | plink -ssh -l $user -pw $pw $sessionHost $cmd1
  
  $report += $log1
}

if($cmd2 -ne ''){

  $log2 = Echo Y | plink -ssh -l $user -pw $pw $sessionHost $cmd2

  $report += $log2
}

if($cmd3 -ne ''){

  $log3 = Echo Y | plink -ssh -l $user -pw $pw $sessionHost $cmd3

  $report += $log3
}

$report  | Out-File -FilePath "$reportLocation\$date-$reportName" -noclobber

Output example from Out-File.

You Wanted VDA Install With Applications!? New And Improved With Application Install On Base Domain Joined Server!

Powered By Philosoraptor Inc.

Building off of the VDA Upgrade script, this adds the additional components from a base server install. You will need to have the software packages in a folder, c:\software\ for this example. This script checks for Remote Desktop Services being installed and if not, installs Remote Desktop Services prior to kicking off the clean install of the Citrix VDA. I found this method worked best when trying to do a clean install. You can adjust the delay on the Add Minutes if you need more time before kicking off the base install. With SSD and decent procs, it shouldn’t take too long to install RDS and the Citrix VDA.

This batch file contains installs for: Acrobat DC; MS Edge; Google Chrome; Office 2016×86. The Install-Edge.ps1 is included below. You will need to create an MSP and config.xml for your Office configuration. Mode.reg is included as it sets the license mode to “Per User” for RDS Licensing mode. If you have any custom registry edits, you can included similar to mode.reg to import those registry settings as part of the install. You can modify the baseinstall.bat to add any programs you wish to add. Just make sure you can do the setup of the app in an unattended mode so that you can run it. When the install is complete, just remember to cleanup the installers in the c:\software folder to save space.

$vdilist = get-content c:\scripts\logs\servers.txt
$source = "\\placewherefilesare"
$dest = "c$\software\vdaupgrade"

  foreach($vdi in $vdilist){
    Write-Host "Working on $vdi"
    if (!(Test-Path -Path \\$vdi\c$\software\vdaupgrade)) {
        New-Item -ItemType Directory -Path \\$vdi\c$\software -Name vdaupgrade
        Copy-Item "\\$source\install.bat" -Destination \\$vdi\$dest -Force
        Copy-Item "\\$source\baseinstall.bat" -Destination \\$vdi\$dest -Force
        Copy-Item "\\$source\VDAServerSetup_1912.exe" -Destination \\$vdi\$dest -Force
    }
    else {
        Copy-Item "\\$source\install.bat" -Destination \\$vdi\$dest -Force
        Copy-Item "\\$source\baseinstall.bat" -Destination \\$vdi\$dest -Force
        Copy-Item "\\$source\VDAServerSetup_1912.exe" -Destination \\$vdi\$dest -Force
    }
  
    $rdsCheck = (invoke-command -ComputerName $vdilist -ScriptBlock {get-windowsfeature | where name -like "rds-rd-server" | select InstallState })

    if($rdsCheck.InstallState.value -eq "Available") {
        
        Copy-Item "\\$source\baseinstall.bat" -Destination \\$vdi\$dest -Force
        
        Invoke-Command -ComputerName $vdi -Scriptblock {
          $action = New-ScheduledTaskAction -Execute 'c:\software\vdaupgrade\install.bat'
          $trigger = New-ScheduledTaskTrigger -AtStartup 
          $principal = New-ScheduledTaskPrincipal  -RunLevel Highest -UserID "NT AUTHORITY\SYSTEM" -LogonType S4U
          $taskName = "VDAInstall"
          $taskDescription = "Citrix VDA Install"

        Register-ScheduledTask -Action $action -Trigger $trigger -Principal $principal -TaskName $taskName -Description $taskDescription
        }
        
        Invoke-Command -ComputerName $vdi -Scriptblock {
          $time = (Get-Date).AddMinutes(7)
          $action = New-ScheduledTaskAction -Execute 'c:\software\vdaupgrade\baseinstall.bat'
          $trigger = New-ScheduledTaskTrigger -Once -At $time
          $principal = New-ScheduledTaskPrincipal  -RunLevel Highest -UserID "NT AUTHORITY\SYSTEM" -LogonType S4U
          $taskName = "BaseInstall"
          $taskDescription = "Base Software Install"

        Register-ScheduledTask -Action $action -Trigger $trigger -Principal $principal -TaskName $taskName -Description $taskDescription 
        }

        Invoke-Command -ComputerName $vdi -ScriptBlock {
          Add-WindowsFeature rds-rd-server
          Restart-computer
        }
    }
   

  }
  

baseinstall.bat
 
@ECHO ON
change user /install
REM pause
timeout 5

net localgroup "Remote Desktop Users" /add "domain1\domain users" "domain2\domain users"
REM pause
timeout 5

REG IMPORT C:\software\mode.reg
REM pause
timeout 5

C:\software\AcrobatRdrDC\setup.exe /sAll /ini Setup.ini
REM pause
timeout 10

cd C:\software\MS-Edge
powershell -File ".\Install-Edge.ps1" -MSIName "MicrosoftEdgeEnterpriseX64.msi" -ChannelID "{56eb18f8-b008-4cbd-b6d2-8c97fe7e9062}" -DoAutoUpdate "True"
REM pause
timeout 5

msiexec.exe /i "C:\software\Google-Chrome\64B\GoogleChromeStandaloneEnterprise64.msi" /qn
REM pause
timeout 5

C:\software\Office\setup.exe /config .\ProPlus.WW\config.xml /adminfile CITRIX.MSP
REM pause
timeout 10

change user /execute
REM pause
timeout 5

C:\Windows\system32\schtasks.exe /delete /tn BaseInstall /f
C:\Windows\System32\timeout.exe /t 5
C:\Windows\System32\shutdown.exe /r /t 20 /f
del c:\software\vdaupgrade\baseinstall.bat /F
Install.bat
REM change port number in below command.
REM Use citrix vda command line helper tool from citrix. https://support.citrix.com/article/CTX234824 if needed
REM Install new VDA agent, delete files and scheduled tasks. Finally reboot.

C:\software\vdaupgrade\VDAServerSetup_1912.exe /masterpvsimage /virtualmachine /components VDA /controllers "DDC1 DDC2 DDC3" /noreboot /quiet /disableexperiencemetrics /enable_hdx_ports /enable_hdx_udp_ports /enable_real_time_transport /enable_remote_assistance
C:\Windows\system32\schtasks.exe /delete /tn VDAInstall /f
del c:\software\vdaupgrade\VDAServerSetup_1912.exe /F
C:\Windows\System32\timeout.exe /t 5
C:\Windows\System32\shutdown.exe /r /t 20 /f
del c:\software\vdaupgrade\install.bat /F

Install-Edge.ps1
param
(
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [ValidatePattern('^[a-zA-Z0-9]+.[m|M][s|S][i|I]$')]
    [string]$MSIName,
        
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [ValidatePattern('^{[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}}$')]
    [string]$ChannelID,

    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]$DoAutoUpdate
)

# See if autoupdate is false
if($DoAutoUpdate -eq $false)
{   
    # Registry value name is in the format "Update<{ChannelID}> where ChannelID is the GUID
    Set-Variable -Name "AutoUpdateValueName" -Value "Update$ChannelID" -Option Constant
    Set-Variable -Name "RegistryPath" -Value "HKLM:\SOFTWARE\Policies\Microsoft\EdgeUpdate" -Option Constant

    # Test if the registry key exists. If it doesn't, create it
    $EdgeUpdateRegKeyExists = Test-Path -Path $RegistryPath

    if (!$EdgeUpdateRegKeyExists)
    {
        New-Item -Path $RegistryPath
    }

    # See if the autoupdate value exists
    if (!(Get-ItemProperty -Path $RegistryPath -Name $AutoUpdateValueName -ErrorAction SilentlyContinue))
    {
        New-ItemProperty -Path $RegistryPath -Name $AutoUpdateValueName -Value 0 -PropertyType DWord
    }

   $AutoupdateValue = (Get-ItemProperty -Path $RegistryPath -Name $AutoUpdateValueName).$AutoUpdateValueName

   # If the value is not set to 0, auto update is not turned off, this is a failure
    if ($AutoupdateValue -ne 0)
    {
        Write-Host "Autoupdate value set incorrectly"
        return -1
    }
}
# Install the Edge MSI
return (Start-Process msiexec.exe -Wait -PassThru -ArgumentList "/i $MSIName /q").ExitCode


mode.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\RCM\Licensing Core]
"LicensingMode"=dword:00000004

You Got Some Of That HSD? : Hosted Shared Desktop Information Gathering Script

Cropped image to remove space from user list

There are times that you created some Hosted Shared Desktops. You published them and gave them out. You want to make sure you don’t duplicate your work and create another one when you may have one that is already available for a user group. How about a script to see what you got, what you named it, what Delivery Group is hosting it, what users are assigned to it, and what servers are assigned to it? I’ve got just the script for you!

# Script to get all Hosted Shared Desktops and user assignments using ISE 5.1 and Citrix Studio SDK installed locally.

asnp Citrix*

$date = Get-Date -Format MMddyyyy

$adminAddress = "ddc.fqdn:80"

$getHSD = Get-BrokerEntitlementPolicyRule -AdminAddress $adminAddress -MaxRecordCount 10000

$report = @()

foreach($hsd in $getHSD){
  $line                  = "" | Select-Object PublishedName, IncludedUsers, DeliveryGroup, ServerNames 
  $desktopGroup          = Get-BrokerDesktopGroup -AdminAddress $adminAddress -uid $hsd.DesktopGroupUid
  $machineNames          = Get-BrokerMachine -AdminAddress $adminAddress -DesktopGroupName $desktopGroup.Name
  
  $line.PublishedName    = $hsd.PublishedName
    
  if($hsd.IncludedUsers.Name -ne $null){
    
    $line.IncludedUsers  = ($hsd.IncludedUsers.Name -join ';').ToString()
    
  }
  
  elseif($hsd.IncludedUsers.Name -eq $null){
   
    $line.IncludedUsers  = "None Assigned"
    
  }
  
  if($desktopGroup.Name -ne $null){
   
    $line.DeliveryGroup  = $desktopGroup.Name -join ';'
    
  }
  
  elseif($desktopGroup.Name -eq $null){

    $line.DeliveryGroup  = "None Assigned"
    
  }
  
  if($machineNames.HostedMachineName -ne $null){
    
    $line.ServerNames    = $machineNames.HostedMachineName -join ';'
    
  }
  
  elseif($machineNames.HostedMachineName -eq $null){

    $line.ServerNames    = "None Assigned"

  }
  
  $report += $line

}

$report | Export-CSV c:\scripts\logs\$date-hostedshareddesktops.csv -Append -NoTypeInformation

Have You Tried A Good Old Fashioned Reboot? : Script To Get Citrix Delivery Group Reboot Schedules

Maybe when you are planning to do some upgrades but don’t remember when you set your reboot schedule times on your Delivery Groups. This will show you all the reboot schedules you have configured with server names. This also shows if you have Delivery Groups with no servers assigned to them, but had previously created a reboot schedule.

Update: I did run into an interesting thing with it. I had to define the if and elseif in order for it to evaluate as being true. Not sure what was going on with that.

# Script to get reboot schedules of Delivery Groups with times and server names using ISE 5.1 and Citrix Studio SDK installed locally.

asnp Citrix*

$date = Get-Date -Format MMddyyyy

$adminAddress = "ddc.fqdn:80"

$ctxRebootSchedule = Get-BrokerRebootScheduleV2 -AdminAddress $adminAddress -MaxRecordCount 100000

$report = @()

foreach($ctx in $ctxRebootSchedule) {
  $line                  = "" | Select-Object DesktopGroupName, ScheduleName, Enabled, Frequency, StartTime, RebootDuration, ServerCount, ServerNames
  $machineNames          = Get-BrokerMachine -AdminAddress $adminAddress -DesktopGroupName $ctx.DesktopGroupName
    
  $line.DesktopGroupName = $ctx.DesktopGroupName
  $line.ScheduleName     = $ctx.Name
  $line.Enabled          = $ctx.Enabled
  $line.Frequency        = $ctx.Frequency
  $line.StartTime        = $ctx.StartTime
  $line.RebootDuration   = $ctx.RebootDuration
  $line.ServerCount      = ($machineNames.HostedMachineName).count 
  
  if(($line.ServerCount) -ne 0){
   
    $line.ServerNames    = ($machineNames.HostedMachineName) -join ';'  
    
  }
  elseif(($line.ServerCount) -eq 0) {
    
    $line.ServerNames    = "None Assigned To DG"
    
  }
  
  $report += $line
  
  }
  
$report | export-csv c:\scripts\logs\$date-Citrix-Reboot-Schedule.csv -Append -NoTypeInformation

It Just Didn’t Register: Find Unregistered Machines

Just a quick little script you can add to your daily checks. This has been helpful for me to see if I have something that didn’t want to play nice BEFORE someone calls me and says it is broken. Good to have also if you have multiple hypervisor connections so you can see where at least it is running. Saves you looking around to figure out where it be.

# Get unregistered machine information

$adminAddress = "ddcaddress.fqdn:80"

$unregisteredMachines = get-brokermachine -AdminAddress $adminAddress -MaxRecordCount 25000| where registrationstate -eq "unregistered"
$report = @()
    foreach($unreg in $unregisteredMachines){

      $line = "" | select HostedMachineName, RegistrationState, AssociatedUserNames, DesktopGroupName, CatalogName, InMaintenanceMode, OSType, LastConnectionUser, LastConnectionTime, HypervisorConnectionName, SessionCount

      $line.HostedMachineName        = $unreg.HostedMachineName
      $line.RegistrationState        = $unreg.RegistrationState
      $line.AssociatedUserNames      = $unreg.AssociatedUserNames -join ','
      $line.DesktopGroupName         = $unreg.DesktopGroupName
      $line.CatalogName              = $unreg.CatalogName
      $line.InMaintenanceMode        = $unreg.InMaintenanceMode
      $line.OSType                   = $unreg.OSType
      $line.LastConnectionUser       = $unreg.LastConnectionUser
      $line.LastConnectionTime       = $unreg.LastConnectionTime
      $line.HypervisorConnectionName = $unreg.HypervisorConnectionName
      $line.SessionCount             = $unreg.SessionCount

      $report += $line

    }

    $report |format-table
    
    

Cross Domain User Add Between Domains With Two-Way Transitive Trust

Quick little script to add users from one domain to a group in another domain.

# Quick cross domain user add with 2 domains in the same forest with two-way transitive trusts using universal / domain local groups for access.
$userDomain  = "userdomain"
$groupDomain = "groupdomain"
$userName    = "useraccountname"
$groupName   = "groupname"
$User        = Get-ADUser -Identity $userName -Server $userDomain
$Group       = Get-ADGroup -Identity $groupName -Server $groupDomain

Add-ADGroupMember -Identity $Group -Members $User -Server $groupDomain

Table For One? : Making DHCP Reservations And Getting Reservations

Using DHCP reservations and you don’t want to have to use the MMC or remote into the server to make those or see what you have reserved? A quick bit of powershell to make and get those reservations at that exclusive table for you, with a nice little glass of CSV with it!

# A couple of commands to create and get reservations from a remote DHCP server. This requires Powershell Remoting, firewall to open to server, admin rights to server, DhcpServer PS module, and used in ISE 5.1.

# DHCP Remote reservation
$sb = {
  $scopeID = "IPsubnet"
  $clientMac = "clientmacaddress"
  $clientName = "clientcomputername"
  $clientIP = "reserveIPaddress"


  Add-DhcpServerv4Reservation -ScopeId $scopeID -Name $clientName -IPAddress $clientIP  -ClientId $clientMac 
 }
  
$dhcpServer = "dhcpservername.fqdn"

Invoke-Command -ComputerName $dhcpServer -ScriptBlock $sb

# Get Remote Reservations
$report =@()

$sb = {
  $scopeID = "IPsubnet"
  
  $output = Get-DhcpServerv4Reservation -ScopeId $scopeID | Select-Object Name, IPAddress, ClientID
  
  $report += $output
}

$dhcpServer = "dhcpservername.fqdn"

Invoke-Command -ComputerName $dhcpServer -ScriptBlock $sb

$report | export-csv c:\scripts\logs\dhcpreservations.csv -Append -NoTypeInformation

VDA Upgrade… Oh Yeah!

So you want to upgrade some VDAs?! Yeah you do! I’ve done some edits on other scripts. I’m also working out for additional revisions to check for present sessions. This targets the Server VDA version. You can edit the name to VDAWorkstationSetup_1912.exe in the script and accompanying files to upgrade on VDI as well. The base for this is listed below in the script from ChayScripts. You can also change the install switches and copy that into the install.bat file if you need different options (https://www.citrix.com/blogs/2018/01/08/citrix-vda-commandline-helper-tool/)

For the contents of the ServerNameTextFile, you will need FQDN of the servers for the invoke commands. This splits the FQDN off for the powercli aspect to snapshot the server.

# Base VDA removal / reinstall script. This uses Powershell ISE on 5.1 with needing to be ran with account with rights in VMware and on the target server as well as the module for PowerCLI. 
# Modified from https://github.com/ChayScripts/Citrix-VDA-Upgrade-Scripts scripts. Added snapshot for VMware and a report of previous versions.

$vdalist = get-content "C:\pathtotextfilewithfqdnservernames.txt"
$source = "placewherefilesarestored\vdaupgrade"
$dest = "c$\software\vdaupgrade"
$date = Get-Date -Format MMddyyyy
$report = @()

  foreach ($vda in $vdalist) {
    $line = "" | Select Name, PreviousVersion, SnapShot
    $vda1 = ($vda.split('.')[0])
    $line.Name = "$vda"
    $line.PreviousVersion = (invoke-command -ComputerName $vda -ScriptBlock {Get-WmiObject -Class Win32_Product | where name -match "Citrix Virtual Desktop Agent - x64" | select Name,Version}).Version
    $snapshot = (get-vm $vda1  | new-snapshot -name $date-$vda1-preupgrade)
    $line.SnapShot = (get-vm $vda1 | get-snapshot).name
    Write-Host "Working on $vda"
    if (!(Test-Path -Path \\$vda\c$\software\vdaupgrade)) {
        New-Item -ItemType Directory -Path \\$vda\c$\software -Name vdaupgrade
        Copy-Item "\\$source\install.bat" -Destination \\$vda\$dest -Force
        Copy-Item "\\$source\remove.bat" -Destination \\$vda\$dest -Force
        Copy-Item "\\$source\VDAServerSetup_1912.exe" -Destination \\$vda\$dest -Force
    }
    else {
        Copy-Item "\\$source\install.bat" -Destination \\$vda\$dest -Force
        Copy-Item "\\$source\remove.bat" -Destination \\$vda\$dest -Force
        Copy-Item "\\$source\VDAServerSetup_1912.exe" -Destination \\$vda\$dest -Force

    }
    Invoke-Command -ComputerName $vda -Scriptblock {
        $time = (Get-Date).AddMinutes(3)
        $action = New-ScheduledTaskAction -Execute 'c:\software\vdaupgrade\remove.bat'
        $trigger = New-ScheduledTaskTrigger -Once -At $time
        $principal = New-ScheduledTaskPrincipal  -RunLevel Highest -UserID "NT AUTHORITY\SYSTEM" -LogonType S4U

        Register-ScheduledTask -Action $action -Trigger $trigger -Principal $principal -TaskName "VDAUninstall" -Description "Citrix VDA Uninstall" 
    }

    Invoke-Command -ComputerName $vda -Scriptblock {
        $action = New-ScheduledTaskAction -Execute 'c:\software\vdaupgrade\install.bat'
        $trigger = New-ScheduledTaskTrigger -AtStartup 
        $principal = New-ScheduledTaskPrincipal  -RunLevel Highest -UserID "NT AUTHORITY\SYSTEM" -LogonType S4U

        Register-ScheduledTask -Action $action -Trigger $trigger -Principal $principal -TaskName "VDAInstall" -Description "Citrix VDA Install" 

    } 

    $report += $line

  }

$report | export-csv c:\scripts\logs\$date-vda-upgrades.csv -Append -NoTypeInformation

You will need to create an install.bat and remove.bat file with the contents below.

Install.bat
REM change port number in below command.
REM Use citrix vda command line helper tool from citrix. https://support.citrix.com/article/CTX234824 if needed
REM Install new VDA agent, delete files and scheduled tasks. Finally reboot.

C:\software\vdaupgrade\VDAServerSetup_1912.exe /masterpvsimage /virtualmachine /components VDA /controllers "DDC1 DDC2 DDC3" /noreboot /quiet /disableexperiencemetrics /enable_hdx_ports /enable_hdx_udp_ports /enable_real_time_transport /enable_remote_assistance
C:\Windows\system32\schtasks.exe /delete /tn VDAInstall /f
C:\Windows\system32\schtasks.exe /delete /tn VDAUninstall /f
del c:\software\vdaupgrade\remove.bat /F
del c:\software\vdaupgrade\VDAServerSetup_1912.exe /F
C:\Windows\System32\timeout.exe /t 5
C:\Windows\System32\shutdown.exe /r /t 20 /f
del c:\software\vdaupgrade\install.bat /F

Remove.bat
"C:\Program Files\Citrix\XenDesktopVdaSetup\XenDesktopVdaSetup.exe" /REMOVEALL /QUIET /NOREBOOT
C:\Windows\System32\shutdown.exe /r /t 5 /f

User Count Breakdown By Delivery Group

This script allows you to get the list of Delivery Groups by “SessionSupport” type and reports back “MultiSession” as “CitrixApp” and SingleSession as “VDI.”

# Script to get MultiSession and SingleSession counts from Delivery Groups with a non-zero user count. This sorts by MultiSession, then SingleSession. This was ran on a machine with Citrix Studio SDK
# installed. This was tested with CVAD 1912 LTSR.
asnp Citrix*
$adminAddress = "deliverycontroller.fqdn"

$getDG = Get-BrokerDesktopGroup -AdminAddress $adminAddress -MaxRecordCount 100000 | Select-Object Name, SessionSupport | Get-Unique -AsString

$report = @()

foreach($dg in $getDG) {
  
  $line = "" | Select DeliveryGroupName, UserCount, SessionSupport
  $userCount = (Get-BrokerSession -AdminAddress $adminAddress -DesktopGroupName $dg.name -MaxRecordCount 100000 | Select-Object BrokeringUserName).count
  
  if ($userCount -ne '0' -and $userCount -ne $null){
    $line.DeliveryGroupName = $dg.name
    $line.UserCount         = $userCount
    
    if($dg.SessionSupport -eq "SingleSession") {
      $line.SessionSupport  = 'VDI'
    }
    else{
      $line.SessionSupport  = 'CitrixApp'
    }
    $report += $line
  }
  }
  
$citrixAppTotal = (($report | Where-Object SessionSupport -eq "CitrixApp"| Select-Object UserCount).UserCount| Measure-Object -Sum).Sum
$citrixVDITotal = (($report | Where-Object SessionSupport -eq "VDI"| Select-Object UserCount).UserCount| Measure-Object -Sum).Sum
$appTotal = write-output "`r`nTotal Citrix App users: $citrixAppTotal"
$vdiTotal = write-output "Total VDI Users: $citrixVDITotal"
  
$report += $apptotal
$report += $vdiTotal
  

$report | sort SessionSupport, @{Expression="UserCount";Descending=$true}|Format-Table




If You Could Get Those User Counts Today, That Would Be Great.

So you like your reports fresh off the press!? We do too! A quick little script to grab a daily report, running as a scheduled task, and send out some user information. Just in case someone likes to know how many people using the platform.

Gets you this nice little emailed report:

# Get Citrix Daily Users reporting. This requires Powershell, Studio SDK, access rights to the license server.
# This gets the unique users, current sessions, connected and disconnected VDI, and license counts.
# This was tested with 11.17.2.0 build 37000 License Server with 1 license file. Running this as a scheduled task you will need an AD account
# to run this under. A service account works well for this.

asnp Citrix*

$adminAddress = "deliverycontroller.fqdn:80"

$licenseServerAddress = "https://licenseserveraddress:8083"

$licenseServerName = "licenseserver.fqdn"

$cert = Get-LicCertificate -AdminAddress $licenseServerAddress

# This section was gotten from https://lalmohan.co.nz/2015/10/09/citrix-license-usage-monitoring-using-powershell/ and modified for my use.
$licenseInfo = Get-WmiObject -Namespace "ROOT\CitrixLicensing" Citrix_GT_License_Pool -ComputerName $licenseServerName
$licenseModel = ($LicenseInfo | Where-Object{($_.pld -like "XDT*") -or ($_.pld -like "MPS*")}|Select-Object pld -unique).pld
$totalLicenses = ($licenseInfo | Where-Object PLD -like "$licenseModel" | Select-Object count).count
# End section.

# This section was assisted from http://notesofascripter.com and https://www.linkedin.com/in/douglas-ruehrwein-56835869/
# This will run differently for Monday since you are getting data from the last 24 hours and weekends are usually lower use.
$Today = Get-Date
if(($Today.DayOfWeek) -eq 'Monday')
{$when = $Today.AddDays(-3)}
else{$when = $Today.AddDays(-1)}
# End section.

$connections = Get-BrokerConnectionLog -AdminAddress $adminAddress -Filter {BrokeringTime -gt $when} -MaxRecordCount 100000 | Select-Object BrokeringUserName

$licenseCount = (Get-LicUsageDetails -AdminAddress $licenseServerAddress -ProductEditionModel $licenseModel -CertHash $cert.CertHash).count


$ctxUsers = [PSCustomObject] @{

  UniqueCitrixUsers      = ($connections.BrokeringUserName | Select-Object -Unique).count
  CurrentSessions        = (Get-BrokerSession -AdminAddress $adminAddress -MaxRecordCount 100000 | Select-Object BrokeringUserName).count
  CitrixVDIConnected     = (Get-BrokerSession -AdminAddress $adminAddress -MaxRecordCount 100000 | Where-Object SessionSupport -eq "SingleSession" | Where-Object SessionState -eq "Active").count
  CitrixVDIDisconnected  = (Get-BrokerSession -AdminAddress $adminAddress -MaxRecordCount 100000 | Where-Object SessionSupport -eq "SingleSession" | Where-Object SessionState -eq "Disconnected").count
  CitrixLicensesUsed     = $licenseCount
  CitrixTotalLicenses    = $totalLicenses
  CtxLicenseFreePercent  = ((($totalLicenses - $licenseCount) / $totalLicenses ) * 100).ToString("#.##")

}

# HTML Formatting
$style = "<style>BODY{font-family: Arial; font-size: 10pt;}"
$style = $style + "TABLE{border: 1px solid black; border-collapse: collapse;}"
$style = $style + "TH{border: 1px solid black; background: #dddddd; padding: 5px; }"
$style = $style + "TD{border: 1px solid black; padding: 5px; }"
$style = $style + "</style>"

# HTML Email Body
$body = $ctxUsers | ConvertTo-Html -Head $style
 

# Generates email with attachment
$date = Get-date -Format "MM-dd-yyyy"
$emailFrom = "someemail@place.com"
$emailto = "someemail@place.com"
#$emailtwo = "someemail@place.com"
#$emailCC = "someemail@place.com"
$subject="Daily Citrix User Report | $date" 
$email = New-object System.Net.Mail.MailMessage 
$email.to.Add($emailto)
#$email.to.Add($emailtwo)
#$email.CC.Add($emailCC)
$Email.From = New-Object system.net.Mail.MailAddress $emailFrom
$email.Subject = $subject
$email.IsBodyHtml = $true
#$attachment = $Reports[1]
#$email.Attachments.add($attachment)
$email.body = $body
 

$smtpserver="stmp.someplace.com" 
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($email)





Page 3 of 4

Powered by WordPress & Theme by Anders Norén