Posts RSS Comments RSS 117 Posts and 170 Comments till now

Get-CitrixApplication (Playing Around Series)

Here is a quick demo of getting a Citrix Application and playing with its properties.

Best Viewed Full Screen
Get the Flash Player to see this player.

Demo File

  1. #
  2. # First we need to create the MFCOM Object
  3. #
  4. $mfapp = new-object -com MetaFrameCom.MetaFrameApplication
  5. #
  6. # To initialize we need to pass the app we want to accesss
  7. #
  8. $mfapp.Initialize(3,"Applications\Powershell")
  9. #
  10. # With Applications we need to load the data
  11. #
  12. $mfapp.loaddata(1)
  13. #
  14. # Lets see what we have
  15. #
  16. $mfapp | Get-Member -type Properties
  17. #
  18. # Lets look at Users and Groups
  19. #
  20. $mfapp | select Users,Groups
  21. #
  22. # How bout Servers
  23. #
  24. $mfapp.Servers | Select ServerName
  25. #
  26. # Sessions?
  27. #
  28. $mfApp.Sessions | ft SessionID,AppName,ClientAddress,ClientHRes,ClientVRes -auto

Get-CitrixFarm (Playing Around Series)

I wanted to show how EASY it is to play with Citrix MFCom so here is a little video.

I also want to note how most of the properties (like Servers,Applications,Zones) all return objects that have their own properties and methods. So you could very easily have these lines in your profile and always have everything just sitting there waiting to be used.

  1. $farm = New-Object -Com ‘MetaframeCOM.MetaFrameFarm’
  2. $farm.Initialize(1)
  3. Write-Host "Loaded Farm Info from $($farm.FarmName)

Best Viewed Full Screen
Get the Flash Player to see this player.

Demo File

  1. # Get Citrix Farm Object
  2. #
  3. $farm = New-Object -Com ‘MetaframeCOM.MetaFrameFarm’
  4. #
  5. # Initialize Farm
  6. #
  7. $farm.Initialize(1)
  8. #
  9. # Now that we have are farm. Lets make sure we have the one we want by Getting the FarmName
  10. $Farm.FarmName
  11. #
  12. # Lets see what we have to play with
  13. #
  14. $farm | Get-Member -type Properties
  15. #
  16. #
  17. # We have the Farm we want. Some of the Info we want is Admins. So lets Start there
  18. #
  19. $farm.Admins
  20. #
  21. # To View just a list
  22. #
  23. $farm.Admins | Select FriendlyName
  24. #
  25. # Lets see what Applications we have
  26. #
  27. $farm.Applications | ft BrowserName,ParentFolderDN
  28. #
  29. # To View the Servers
  30. #
  31. $farm.Servers | ft ServerName,IPAddress,SessionCount
  32. #
  33. # How bout Sessions?
  34. $farm.Sessions
  35. #
  36. # Lets look at Print Drivers we Have installed
  37. #
  38. $farm.Drivers
  39. #
  40. # If you have multiple Zones you can get the Names Servers and DataCollector for the Zone
  41. $farm.Zones
  42. #

Get-CitrixServer (Playing Around Series)

This is a quick run through a MFCOm Citrix Server Object

Best Viewed Full Screen
Get the Flash Player to see this player.

Demo File

  1. #
  2. # We start by creating a Server Object
  3. #
  4. $mfsrv = New-Object -ComObject MetaFrameCOM.MetaFrameServer
  5. #
  6. # Initializing Server
  7. #
  8. $mfsrv.Initialize(6,$ENV:ComputerName)
  9. #
  10. # Now we have are server… Lets see what we have to play with
  11. #
  12. $mfsrv | Get-Member -type Properties
  13. #
  14. # Lets start by looking at the current sessions on the server
  15. #
  16. $mfsrv.Sessions | ft SessionID,AppName,ClientAddress,ClientHRes,ClientVRes -auto
  17. #
  18. # What about what Zone it is in?
  19. #
  20. $mfsrv.ZoneName
  21. #
  22. # Printers?
  23. #
  24. $mfsrv.Printers
  25. #
  26. # Lets see what Processes are running
  27. #
  28. $mfsrv.Processes | ft SessionID,ProcessID,UserName,ProcessState -auto
  29. #
  30. # A common task is Server Load
  31. #
  32. $mfsrv.WinServerObject.ServerLoad
  33. #
  34. # Last (and perhaps most important) What applications?
  35. #
  36. $mfsrv.Applications | ft BrowserName,ParentFolderDN

Powershell and MFCom (Citrix takes more steps)

Vishal Ganeriwala is hosting a webinar on the 29th of April on Powershell and MFCom. This is just another example of Citrix actively embracing Powershell.

