Posts RSS Comments RSS 253 Posts and 411 Comments till now

Printing Multiple InfoPath forms (Automated)

My name is John Negus and I work for a small consulting company called MSEtechnology.  I specialize in Active Directory and Microsoft Operating Systems, with a little bit of Exchange and everything else Microsoft thrown in.  I have taught a lot of internal AD courses for Microsoft all over the world and my current contract has me working on site alongside Brandon “The Power” Shell.  That is where I was presented with the challenge of automating the printing of multiple InfoPath 2003 forms.
I was told, by Microsoft, that this was not an easy thing to do and that I could open up an advisory case in which they could give me some sample code to do this.  I was also informed that I could create a transform file for Word and print all the forms using Word.  I attempted this approach but gave up as it was long and drawn out.

Alas, PowerShell came to the rescue.  Once I found the correct COM object to use and with the help of the “Great One” (that’s Brandon, in-case you did not know) it was easy, as you can see below.

Param($Path = "\\sharepoint.corp.com\Form_Folder",[switch]$verbose)

Write-Host

function Invoke-FormPrint
{
    Param($InfoForm)
    $shortname = $InfoForm.name
    Write-Verbose "   – FormPrint: Creating COM Object"
    $infopath = New-Object -com InfoPath.Application -verbose:$false
    Write-Verbose "   – FormPrint: Calling Open(`$InfoForm.fullname,10)"
    $infopath.XDocuments.Open($InfoForm.fullname,10) | out-null
    Write-verbose "   – FormPrint: Calling PrintOut()"
    $infopath.XDocuments[0].printout()
    sleep 10
    Write-verbose "   – FormPrint: Calling Quit()"
    $infopath.quit()
    if(!$?)
    {
        Write-Host "    – Error printing Form: $shortname" -fore RED
    }
    else
    {
        Write-Host "    – Successfully printed Form: $shortname" -fore Green
    }
}

$erroractionpreference = "silentlycontinue"

if($verbose){$verbosepreference="continue";$erroractionpreference="continue"}

Write-Verbose " + Processing all Forms from: $path"
$Forms = dir $path "*.xml"

Write-Verbose "  + $($Forms.count) Forms found"
Write-host " + Processing all $($Forms.count) Forms located at: $path" -fore White

foreach($Form in $Forms)
{
    Write-Host "  + Printing Form: $($Form.Name)" -fore White
    Invoke-FormPrint $Form
}

Get-CitrixApplication.ps1 (Citrix Top 10)

This script returns Citrix Application Objects.
– With no -AppName passed it will return All application Objects
– With -AppName it will return all apps that match (regex.)

# Get-CitrixApplication.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Returns Citrix Application Objects for AppName passed or RegEx
Param($AppName=".*",$server=$env:ComputerName)
$type = [system.Type]::GetTypeFromProgID("MetaframeCOM.MetaFrameFarm",$server)
$farm = [system.Activator]::CreateInstance($type)
$farm.Initialize(1)
$farm.Applications | ?{($_.AppName -match $AppName) -or ($_.BrowserName -match $AppName)}

Set-CitrixServerLogon.ps1 (Citrix Top 10)

Here is a useful little script. This Creates a MFCom Server Object and disables or Enables Logons for that Server.

# Set-CitrixServerLogon.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Sets the Server to Enable or Disable Logons
Param($Server,[switch]$enable,[switch]$disable,[switch]$help)
function HelpMe{
    Write-Host
    Write-Host " Set-CitrixServerLogon.ps1:" -fore Green
    Write-Host "   Sets the Server to Enable or Disable Logons"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -Server                  : Optional. Server to Set Logon"
    Write-Host "   -Enable                  : Optional. Checks Hours of Idle Time (Default)"
    Write-Host "   -Disable                 : Optional. Checks Minutes of Idle Time"
    Write-Host "   -Help                    : Optional. Displays This"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   To disable the Logon for a Server" -fore White
    Write-Host "     Set-CitrixServerLogon.ps1 -server <serverName> -Disable" -fore Yellow
    Write-Host
}

if(!$Server -or $help){helpme;Write-Host;return}

Write-Host

Write-Host " Getting Server [$Server]"
$mfsrv = New-Object -ComObject MetaFrameCOM.MetaFrameServer

Write-Host " – Initializing Server"
$mfsrv.Initialize(6,$Server)

