Powershelling Citrix (The Good, Bad, and The Code)
I would have to say that my first real experience with POSH was specifically with Citrix. As an Admin (one of many hats as a network engineer) of over 400 Citrix Servers and 3 Farms… I tend to script a alot. I am not a real fan of the CMC (Citrix Managment Console) and I much prefer anything that does not involve a GUI.
One of my biggest problems is that the three farms are isolated from each other. That makes what ever I do 3x the work. In this aspect… POSH has been a savior. I can write the script once… and then cut/paste. It’s awesome.
The Good:
If there is one thing I like about Citrix (and thats about it) is the fact they wrote a series of COM interfaces for Metaframe. These are incredibly useful but until POSH you couldn’t access these from the Command Shell. POSH lets you create COM objects on the fly so I use the Metafram COM interfaces exclusively.
The Bad:
As in all things Citrix… The COM interface is quirky (do I sound bitter?) I have run into a couple of little snags that if avoided will make your life alot easier.
1) Case Sensitive: I have found in my Citrix Use that for some reason. When you use MetaFrameCOM.MetaFrameServer and Initialize it… the Server Name must be in all CAPS. Not sure why (sorry) but I know if you don’t .ToUpper the Server… it failes.
2) Initialize… Initialize… Initialize: Almost all of the MetaFrameCOM component’s require you to Initialize… this would normally wouldn’t be a problem, but the finding the Initialization codes was a bit a of a pain. (I posted them in the appendix.)
3) For none developers passing an object as a parameter (who’d of thunk it?): So… for you C# people this is normal, but for the rest u sof scripters… not so much. You can see example of this in my Publish-CitrixApplication Function at the line $mfApp.AddServer($mfAppBinding). You have to create an App Binding Object to Add the server.
The Code:
Name: Get-CitrixOnline
Purpose: Get All Citrix Servers Currently Online (not to be confused with published)
Param([string]$zone)
$mfzone = New-Object -ComObject MetaFrameCOM.MetaFrameZone
$mfzone.Initialize("$zone")
$servers = $mfzone.OnlineServers
$servers | sort ServerName | Write-Output
}
Notes: Nothing special here, but make sure you know the zone name. You can get it from the CMC, but it should be the network of the first Citrix Server (i.e. 192.168.0.0)
Name: Get-CitrixApplications
Purpose: Get Citrix Apps published on Server
Param([string]$server)
$Server = $Server.ToUpper() # Citrix requires Server in CAPS (how odd)
$mfsrv = New-Object -ComObject MetaFrameCOM.MetaFrameServer
$mfsrv.Initialize(6,"$Server")
Write-Host "SERVER $Server" -foregroundcolor Red
Write-Host "==================" -ForegroundColor Green
If($mfSrv.Applications.Count -gt 0) {
$mfSrv.Applications %{Write-Host "Published: $($_.AppName.ToUpper())"}
}
else {
Write-Host "No Applications Published for $Server" -foregroundcolor white
}
}
Notes: Very useful for getting quick idea at what apps a server has published.
Name: Publish-CitrixApplications
Purpose: Publish Citrix App on Server
Param([string]$Srv,[string]$myapp)
$Srv = $Srv.toUpper()
$mfSrv = New-Object -ComObject MetaFrameCOM.MetaFrameServer
$mfSrv.Initialize(6,"$Srv")
$mfApp = New-Object -ComObject MetaFrameCOM.MetaFrameApplication
$mfApp.Initialize(3,"Applications\$myapp")
$mfApp.LoadData($true)
$mfAppBinding = New-Object -ComObject MetaFrameCOM.MetaFrameAppSrvBinding
$mfAppBinding.Initialize(6,$Srv,"Applications\$app")
if($mfAppBinding) {
Write-Host "Publishing App[$myapp] on Server [$Srv]" -ForegroundColor Green
$mfApp.AddServer($mfAppBinding)
$mfApp.SaveData()
}
else {
Write-Host "Unable To Create App Binding" -ForegroundColor Red
}
}
Notes: Thing to be careful with this one is the $mfApp.Initialize(3,”Applications\$myapp”) It is important to know that “Application\$myApp” needs to be the path you see in the CMC. If you created subfolders then you need to include them like $mfApp.Initialize(3,”Applications\Lab\$myapp”).
Name: UnPublish-CitrixServer
Purpose: Remove All Citrix Apps from Server
Param([string]$Server)
Write-Host $Server = $Server.toUpper()
$mfSrv = New-Object -ComObject MetaFrameCOM.MetaFrameServer
$mfSrv.Initialize(6,"$Server")
If($mfSrv.Applications.Count -gt 0) {
Write-Host "Removing All Published Applications from $Server"
Write-Host "==================================================="
ForEach($app in $mfSrv.Applications) {
$myApp = $App.AppName
Write-Host "Removing App [$myApp] from Server [$Server]"
$app.RemoveServer($Server)
$app.SaveData()
}
}
else {
Write-Host "No Published Applications for $Server"
}
}
Notes: Pretty strait forward. Remember that it removes ALL apps from the server.
Name: Remove-CitrixApplication
Purpose: Removes Citrix App from Server
Param([string]$Srv,[string]$myapp)
Write-Host
$AppRemoved = $false
$Srv = $Srv.toUpper()
$mfSrv = New-Object -ComObject MetaFrameCOM.MetaFrameServer
$mfSrv.Initialize(6,"$Srv")
If($mfSrv.Applications.Count -gt 0) {
ForEach($app in $mfSrv.Applications) {
If($app.AppName -eq "$myapp") {
Write-Host "Removing App [$myApp] from Server [$Srv]"
$app.RemoveServer($Srv)
$app.SaveData()
$AppRemoved = $true
}
}
}
else {
Write-Host "No Applications Published for $Srv" -ForegroundColor Red
$AppRemoved = $true
}
If($AppRemoved -eq $false) {
Write-Host "This Application not Published for $Srv" -ForegroundColor Red
}
}
Notes: Only removes specified app.
Coming Soon: Should be posting more complex Citrix scripts to Add/Remove apps. Get some basic Stats, and such.
Appendix:
———
Typical:
MetaFrameCOM.MetaFrameServer: (6,”SERVERNAME”)
MetaFrameCOM.MetaFrameAppSrvBinding: (6,”SERVERNAME”,”AppPath\AppName”)
MetaFrameCOM.MetaFrameApplication: (3,”AppPath\AppName”)
MetaFrameCOM.MetaFrameZone: (”ZONE”)
—— Will be adding headers soon —–
tshell :: Jan.16.2007 :: All, Citrix, HowTo, Powershell, Scripting :: No Comments »

Do you know of any way to switch farms in powershell without using mfreg? We have two farms we must manage and it would be a pain to have to switch back and forth every time. I am primarily a vbscripter and this is not hard to do in vbscript but seems impossible in powershell thus farm. Any help is much appreciated.
[...] recent post title How to Manage Multiple Citrix Farms New!Birth of a Script/Function C# to PowerShell Translation Thought Process Kill-UserProcess (myfirst whatif Script) Where is BS? UPDATED!!! Get-Uptime (The Custom Object extravaganza!!!) Get-Uptime (fun with Write-Host) Powershell Information Central (work in progress) A Powershell Adventure: Chpt2 'Using .NET in Powershell' Powershelling Citrix (The Good, Bad, and The Code) WordPress sidebar #wordpress_sidebar div.sidetitle{ padding: 1em 0 0 0; } Categories [...]
[...] Here is a great article to get you started. [...]