http://community.citrix.com/blogs/citrite/vishalg/2008/04/21/Free+Managing+Citrix+Servers+via+PowerShell+and+MFCOM+webinar

It will cover some basic Powershell for those who do not have much XP with Powershell.
- What is an Object
- Properties
- Methods
- New-Object (-ComObject)

It will also cover how to create a Citrix Farm Object in Powershell and some of the interactive nature of Powershell
- Getting Farm Properties
- Getting Applications
- Getting Servers
- Getting Sessions

Example
- Get Current Sessions Client Resolution

Get-CitrixAppServer.ps1 (Citrix Top 10)

This is pretty simple script. It is actually just an adaption from my Get-CitrixApplication.ps1 script posted at the bottom. There is a moment in time when you start thinking in terms of objects and stop thinking in terms of text output you are looking for.

This will make a huge difference in productivity and take you from constantly writing scripts to interactively getting the information you are after, but until you make the transition I will continue to provide scripts that do both :)

  1. # Get-CitrixAppServer.ps1
  2. # Brandon Shell [MVP]
  3. # www.bsonposh.com
  4. # Gets All the Servers for Specific App
  5. Param($app)
  6. $mfApp = New-Object -ComObject MetaFrameCOM.MetaFrameApplication
  7. $mfApp.Initialize(3,$app)
  8. $mfApp.LoadData(1)
  9. $mfApp.Servers | %{$_.ServerName}

Here is the script that I use to return an Application object.

  1. # Get-CitrixApplication.ps1
  2. # Brandon Shell [MVP]
  3. # www.bsonposh.com
  4. # Gets a Citrix Application Object.
  5. Param($app)
  6. $mfApp = New-Object -ComObject MetaFrameCOM.MetaFrameApplication
  7. $mfApp.Initialize(3,$app)
  8. $mfApp.LoadData(1)
  9. $mfApp

Then from the commandline I would just do this
PS> Get-CitrixApplication.ps1 “Applications\MyApp1″ | %{$_.Servers} | %{$_.ServerName}

While this looks more complicated it is more versatile and easy to change. Lets say I want current User for this app instead.
PS> Get-CitrixApplication.ps1 “Applications\MyApp1″ | %{$_.Sessions} | %{$_.UserName}

Find-CitrixUser.ps1 (Citrix Top 10)

This is another script that I can use quite often. It is a simple script that queries all the sessions and returns the ones where the User matches. I made the User a RegEx search so you could do multiple users.

