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-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}

Citrix Policies and Powershell (Double the Pleasure!)

I notice there was entry on Brian Madden forums about creating Citrix Policies. http://www.brianmadden.com/Forum/Topic/97139

I decided to spend a little time looking at this from a script perspective and here are some examples of dealing with Citrix Policies that I came up with.

Just a FYI
I hear tell there will be some Citrix CMDLets coming very soon that will make working with Citrix amazingly simple (which will include an import/export Citrix policy cmdlets.) I cannot tell you how revolutionary this will be for your typical Citrix Admin.

You can find the Citrix Enums here
http://bsonposh.com/modules/wordpress/?p=62

Script To Get Citrix Policy

  1. # Get-CitrixPolicy.ps1
  2. Param($Server,$PolicyName = ".*")
  3.  
  4. # Enums in Use
  5. $MetaFrameUnknownObject = 0
  6. $MetaFrameWinFarmObject = 1
  7.  
  8. # Getting Farm Object
  9. $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeFarm",$Server)
  10. $mfarm = [system.Activator]::CreateInstance($type)
  11. $mfarm.Initialize($MetaFrameWinFarmObject)
  12.  
  13. # Getting Policies that Match Name and Loading Data
  14. $pol = $mfarm.policies($MetaFrameUnknownObject) | ?{$_.Name -match $PolicyName}
  15. $pol | %{$_.LoadData($true)}
  16. $pol

Script To Create a New Citrix Policy

  1. # New-CitrixPolicy.ps1
  2. Param($Server,$PolicyName,$PolicyDescription)
  3. if(!$PolicyDescription){$PolicyDescription=$PolicyName)
  4. $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeFarm",$Server)
  5. $mfarm = [system.Activator]::CreateInstance($type)
  6. $mfarm.Initialize(1)
  7. $NewPolicy = $mfarm.CreatePolicy(19,$PolicyName,$PolicyDescription)