if($enable)
{
    Write-Host " – Setting to EnableLogon = 1"
    $mfSrv.WinServerObject.EnableLogon = 1
}
if($disable)
{
    Write-Host " – Setting to EnableLogon = 0"
    $mfSrv.WinServerObject.EnableLogon = 0
}

Write-Host " – Server [$($mfSrv.ServerName)] is set to [$($mfSrv.WinServerObject.EnableLogon)] for EnableLogon"

Write-Host

Another option would be to remove the Apps from the Server all together.

# Unpublish-CitrixServer.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Removes all App from Server
Param($Server)
$mfsrv = New-Object -ComObject MetaFrameCOM.MetaFrameServer
$mfsrv.Initialize(6,$Server.ToUpper())
$mfsrv | foreach{$_.Applications} | foreach{$_.LoadData(1);$_.RemoveServer($Server.ToUpper());$_.SaveData()}

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 🙂

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

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

# Get-CitrixApplication.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Gets a Citrix Application Object.
Param($app)
$mfApp = New-Object -ComObject MetaFrameCOM.MetaFrameApplication
$mfApp.Initialize(3,$app)
$mfApp.LoadData(1)
$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

# Find-CitrixUser.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Finds where the user(s) are and out puts session info
Param($user=".*",[switch]$help)
function HelpMe{
    Write-Host
    Write-Host " Find-CitrixUser.ps1:" -fore Green
    Write-Host "   Finds where the user(s) are and out puts session info"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -User                  : Optional. Name of the User or RegEx (Default is all users)"
    Write-Host "   -Help                  : Optional. Displays This"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Finds User TestMe and outputs and returns ServerName,ClientAddress, and SessionID" -fore White
    Write-Host "     .\Find-CitrixUser.ps1 | ft ServerName,ClientAddress,SessionID " -fore Yellow
    Write-Host
    Write-Host "   Finds all Users who start with ‘Sales’ and returns UserName,ServerName, and SessionID"  -fore White
    Write-Host "     .\Find-CitrixUser.ps1 `"^sales`" | ft UserName,ServerName,SessionID " -fore Yellow
    Write-Host
    Write-Host "   To View All properties availiable." -fore White
    Write-Host "     .\Find-CitrixUser.ps1 <username> | Get-Member" -fore Yellow
    Write-Host
}

# Check for the Help or if
if($help){helpme;Write-Host;return}

# Code to Get the Farm and Initialize
$farm = New-Object -com "MetaframeCOM.MetaFrameFarm"
$farm.Initialize(1)

# Get the Sessions and Parse for Users who match
$farm.Sessions | ?{$_.UserName -match $user}

Get-CitrixPrinterInfo.ps1 (Citrix Top 10)

This script just collects the Printer Information from all the Servers in the Farm. It will output them to a file or you can pipe them and filter them.

Name: Get-CitrixPrinterInfo.ps1
Purpose: Gets Print Driver Info from all the Servers in the Farm and outputs to file or console

# Get-CitrixPrinterInfo.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Gets Print Driver Info from all the Servers in the Farm
Param($Server,$file,[Switch]$help)
function HelpMe{
    Write-Host
    Write-Host " Get-CitrixPrinterInfo.ps1:" -fore Green
    Write-Host "   Gets Print Driver Info from all the Servers in the Farm"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -Server                : Optional. Server to Get Print Info From "
    Write-Host "   -File                  : Optional. File Name to Export Info to"
    Write-Host "   -Help                  : Optional. Displays This"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Gets Print Info and Exports to File" -fore White
    Write-Host "     .\Get-CitrixPrinterInfo.ps1 -file MyExportFile.txt" -fore Yellow
    Write-Host
    Write-Host "   Gets Print Drivers from a Specific Server and outputs DriverName and SourceServer"  -fore White
    Write-Host "     .\Get-CitrixPrinterInfo.ps1 <serverName> | ft DriverName,SourceServer" -fore Yellow
    Write-Host
}

# Check for Help Flag
if($help){HelpMe;Write-Host;Return}

# Check for File
if($file)
{
    if($server) # If -Server was passed we run check just against it and output to screen
    {
        $mfsrv = new-Object -com "MetaframeCOM.MetaframeServer"
        $mfsrv.Initialize(6,$Server.ToUpper())
        $mfsrv | foreach{"`n$($_.ServerName) `n$(‘-‘*20)";$_.PrinterDrivers| Format-Table} | out-File $file -enc ASCII
    }
    else # We run the check against the whole farm and output results to file
    {
        $mfarm = new-Object -com "MetaframeCOM.MetaframeFarm"
        $mfarm.Initialize(1)
        $mfarm.Servers | foreach{"`n$($_.ServerName) `n$(‘-‘*20)";$_.PrinterDrivers| Format-Table} | out-File $file -enc ASCII
    }
}
else
{
    if($server) # If -Server was passed we run check just against it and output to screen
    {
        $mfsrv = new-Object -com "MetaframeCOM.MetaframeServer"
        $mfsrv.Initialize(6,$Server.ToUpper())
        $mfsrv | foreach{"`n$($_.ServerName) `n$(‘-‘*20)";$_.PrinterDrivers| Format-Table}
    }
    else # We run the check against the whole farm and output results to screen
    {
        $mfarm = new-Object -com "MetaframeCOM.MetaframeFarm"
        $mfarm.Initialize(1)
        $mfarm.Servers | foreach{"`n$($_.ServerName) `n$(‘-‘*20)";$_.PrinterDrivers| Format-Table}
    }
 }

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

# Find-CitrixIdleUser.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Finds users with idle time greater than value passed
Param($time,[switch]$day,[switch]$hour,[switch]$minute,[switch]$logoff,[switch]$verbose,[switch]$help)
function HelpMe{
    Write-Host
    Write-Host " Find-CitrixIdleUser.ps1:" -fore Green
    Write-Host "   Finds users with idle time greater than value passed"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -Time                  : Optional. Server to Get Print Info From "
    Write-Host "   -Day                   : Optional. Checks Days of Idle Time "
    Write-Host "   -Hour                  : Optional. Checks Hours of Idle Time (Default)"
    Write-Host "   -Minute                : Optional. Checks Minutes of Idle Time"
    Write-Host "   -Logoff                : Optional. Logs User off if Idle Time exceeds Time"
    Write-Host "   -Verbose               : Optional. Show Verbose Output"
    Write-Host "   -Help                  : Optional. Displays This"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Finds Users who have been idle 2 hours and return AppName, UserName, SessionID, and ClientName" -fore White
    Write-Host "     Find-CitrixIdleUser.ps1 2 -hour | ft AppName,UserName,SessionID,ClientName -auto" -fore Yellow
    Write-Host
    Write-Host "   Finds Users who have been idle 2 hours and Logs them Off" -fore White
    Write-Host "     Find-CitrixIdleUser.ps1 2 -hour -logoff" -fore Yellow
    Write-Host
}
if($verbose){$verbosepreference = "Continue"}
Write-Host
if(!$time -or $help){helpme;Write-Host;Return}

# Get Citrix Farm Object
Write-Verbose " – Creating MFFarm Object"
$farm = new-Object -com "MetaframeCOM.MetaframeFarm"
$farm.Initialize(1)

# Parse Sessions
Write-Verbose " – Parsing Sessions. Total of [$($farm.Sessions.count)] Sessions"
foreach($session in $farm.Sessions)
{
    Write-Verbose "   – Processing Session ID [$($Session.SessionId)]"
    $shouldLogOff = $false

    # Getting Citrix Session Idle Time and Convert to System.DateTime
    Write-Verbose "   – Getting LastInputTime"
    $ctxDate = $session.LastInputTime(1)
    Write-Verbose "   – Checking if idle time is -gt 0"
    if(($ctxDate.HighPart -ne 0) -and ($ctxDate.LowPart -ne 0))
    {
        $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
        Write-Verbose "   – Converted LastInputTime to [$date]"
        $SessionIdleTime = [system.DateTime]::ParseExact($date,‘yyyyMMddHHmm’,$null)

        # Get Current Time in System.DateTime
        Write-Verbose "   – Getting Current Date"
        $now = Get-Date
        Write-Verbose "   – Current Date is [$now]"

        # Find Difference
        Write-Verbose "   + Getting Time Difference"
        $diff = $now$SessionIdleTime
        Write-Verbose "     – Found Days [$($diff.TotalDays)] Hours [$($diff.Totalhours)] Minutes [$($diff.TotalMinutes)]"

        # Output Sessions that match
        if($day)   {    if($diff.TotalDays    -gt $time)    {$session;$shouldLogOff = $true}  }
        if($hour)  {    if($diff.Totalhours   -gt $time)    {$session;$shouldLogOff = $true}  }
        if($minute){    if($diff.TotalMinutes -gt $time)    {$session;$shouldLogOff = $true}  }

        Write-Verbose "     – Set `$shouldLogOff to [$shouldLogOff]"

        # Logging Off User
        if($logoff -and $shouldLogOff)
        {
            Write-Verbose "   – Logging Off Session ID [$($Session.SessionId)]"
            $session.Logoff($false)
        }
    }
    else
    {
        Write-Verbose "   – Session ID [$($Session.SessionId)] NOT Idle"
    }
    Write-Host
}

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