Name: Find-CitrixUser.ps1
Purpose: Finds where the user(s) are and outputs session info

  1. # Find-CitrixUser.ps1
  2. # Brandon Shell [MVP]
  3. # www.bsonposh.com
  4. # Finds where the user(s) are and out puts session info
  5. Param($user=".*",[switch]$help)
  6. function HelpMe{
  7.     Write-Host
  8.     Write-Host " Find-CitrixUser.ps1:" -fore Green
  9.     Write-Host "   Finds where the user(s) are and out puts session info"
  10.     Write-Host
  11.     Write-Host " Parameters:" -fore Green
  12.     Write-Host "   -User                  : Optional. Name of the User or RegEx (Default is all users)"
  13.     Write-Host "   -Help                  : Optional. Displays This"
  14.     Write-Host
  15.     Write-Host " Examples:" -fore Green
  16.     Write-Host "   Finds User TestMe and outputs and returns ServerName,ClientAddress, and SessionID" -fore White
  17.     Write-Host "     .\Find-CitrixUser.ps1 | ft ServerName,ClientAddress,SessionID " -fore Yellow
  18.     Write-Host
  19.     Write-Host "   Finds all Users who start with ‘Sales’ and returns UserName,ServerName, and SessionID"  -fore White
  20.     Write-Host "     .\Find-CitrixUser.ps1 `"^sales`" | ft UserName,ServerName,SessionID " -fore Yellow
  21.     Write-Host
  22.     Write-Host "   To View All properties availiable." -fore White
  23.     Write-Host "     .\Find-CitrixUser.ps1 <username> | Get-Member" -fore Yellow
  24.     Write-Host
  25. }
  26.  
  27. # Check for the Help or if
  28. if($help){helpme;Write-Host;return}
  29.  
  30. # Code to Get the Farm and Initialize
  31. $farm = New-Object -com "MetaframeCOM.MetaFrameFarm"
  32. $farm.Initialize(1)
  33.  
  34. # Get the Sessions and Parse for Users who match
  35. $farm.Sessions | ?{$_.UserName -match $user}

Find-CitrixIdleUser.ps1 (Citrix Top 10)

This is one of the more useful scripts (at least for me.) It will query the farm and tell you all the user who have exceeded the idle time specified. I also combined another script that logged off users.

Name: Find-CitrixIdleUser.ps1
Purpose: Finds users with idle time greater than value passed and logs them off if -logoff is passed

  1. # Find-CitrixIdleUser.ps1
  2. # Brandon Shell [MVP]
  3. # www.bsonposh.com
  4. # Finds users with idle time greater than value passed
  5. Param($time,[switch]$day,[switch]$hour,[switch]$minute,[switch]$logoff,[switch]$verbose,[switch]$help)
  6. function HelpMe{
  7.     Write-Host
  8.     Write-Host " Find-CitrixIdleUser.ps1:" -fore Green
  9.     Write-Host "   Finds users with idle time greater than value passed"
  10.     Write-Host
  11.     Write-Host " Parameters:" -fore Green
  12.     Write-Host "   -Time                  : Optional. Server to Get Print Info From "
  13.     Write-Host "   -Day                   : Optional. Checks Days of Idle Time "
  14.     Write-Host "   -Hour                  : Optional. Checks Hours of Idle Time (Default)"
  15.     Write-Host "   -Minute                : Optional. Checks Minutes of Idle Time"
  16.     Write-Host "   -Logoff                : Optional. Logs User off if Idle Time exceeds Time"
  17.     Write-Host "   -Verbose               : Optional. Show Verbose Output"
  18.     Write-Host "   -Help                  : Optional. Displays This"
  19.     Write-Host
  20.     Write-Host " Examples:" -fore Green
  21.     Write-Host "   Finds Users who have been idle 2 hours and return AppName, UserName, SessionID, and ClientName" -fore White
  22.     Write-Host "     Find-CitrixIdleUser.ps1 2 -hour | ft AppName,UserName,SessionID,ClientName -auto" -fore Yellow
  23.     Write-Host
  24.     Write-Host "   Finds Users who have been idle 2 hours and Logs them Off" -fore White
  25.     Write-Host "     Find-CitrixIdleUser.ps1 2 -hour -logoff" -fore Yellow
  26.     Write-Host
  27. }
  28. if($verbose){$verbosepreference = "Continue"}
  29. Write-Host
  30. if(!$time -or $help){helpme;Write-Host;Return}
  31.  
  32. # Get Citrix Farm Object
  33. Write-Verbose " - Creating MFFarm Object"
  34. $farm = new-Object -com "MetaframeCOM.MetaframeFarm"
  35. $farm.Initialize(1)
  36.  
  37. # Parse Sessions
  38. Write-Verbose " - Parsing Sessions. Total of [$($farm.Sessions.count)] Sessions"
  39. foreach($session in $farm.Sessions)
  40. {
  41.     Write-Verbose "   - Processing Session ID [$($Session.SessionId)]"
  42.     $shouldLogOff = $false
  43.  
  44.     # Getting Citrix Session Idle Time and Convert to System.DateTime
  45.     Write-Verbose "   - Getting LastInputTime"
  46.     $ctxDate = $session.LastInputTime(1)
  47.     Write-Verbose "   - Checking if idle time is -gt 0"
  48.     if(($ctxDate.HighPart -ne 0) -and ($ctxDate.LowPart -ne 0))
  49.     {
  50.         $date = "{0,4}{1,2:00}{2,2:00}{3,2:00}{4,2:00}" -f $ctxDate.year,$ctxDate.Month,$ctxDate.Day,$ctxDate.Hour,$ctxDate.Minute
  51.         Write-Verbose "   - Converted LastInputTime to [$date]"
  52.         $SessionIdleTime = [system.DateTime]::ParseExact($date,‘yyyyMMddHHmm’,$null)
  53.  
  54.         # Get Current Time in System.DateTime
  55.         Write-Verbose "   - Getting Current Date"
  56.         $now = Get-Date
  57.         Write-Verbose "   - Current Date is [$now]"
  58.  
  59.         # Find Difference
  60.         Write-Verbose "   + Getting Time Difference"
  61.         $diff = $now - $SessionIdleTime
  62.         Write-Verbose "     - Found Days [$($diff.TotalDays)] Hours [$($diff.Totalhours)] Minutes [$($diff.TotalMinutes)]"
  63.  
  64.         # Output Sessions that match
  65.         if($day)   {    if($diff.TotalDays    -gt $time)    {$session;$shouldLogOff = $true}  }
  66.         if($hour)  {    if($diff.Totalhours   -gt $time)    {$session;$shouldLogOff = $true}  }
  67.         if($minute){    if($diff.TotalMinutes -gt $time)    {$session;$shouldLogOff = $true}  }
  68.  
  69.         Write-Verbose "     - Set `$shouldLogOff to [$shouldLogOff]"
  70.  
  71.         # Logging Off User
  72.         if($logoff -and $shouldLogOff)
  73.         {
  74.             Write-Verbose "   - Logging Off Session ID [$($Session.SessionId)]"
  75.             $session.Logoff($false)
  76.         }
  77.     }
  78.     else
  79.     {
  80.         Write-Verbose "   - Session ID [$($Session.SessionId)] NOT Idle"
  81.     }
  82.     Write-Host
  83. }