Script To Remove a Citrix Policy

  1. # Remove-CitrixPolicy.ps1
  2. Param($Server,$PolicyName = $(throw ‘$PolicyName is Required’),[switch]$whatif)
  3.  
  4. # Enums in Use
  5. $MetaFrameUnknownObject = 0
  6. $MetaFrameWinFarmObject = 1
  7.  
  8. # Getting Farm Object
  9. $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeFarm",$Server)
  10. $mfarm = [system.Activator]::CreateInstance($type)
  11. $mfarm.Initialize($MetaFrameWinFarmObject)
  12.  
  13. # Getting Policies that Match Name and Loading Data
  14. $policies = $mfarm.policies($MetaFrameUnknownObject) | ?{$_.Name -eq $PolicyName}
  15. foreach($pol in $policies)
  16. {
  17.     if($whatif){Write-Host " What if: Performing operation `"Delete`" on Target `"$($pol.Name)`". " -foreground yellow}
  18.     else{Write-Host " - Deleting $($pol.Name)";$pol.Delete()}
  19. }

Calculated Properties (UPDATE!)

I had a user point out that my code didnt work in a 4.5 farm. I did some testing and while some information was there, it was not complete. I did Test XP and 4.0 and they worked fine. I created a new one for CTX PS 4.5

  1. $MF = (New-Object -com MetaFrameCOM.MetaFrameFarm)
  2. $MF.Initialize(1)
  3. $MF.Servers | Select-Object ServerName -expand Applications | Select-Object ServerName,DistinguishedName,
  4.   @{n="AppName";e={$_.WinAppObject.BrowserName}},
  5.   @{n=‘Users’; e={$_.LoadData(1) | %{$_.Accounts2} | ?{$_.AccountType -eq 2} | %{$_.AccountName}}},
  6.   @{n=‘Groups’;e={$_.LoadData(1) | %{$_.Accounts2} | ?{$_.AccountType -eq 4} | %{$_.AccountName}}}

Lets talk about whats going on here

First We Get the MFCom Farm Object and Initialize it.

  1. $MF = (New-Object -com MetaFrameCOM.MetaFrameFarm)
  2. $MF.Initialize(1)

Next we iterate throught the servers parsing out only the ServerName and Getting MFCom Application Objects and pipe it along

  1. $MF.Servers | Select-Object ServerName -expand Applications |

The Final part is where we make the changes. In 4.5 the Application object no longer has Users Property or Group Property. It also no longer uses AppName.
For AppName we use: $_.WinAppObject.BrowserName
For Users we use: Accounts2 with AccountType 2
For Groups we use: Accounts2 with AccountType 4
The User/Group Name is stored in a property called AccountName

You will also notice the LoadData. This because not all information is there be default. LoadData fills out the object with data.

  1.  # Get the AppName from BrowserName
  2.   @{n="AppName";e={$_.WinAppObject.BrowserName}},
  3.   # Get users from Accounts2 filtering type 2 and selecting AccountName
  4.   @{n=‘Users’; e={$_.LoadData(1) | %{$_.Accounts2} | ?{$_.AccountType -eq 2} | %{$_.AccountName}}},
  5.   # Get Groups from Accounts2 filtering type 4 and selecting AccountName
  6.   @{n=‘Groups’;e={$_.LoadData(1) | %{$_.Accounts2} | ?{$_.AccountType -eq 4} | %{$_.AccountName}}}

Citrix functions Updated!

I didn’t have time last post to additional “Farm” functionality to some the functions. The following are updated to work against multiple farms.

Updated Server functions

  • Publish-CitrixApplication
  • UnPublish-CitrixServer
  • Remove-CitrixApplication
  • Updated Application functions

  • Get-CitrixApp
  • Get-CitrixAppUsers
  • Get-CitrixAppServers
  • Find-CitrixUser
  • Citrix Server Functions

    1. ##########################################
    2. ####     Citrix Server Functions      ####
    3. ##########################################
    4.  
    5. ## Publish Application to Server(s)
    6. ## -app: Name of Application to remove. This is required
    7. ## -Server: Name of Server
    8. ## PIPED: It will take Servers via Pipe. It expects a list or Citrix Server Object
    9. ## NOTE: App Name must include subfolders of the app.
    10. ##       If the app in in Applications\Test then app would be Test\MyApp
    11. ##       Example: Publish-CitrixApplication -server myserver -app Test\MyApp
    12. function Publish-CitrixApplication{
    13.     Param([string]$server,[string]$app)
    14.     Begin{
    15.         Write-Host
    16.         function gcs{
    17.             Param($srv)
    18.             $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$Server)
    19.             $mfServer = [system.Activator]::CreateInstance($type)
    20.             $mfServer.Initialize(6,$Server)
    21.             $mfServer
    22.         }
    23.         function gca{
    24.             Param($srv,$ma)
    25.             $type = [System.Type]::GetTypeFromProgID("MetaFrameCOM.MetaFrameApplication",$Server)
    26.             $mfApp = [system.Activator]::CreateInstance($type)
    27.             $mfApp.Initialize(3,"Applications\$ma")
    28.             $mfApp.LoadData($true)
    29.             $mfApp
    30.         }
    31.         function cPublish {
    32.             Param([string]$Srv,[string]$myapp)
    33.             $Srv = $Srv.toUpper()
    34.             $mfSrv = gcs $srv
    35.             $mfApp = gca $srv $myapp
    36.             $mfAppBinding = New-Object -ComObject MetaFrameCOM.MetaFrameAppSrvBinding
    37.             $mfAppBinding.Initialize(6,$Srv,"Applications\$app")
    38.             if($mfAppBinding)
    39.             {
    40.                 Write-Host "Publishing App[$myapp] on Server [$Srv]" -ForegroundColor Green
    41.                 $mfApp.AddServer($mfAppBinding)
    42.                 $mfApp.SaveData()
    43.             }
    44.             else
    45.             {
    46.                 Write-Host "Unable To Create App Binding" -ForegroundColor Red
    47.             }
    48.         }
    49.         $process = @()
    50.     }
    51.     Process{
    52.         if($_){
    53.             if($_.ServerName){
    54.                 $process += $_.ServerName
    55.             }
    56.             else{
    57.                 $process += $_
    58.             }
    59.         }
    60.     }
    61.     End{
    62.         if($Server){$Process += $Server}
    63.         foreach($s in $process){
    64.             cPublish -srv $s -myapp $app
    65.             Write-Host
    66.         }
    67.     }
    68. }
    69.  
    70. ## UnPublishes ALL Application from Server(s)
    71. ## -Server: Name of Server
    72. ## PIPED: It will take Servers via Pipe. It expects a list or Citrix Server Object
    73. function UnPublish-CitrixServer{
    74.     Param([string]$server)
    75.     Begin{
    76.         function gcs{
    77.             Param($srv)
    78.             $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$Server)
    79.             $mfServer = [system.Activator]::CreateInstance($type)
    80.             $mfServer.Initialize(6,$Server)
    81.             $mfServer
    82.         }
    83.         function cUnPublish {
    84.             Param([string]$Srv)
    85.             $Srv = $Srv.toUpper()
    86.             $mfSrv = gcs $srv
    87.             If($mfSrv.Applications.Count -gt 0)
    88.             {
    89.                 Write-Host "Removing All Published Applications from $Srv" -ForegroundColor Red
    90.                 Write-Host "===================================================" -ForegroundColor Green
    91.                 ForEach($a in $mfSrv.Applications)
    92.                 {
    93.                     $myApp = $a.AppName
    94.                     Write-Host "Removing App [$myApp] from Server [$Srv]" -ForegroundColor White
    95.                     $a.RemoveServer($Srv)
    96.                     $a.SaveData()
    97.                 }
    98.             }
    99.             else
    100.             {
    101.                 Write-Host "No Published Applications for $Srv" -ForegroundColor Red
    102.             }
    103.         }
    104.         Write-Host
    105.         $process = @()
    106.     }
    107.     Process{
    108.         if($_){
    109.             if($_.ServerName)
    110.             {
    111.                 $process += $_.ServerName
    112.             }
    113.             else
    114.             {
    115.                 $process += $_
    116.             }
    117.         }
    118.     }
    119.     End{
    120.         if($Server){$Process += $Server}
    121.         foreach($s in $process){
    122.             cUnPublish $s
    123.             Write-Host
    124.         }
    125.     }
    126. }
    127.  
    128. ## Remove Specific Application from Server(s)
    129. ## -app: Name of Application to remove. This is required
    130. ## -Server: Name Server.
    131. ## PIPED: It will take Servers via Pipe. It expects a list or Citrix Server Object
    132. function Remove-CitrixApplication {
    133.     Param([string]$server,[string]$app)
    134.     Begin{
    135.         function gcs{
    136.             Param($srv)
    137.             $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$Server)
    138.             $mfServer = [system.Activator]::CreateInstance($type)
    139.             $mfServer.Initialize(6,$Server)
    140.             $mfServer
    141.         }
    142.         function RemoveApp {
    143.             Param([string]$Srv,[string]$myapp)
    144.             $AppRemoved = $false
    145.             $Srv = $Srv.toUpper()
    146.             $mfSrv = gcs $srv
    147.             If($mfSrv.Applications.Count -gt 0)
    148.             {
    149.                 ForEach($a in $mfSrv.Applications)
    150.                 {
    151.                     If(($a.AppName -eq "$myapp") -or ($a.BrowserName -eq "$myapp"))
    152.                     {
    153.                         Write-Host "Removing App [$myApp] from Server [$Srv]" -ForegroundColor Green
    154.                         $a.RemoveServer($Srv)
    155.                         $a.SaveData()
    156.                         $AppRemoved = $true
    157.                     }
    158.                 }
    159.             }
    160.             else
    161.             {
    162.                 Write-Host "No Applications Published for $Srv" -ForegroundColor Red
    163.                 $AppRemoved = $true
    164.             }
    165.             If($AppRemoved -eq $false)
    166.             {
    167.                 Write-Host "This Application not Published for $Srv" -ForegroundColor Red
    168.             }
    169.         }
    170.         Write-Host
    171.         $process = @()
    172.     }
    173.     Process{
    174.         if($_)
    175.         {
    176.             if($_.ServerName){
    177.  
    178.                 $process += $_.ServerName
    179.             }
    180.             else
    181.             {
    182.                 $process += $_
    183.             }
    184.         }
    185.     }
    186.     End{
    187.         if($Server){$Process += $Server}
    188.         if($process.Length -eq 0){$Process += get-content env:COMPUTERNAME}
    189.         foreach($s in $process)
    190.         {
    191.             RemoveApp -Srv $s -myapp $app
    192.             Write-Host
    193.         }
    194.     }
    195. }

    Citrix App Functions

    1. #########################################
    2. ####     Citrix App Functions        ####
    3. #########################################
    4. ## Returns Citrix Application for Farm
    5. ## -Server: Name of Farm Server. This is required
    6. ## -App: Name of Application to remove. This is required
    7. function Get-CitrixApp{
    8.     Param($Server =$(throw ‘$Server is Required’),$App= $(throw ‘$FarmServer is Required’))
    9.     $type = [System.Type]::GetTypeFromProgID("MetaFrameCOM.MetaFrameApplication",$Server)
    10.     $mfApp = [system.Activator]::CreateInstance($type)
    11.     $mfApp.Initialize(3,"Applications\$myapp")
    12.     $mfApp.LoadData($true)
    13.     $mfApp
    14. }
    15.  
    16. ## Returns Users currently using APP
    17. ## -app: Name of Application. This is required
    18. ## -Server: Name of Farm Server. Defaults to local if not passed
    19. ## -count: Switch… if set just returns count of servers
    20. function Get-CitrixAppUsers {
    21.     Param($app = $(throw ‘$app is required’),$server,[switch]$count)
    22.     function gcf{
    23.         param($srv)
    24.         $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeFarm",$Server)
    25.         $mfarm = [system.Activator]::CreateInstance($type)
    26.         $mfarm.Initialize(1)
    27.         return $mFarm
    28.     }
    29.     $ErrorActionPreference = "SilentlyContinue"
    30.     Write-host
    31.     if($server){$mfm = gcf $server}
    32.     else{$mfm = New-Object -com MetaFrameCOM.MetaFrameFarm;$mfm.Initialize(1)}
    33.     $users = $mfm.Applications | ?{($_.AppName -eq $app) -or ($_.BrowserName -eq $app)}
    34.     $Users = $users.Sessions | sort -Property UserName
    35.     if($count){
    36.         Write-Host "Found [$($Users.Count)] Users for Application [$app]" -ForegroundColor White
    37.         Write-Host
    38.     }
    39.     else{
    40.         Write-Host ""
    41.         Write-Host "Found [$($Users.Count)] Users for Application [$app]" -ForegroundColor White
    42.         Write-Host "—————————————————–" -ForegroundColor gray
    43.         foreach($user in $Users){
    44.             If($User.SessionState -eq 1){
    45.                 Write-Host ($User.UserName).PadRight(10) -ForegroundColor Green -NoNewline
    46.             }
    47.             else{
    48.                 Write-Host ($User.UserName).PadRight(10) -ForegroundColor yellow -NoNewline
    49.             }
    50.         }
    51.         Write-Host
    52.         Write-Host "—————————————————–" -ForegroundColor gray
    53.         Write-Host "Found [$($Users.Count)] Users for Application [$app]" -ForegroundColor White
    54.         Write-Host
    55.     }
    56. }
    57.  
    58. ## Returns Servers currently published APP
    59. ## -app: Name of Application. This is required
    60. ## -Server: Name of Farm Server. Defaults to local if not passed
    61. ## -count: Switch… if set just returns count of servers
    62. function Get-CitrixAppServers {
    63.     Param($app = $(throw ‘$app is required’),$Server,[switch]$count)
    64.     function gcf{
    65.         param($srv)
    66.         $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeFarm",$Server)
    67.         $mfarm = [system.Activator]::CreateInstance($type)
    68.         $mfarm.Initialize(1)
    69.         return $mFarm
    70.     }
    71.     if($server){$mfm = gcf $server}
    72.     else{$mfm = New-Object -com MetaFrameCOM.MetaFrameFarm;$mfm.Initialize(1)}
    73.     $Apps = $mfm.Applications | ?{($_.AppName -eq $app) -or ($_.BrowserName -eq $app)}
    74.     # for XP farms
    75.     $servers = $apps | %{$_.Servers} | sort -Property ServerName | Select-Object ServerName
    76.     if(!$servers){
    77.         # for 40/45 farms
    78.         $servers = $Apps.Sessions | Select-Object ServerName | Sort-Object -unique ServerName
    79.     }
    80.     if($count)
    81.     {
    82.         Write-Host
    83.         Write-Host "Found [$($Servers.Count)] Servers for Application [$app]" -ForegroundColor White
    84.         Write-Host
    85.     }
    86.     else
    87.     {
    88.         Write-Host ""
    89.         Write-Host "Found [$($Servers.Count)] Servers for Application [$app]" -ForegroundColor White
    90.         Write-Host "———————————————–" -ForegroundColor gray
    91.         foreach($server in $servers){Write-Host "$($server.ServerName)" -ForegroundColor Green}
    92.         Write-Host "———————————————–" -ForegroundColor gray
    93.         Write-Host "Found [$($Servers.Count)] Servers for Application [$app]" -ForegroundColor White
    94.         Write-Host ""
    95.     }
    96. }
    97.  
    98. ## Returns Server(s) user is logged into via Citrix
    99. ## -LoginName: Login Name of user (Domain\User). This is Required
    100. ## -Server: Name of Farm Server. Defaults to local if not passed
    101. ## -Verbose: Details about User
    102. function Find-CitrixUser {
    103.     Param([string]$LoginName,$Server,[switch]$verbose)
    104.     $user = $LoginName.Split("\")[1]
    105.     $Domain = $LoginName.Split("\")[0]
    106.     if($server)
    107.     {
    108.         $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeUser",$Server)
    109.         $mfuser = [system.Activator]::CreateInstance($type)
    110.         $mfuser.Initialize(1,$Domain,1,$user)
    111.     }
    112.     else
    113.     {
    114.         $mfuser = New-Object -ComObject MetaframeCOM.MetaframeUser
    115.         $mfuser.Initialize(1,$Domain,1,$user)
    116.     }
    117.     Write-Host
    118.     Write-Host "User: $($mfuser.UserName) found on the Following:"
    119.     foreach ($s in $mfuser.Sessions)
    120.     {
    121.         if($verbose)
    122.         {
    123.             Write-Host
    124.             Write-Host "$($s.ServerName)"
    125.             Write-Host "-=-=-=-=-=-"
    126.             Write-Host "AppName          : $($s.AppName)" -foregroundcolor yellow
    127.             Write-Host "SessionName      : $($s.SessionName)" -foregroundcolor yellow
    128.             Write-Host "SessionID        : $($s.SessionID)" -foregroundcolor yellow
    129.             Write-Host "ClientAddress    : $($s.ClientAddress)" -foregroundcolor yellow
    130.             Write-Host "ClientEncryption : $($s.ClientEncryption)" -foregroundcolor yellow
    131.             Write-Host
    132.             Write-Host "Processes"
    133.             Write-Host "========="
    134.             foreach ($proc in $s.Processes)
    135.             {
    136.                 Write-Host $proc.ProcessName -foregroundcolor Green
    137.             }
    138.             Write-host
    139.         }
    140.         else
    141.         {
    142.             write-Host "   -> $($s.ServerName)"
    143.         }
    144.     }
    145. }