# Get-CitrixSessionUser.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# List ClientAddress and UserName for each Session

$farm = new-Object -com "MetaframeCOM.MetaframeFarm"
$farm.Initialize(1)
$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

# Get-CitrixSession.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Gets all the Sessions for a Farm

$farm = new-Object -com "MetaframeCOM.MetaframeFarm"
$farm.Initialize(1)
$farm.Sessions

Set-CitrixPSVersion.ps1 (Citrix Top 10)

I am constantly looking for content for my blog and tasks that can be automated. I believe this helps me learn and helps other with their needs.

In this search I was directed to convert/write Powershell examples for scripts located here http://community.citrix.com/display/cdn/Script+Exchange

Here is the first of those scripts.

Name: Set-CitrixPSVersion.ps1
Purpose: Sets PS Version on a Server, List of Servers, or all Servers in the Farm

# Set-CitrixPSVersion.ps1
# Brandon Shell [MVP]
# www.bsonposh.com
# Sets PS Version on a Server, List of Servers, or all Servers in the Farm
Param($file,$server,$PSVer,[switch]$help,[switch]$all,[switch]$whatif,[switch]$show,[switch]$verbose)
function HelpMe{
    Write-Host
    Write-Host " Set-CitrixPSVersion.ps1:" -fore Green
    Write-Host "   Sets PS Version on a Server, List of Servers, or all Servers in the Farm"
    Write-Host
    Write-Host " Parameters:" -fore Green
    Write-Host "   -File <fileName>       : Optional. Name of the File of Servers"
    Write-Host "   -Server <serverName>   : Optional. Name of the Server to Change"
    Write-Host "   -Verbose               : Optional. Enables Verbose Output"
    Write-Host "   -All                   : Optional. Sets Version on all Servers [Requires -Server]"
    Write-Host "   -Show                  : Optional. Displays the Version for Server(s)"
    Write-Host "   -Help                  : Optional. Displays This"
    Write-Host "   -Whatif                : Optional. Will not Commit Info just Display what would change"
    Write-Host
    Write-Host " Examples:" -fore Green
    Write-Host "   Set PS Version on Server1 to STD" -fore White
    Write-Host "     .\Set-CitrixPSVersion.ps1 -Server Server1 -psver STD " -fore Yellow
    Write-Host
    Write-Host "   Set PS Version on Servers in a File" -fore White
    Write-Host "     .\Set-CitrixPSVersion.ps1 -file c:\Mylist.txt -psver STD " -fore Yellow
    Write-Host
    Write-Host "   Get PS Version from ALL server" -fore White
    Write-Host "     .\Set-CitrixPSVersion.ps1 -all -Server myzdcserver" -fore Yellow
    Write-Host
    Write-Host " Product Edition Options" -fore Green
    Write-Host "   STD = Citrix Presentation Server Standard Edition" -fore White
    Write-Host "   ADV = Citrix Presentation Server Advanced Edition" -fore White
    Write-Host "   ENT = Citrix Presentation Server Enterprise Edition" -fore White
    Write-Host "   PLT = Citrix Presentation Server Platinum Edition" -fore White
    Write-Host
}
function Ping-Server {
    Param($srv)
    $pingresult = Get-WmiObject win32_pingstatus -f "address=’$srv’"
    if($pingresult.statuscode -eq 0) {$true} else {$false}
}
function Set-PSVer{
    Param($srv)
    Write-Verbose "  Getting Citrix Server Object"
    $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$srv)
    $mfsrv = [system.Activator]::CreateInstance($type)
    $mfsrv.Initialize(6,$srv)
    if(!$?){Write-Host "   – Server [$srv] threw and Error" -fore red;return}

    if($show) # Check for $Show and will display only
    {
        Write-Host "   – PS Version for [$srv]: $($mfsrv.WinServerObject.mpsedition)"
        return
    }
    else
    {
        if($whatif) # Check for $Whatif
        {
            Write-Host "  What if: Performing operation `"Set PS Version [$PSVer]`" on Target `"$srv`"."
        }
        else
        {
            Write-Verbose "   – Setting PSVer to [$PSVer] on [$srv]"
            $mfsrv.WinServerObject.mpsedition = $PSVer
            Write-Host "   – PS Version for [$srv]: $($mfsrv.WinServerObject.mpsedition)"
        }
    }
}
function Set-PSALL{
    $mfarm = new-Object -com "MetaframeCOM.MetaframeFarm"
    $mfarm.Initialize(1)
    foreach($mfsrv in $mfarm.Servers)
    {
        if($show){Write-Host "   – PS Version for [$($mfsrv.ServerName)]: $($mfsrv.WinServerObject.MPSEdition)";continue}
        if($whatif){Write-Host "  What if: Performing operation `"Set PS Version [$PSVer]`" on Target `"$($mfsrv.ServerName)`"."}
        else
        {
            Write-Verbose "   – Setting PSVer to [$PSVer] on [$($mfsrv.ServerName)]"
            $mfsrv.WinServerObject.mpsedition = $PSVer
            Write-Host "   – PS Version for [$($mfsrv.ServerName)]: $($mfsrv.WinServerObject.MPSEdition)"
        }
    }
}

# Script Setup. Checking Parameters
Write-Host

## Checing Verbose flag
if($verbose){$verbosepreference = "Continue"}else{$erroractionpreference = "SilentlyContinue"}

## Verifying that File/Server was passed. If not or -help I Call HelpMe and close.
if(!$file -and !$server -and !$all -or $help){HelpMe;Return}

## Verify Valid Edition was Passed
if(!$show -and ($PSVer -notmatch "STD|ADV|ENT|PLT"))
{
    Write-Host " PS Edition [$PSVER] is NOT Valid. Please use STD, ADV, ENT, or PLT" -fore RED
    Write-Host
    Return
}

# If $Server and we can ping it we run Set-PSVer against Server
if($server -and (ping-server $server))
{
    Set-PSVer $server
    Write-host
}

# Check for -File and Verify the file is valid
if($File -and (test-Path $file))
{
    Write-Verbose " – Processing File [$file]"
    # Process each Server checking for blanks
    foreach($Server in (get-Content $file | where{$_ -match "^\S"}))
    {
        Write-Host " + Processing Server [$Server]"
        if(ping-Server $server){Set-PSVer $Server}else{Write-Host "   – Ping Failed to [$Server]" -fore Red}
        Write-host
    }
}

if($all){Set-PSALL}

Write-Host

An Interactive Case for Powershell (Yet more Citrix Fun!)

I was recently in a discussion on Brian Madden Forums about listing Citrix Information and exporting to CSV. It seemed like a
perfect fit for Powershell so I converted the VBScripts to Powershell (of course taking an 85 line script to 3 lines. Convert is
hardly the correct term.)

Here is the Forum Topic
http://www.brianmadden.com/Forum/Topic/95285

Here is my Code. There were three scripts, so I made three as well.

# Apps by Server CTXApps_by_Server_w_Users
$MF = (New-Object -com MetaFrameCOM.MetaFrameFarm)
$MF.Initialize(1)
$MF.Servers | Select-Object ServerName -expand Applications | Select-Object ServerName,AppName,DistinguishedName,
       @{n=‘Users’;e={$_.Users | %{$_.UserName}}},
       @{n=‘Groups’;e={$_.Groups | %{$_.GroupName}}} | export-Csv C:\AppsByServer.Csv -noType
# Apps with Servers
$MF = New-Object -com MetaFrameCOM.MetaFrameFarm
$MF.Initialize(1)
$MF.Applications | Select-Object AppName,DistinguishedName,
      @{n="Servers";e={$_.Servers | foreach{$_.ServerName}}} | export-Csv C:\AppsWithServer.Csv -noType
# Apps with Servers and Users CTXApps_w_Servers_w_Users
$MF = New-Object -com MetaFrameCOM.MetaFrameFarm
$MF.Initialize(1)
$MF.Applications | Select-Object AppName,DistinguishedName,
      @{n="Servers";e={$_.Servers | foreach{$_.ServerName}}},
      @{n=‘Users’;e={$_.Users | %{$_.UserName}}},
      @{n=‘Groups’;e={$_.Groups | %{$_.GroupName}}} | export-Csv C:\AppsWithServerandUsers.Csv -noType

If you notice in my three scripts they all start with the same two lines. Effectively these are one liners that could be used
interactively. I think this does a great job of showing Citrix Admins how nicely Powershell will fit in to their daily lives.
Things that use to take 100s of lines of script writing can now be done interactively at a shell.

Next »