Get-CitrixSessionUser.ps1 (Citrix Top 10)

One of the script I was asked to convert was a script to output all the Users and the Client IP.

This is what I came up with

Name: Get-CitrixSessionUser.ps1
Purpose: List ClientAddress and UserName for each Session

  1. # Get-CitrixSessionUser.ps1
  2. # Brandon Shell [MVP]
  3. # www.bsonposh.com
  4. # List ClientAddress and UserName for each Session
  5.  
  6. $farm = new-Object -com "MetaframeCOM.MetaframeFarm"
  7. $farm.Initialize(1)
  8. $farm.Sessions | Format-Table UserName,ClientAddress

After I did this… I stopped and actually thought about what I was doing. What is the point? What would someone use this for? It seemed to me that a simpler script that was more flexible would not only meet the original goal, but expand it significantly. It comes back to the object nature of Powershell. I needed to stop thinking strings and start thinking objects. Using the following script not only accomplishes the same goal to get UserName and ClientAddress, but also expands it to add the following:

AAName
AAType
AccessSessionGuid
Applications
AppliedPolicy
AppName
AverageLatency
BandwidthCap
BytesRcvdPostExpansion
BytesRcvdPreExpansion
BytesSentPostCompression
BytesSentPreCompression
ClientAddress
ClientAddrFamily
ClientBuffers
ClientBuild
ClientCacheDisk
ClientCacheLowMem
ClientCacheTiny
ClientCacheXms
ClientColorDepth
ClientDimBitmapMin
ClientDimCacheSize
ClientDimVersion
ClientDirectory
ClientEncryption
ClientHardwareID
ClientHRes
ClientID
ClientLicense
ClientModemName
ClientModules
ClientName
ClientProductID
ClientProductIDValue
ClientVRes
DeviceID
ICABufLen
InputSpeed
LastLatency
LatencyDeviation
OutputSpeed
Processes
ProtocolType
ServerBuffers
ServerName
SessionID
SessionName
SessionState
SmartAccessFilters
UserName
VIPAddress
VirtualChannels

  1. # Get-CitrixSession.ps1
  2. # Brandon Shell [MVP]
  3. # www.bsonposh.com
  4. # Gets all the Sessions for a Farm
  5.  
  6. $farm = new-Object -com "MetaframeCOM.MetaframeFarm"
  7. $farm.Initialize(1)
  8. $farm.Sessions

How to Manage Multiple Citrix Farms

Chris left a comment on Powershelling Citrix (The Good, Bad, and The Code)

Here is a function that returns a farm object for Server that is passed.

  1. function Get-CitrixFarm {
  2.    Param([string]$server)
  3.    $type = [system.Type]::GetTypeFromProgID("MetaframeCOM.MetaFrameFarm",$server)
  4.    $farm = [system.Activator]::CreateInstance($type)
  5.    $farm.Initialize(1)
  6.    return $farm
  7. }
  8.  

Here is an example to find a Server that a User is on.

  1. function Find-CitrixUser {
  2.     Param([string]$user,[string]$server,[string]$domain,[switch]$verbose)
  3.     $type = [system.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeUser",$server)
  4.     $mfuser = [system.Activator]::CreateInstance($type)
  5.     $mfuser.Initialize(1,$domain,1,$user)
  6.     Write-Host
  7.     Write-Host "User: $($mfuser.UserName) found on the Following:"
  8.     foreach ($s in $mfuser.Sessions)
  9.     {
  10.         if($verbose)
  11.         {
  12.             Write-Host
  13.             Write-Host "$($s.ServerName)"
  14.             Write-Host "-=-=-=-=-=-"
  15.             Write-Host "AppName          : $($s.AppName)" -foregroundcolor yellow
  16.             Write-Host "SessionName      : $($s.SessionName)" -foregroundcolor yellow
  17.             Write-Host "SessionID        : $($s.SessionID)" -foregroundcolor yellow
  18.             Write-Host "ClientAddress    : $($s.ClientAddress)" -foregroundcolor yellow
  19.             Write-Host "ClientEncryption : $($s.ClientEncryption)" -foregroundcolor yellow
  20.             Write-Host
  21.             Write-Host "Processes"
  22.             Write-Host "========="
  23.             foreach ($proc in $s.Processes)
  24.             {
  25.                 Write-Host $proc.ProcessName -foregroundcolor Green
  26.             }
  27.             Write-host
  28.         }
  29.         else
  30.         {
  31.             write-Host "   -> $($s.ServerName)"
  32.         }
  33.     }
  34. }