Posts RSS Comments RSS 253 Posts and 408 Comments till now

BSonPosh Module goes beta

I am releasing a beta of my BSonPosh module. This is a early release and may have some bugs that need to be tweaked. It may also be missing some functionality and help files. If you would like participate in the beta send me an email via my contact form and I will shoot you a copy.

I am looking for any feedback. Specifically if you think any thing is missing :)

Here is a list of the functions/cmdlets provided by the module:

—————————————-
ConvertTO-DistinguishedName
ConvertTo-DNSName
ConvertTo-Name
ConvertTo-NetbiosName
ConvertTo-Sid
ConvertTo-UACFLag
Format-XML
Get-ADACL
Get-ADSchema
Get-ADSchemaClass
Get-ADSchemaProperty
Get-Assemblies
Get-BSonPosh
Get-DC
Get-DCConnectionObject
Get-Forest
Get-RebootTime
Get-Routetable
Get-SiteLink
Get-SysInternals
Get-TraceFile
Get-Uptime
Get-WindowsUpdate
Import-BSonPosh
Invoke-uac
Invoke-WhoAmI
New-ADACE
Resolve-Host
Select-LargeFiles
Set-ADACL
Set-DCConnectionOption
Set-SiteLink
Start-TS
Test-ADReplication
Test-Host
Test-LdapFilter
Trace-LDAP
update-Gac

blog: Import/Export XenApp Applications with Powershell

If there is one functionality that has been requested from myself and Citrix it is the ability to import/export applications.

With the XenApp cmdlets this is super trivial.

This is the SUPER COMPLEX Script ;)

Get-XAApplication -full | Export-Clixml .MyApps.txt
# Make sure the Apps are as you want
Import-Clixml .MyApps.txt
# To Import
Import-Clixml .MyApps.txt| New-XAApplication
# Lets see what apps we have now (I added the Imported)
Get-XAApplication | select BrowserName

Not at all complex is it? Great stuff.

Here is a demo that shows how to do it.
Download XenAppExport Demo

blog: New XenApp cmdlets demo from Synergy

I have to say… the XenApp guys at Citrix get it and I mean they really get it. We all know there are areas where Citrix has blew it in the Powershell space, but this is not one of them (good time to note that Citrix has taken the feedback from the community and is changing things.)

btw… You can catch a vid of me and Brian Madden discussing Powershell HERE. If I sound a tad distracted… I am. This was done in the Expo hall with 1000s of people walking around. I was doing my best not to yell out ";LOOK!… SHINY!";

I had the privilege of showing off the new XenApp cmdlets to the world at Synergy and thought I would share the demo's with you guys as well.

Ok… back to the blog at hand :)

NOTE: It requires 4.5 with HR3 and above for most functionality. XenApp5 for full functionality.

Here is the first demo that demo's Get-XAFarm, Get-XAFarmConfiguration, Get-XAServer, and Get-XAApplication

Download XenAppDemo

Here is the list of the cmdlets included, sorted by verb:

Verb: Add
Name
—-
Add-XAAdministratorPrivilege
Add-XAApplicationAccount
Add-XAApplicationFileType
Add-XAApplicationServer
Add-XALoadEvaluatorServer
Add-XASessionPrinter

Verb: Clear
Name
—-
Clear-XAConfigurationLog

Verb: Connect
Name
—-
Connect-XASession

Verb: Copy
Name
—-
Copy-XAApplication

Verb: Disable
Name
—-
Disable-XAAdministrator
Disable-XAApplication
Disable-XAPolicy
Disable-XAServerLogOn

Verb: Disconnect
Name
—-
Disconnect-XASession

Verb: Enable
Name
—-
Enable-XAAdministrator
Enable-XAApplication
Enable-XAPolicy
Enable-XAServerLogOn

Verb: Get
Name
—-
Get-XAAccount
Get-XAAccountAuthority
Get-XAAdministrator
Get-XAAdministratorFolder
Get-XAAdministratorPrivilege
Get-XAApplication
Get-XAAppliedPolicy
Get-XAAutoReplicatedPrinterDriver
Get-XAClientModule
Get-XAClientPrinter
Get-XAConfigurationLog
Get-XAFarm
Get-XAFarmConfiguration
Get-XAFileType
Get-XAFolder
Get-XAHmrTest
Get-XAIconStream
Get-XALoadEvaluator
Get-XAMemoryOptimization
Get-XAOfflineLicense
Get-XAPolicy
Get-XAPolicyConfiguration
Get-XAPolicyFilter
Get-XAPrinter
Get-XAPrinterDriver
Get-XAPrinterDriverCompatibility
Get-XAPrinterDriverMapping
Get-XAPrintServer
Get-XAProfileApplication
Get-XAResultantPolicy
Get-XAServer
Get-XAServerConfiguration
Get-XAServerLoad
Get-XASession
Get-XASessionPrinter
Get-XASessionProcess
Get-XAStreamingSession
Get-XAVirtualIPRange
Get-XAZone

Verb: Import
Name
—-
Import-XALegacyApplication
Import-XAPrintServer

Verb: Move
Name
—-
Move-XAApplication
Move-XAFolder
Move-XAServer

Verb: New
Name
—-
New-XAAdministrator
New-XAApplication
New-XAAutoReplicatedPrinterDriver
New-XAClientPrinter
New-XAFolder
New-XAHmrTest
New-XAIcaFile
New-XALoadEvaluator
New-XAPolicy
New-XAPrinterDriverCompatibility
New-XAPrinterDriverMapping
New-XAVirtualIPRange

Verb: Remove
Name
—-
Remove-XAAdministrator
Remove-XAAdministratorPrivilege
Remove-XAApplication
Remove-XAApplicationAccount
Remove-XAApplicationFileType
Remove-XAApplicationServer
Remove-XAAutoReplicatedPrinterDriver
Remove-XAClientPrinter
Remove-XAFolder
Remove-XAHmrTest
Remove-XALoadEvaluator
Remove-XALoadEvaluatorServer
Remove-XAPolicy
Remove-XAPrinterDriverCompatibility
Remove-XAPrinterDriverMapping
Remove-XAPrintServer
Remove-XAServer
Remove-XASessionPrinter
Remove-XAVirtualIPRange

Verb: Rename
Name
—-
Rename-XAApplication
Rename-XAFolder
Rename-XAHmrTest
Rename-XALoadEvaluator
Rename-XAPolicy
Rename-XAZone

Verb: Replicate
Name
—-
Replicate-XAPrinterDriver

Verb: Reset
Name
—-
Reset-XAClientPrinter

Verb: Send
Name
—-
Send-XASessionMessage

Verb: Set
Name
—-
Set-XAAdministrator
Set-XAAdministratorFolder
Set-XAApplication
Set-XAFarmConfiguration
Set-XAHmrTest
Set-XALoadEvaluator
Set-XAPolicy
Set-XAPolicyConfiguration
Set-XAPolicyFilter
Set-XAPrinterDriverCompatibility
Set-XAPrinterDriverMapping
Set-XAServerConfiguration
Set-XAServerEdition
Set-XAServerZone
Set-XASessionPrinter

Verb: Stop
Name
—-
Stop-XASession
Stop-XASessionProcess

Verb: Test
Name
—-
Test-XAConfigurationLog
Test-XALicenseServer

Verb: Update

Name
—-
Update-XAFileType
Update-XAPrinter

Import/Export XenApp Applications with Powershell

If there is one functionality that has been requested from myself and Citrix it is the ability to import/export applications.

With the XenApp cmdlets this is super trivial.

This is the SUPER COMPLEX Script ;)

Get-XAApplication -full | Export-Clixml .\MyApps.txt
# Make sure the Apps are as you want
Import-Clixml .\MyApps.txt
# To Import
Import-Clixml .\MyApps.txt| New-XAApplication
# Lets see what apps we have now (I added the Imported)
Get-XAApplication | select BrowserName

Not at all complex is it? Great stuff.

Here is a demo that shows how to do it.
Download XenAppExport Demo

New XenApp cmdlets demo from Synergy

I have to say… the XenApp guys at Citrix get it and I mean they really get it. We all know there are areas where Citrix has blew it in the Powershell space, but this is not one of them (good time to note that Citrix has taken the feedback from the community and is changing things.)

btw… You can catch a vid of me and Brian Madden discussing Powershell HERE. If I sound a tad distracted… I am. This was done in the Expo hall with 1000s of people walking around. I was doing my best not to yell out “LOOK!… SHINY!”

I had the privilege of showing off the new XenApp cmdlets to the world at Synergy and thought I would share the demo’s with you guys as well.

Ok… back to the blog at hand :)

NOTE: It requires 4.5 with HR3 and above for most functionality. XenApp5 for full functionality.

Here is the first demo that demo’s Get-XAFarm, Get-XAFarmConfiguration, Get-XAServer, and Get-XAApplication

Download XenAppDemo

Here is the list of the cmdlets included, sorted by verb:

Verb: Add
Name
—-
Add-XAAdministratorPrivilege
Add-XAApplicationAccount
Add-XAApplicationFileType
Add-XAApplicationServer
Add-XALoadEvaluatorServer
Add-XASessionPrinter

Verb: Clear
Name
—-
Clear-XAConfigurationLog

Verb: Connect
Name
—-
Connect-XASession

Verb: Copy
Name
—-
Copy-XAApplication

Verb: Disable
Name
—-
Disable-XAAdministrator
Disable-XAApplication
Disable-XAPolicy
Disable-XAServerLogOn

Verb: Disconnect
Name
—-
Disconnect-XASession

Verb: Enable
Name
—-
Enable-XAAdministrator
Enable-XAApplication
Enable-XAPolicy
Enable-XAServerLogOn

Verb: Get
Name
—-
Get-XAAccount
Get-XAAccountAuthority
Get-XAAdministrator
Get-XAAdministratorFolder
Get-XAAdministratorPrivilege
Get-XAApplication
Get-XAAppliedPolicy
Get-XAAutoReplicatedPrinterDriver
Get-XAClientModule
Get-XAClientPrinter
Get-XAConfigurationLog
Get-XAFarm
Get-XAFarmConfiguration
Get-XAFileType
Get-XAFolder
Get-XAHmrTest
Get-XAIconStream
Get-XALoadEvaluator
Get-XAMemoryOptimization
Get-XAOfflineLicense
Get-XAPolicy
Get-XAPolicyConfiguration
Get-XAPolicyFilter
Get-XAPrinter
Get-XAPrinterDriver
Get-XAPrinterDriverCompatibility
Get-XAPrinterDriverMapping
Get-XAPrintServer
Get-XAProfileApplication
Get-XAResultantPolicy
Get-XAServer
Get-XAServerConfiguration
Get-XAServerLoad
Get-XASession
Get-XASessionPrinter
Get-XASessionProcess
Get-XAStreamingSession
Get-XAVirtualIPRange
Get-XAZone

Verb: Import
Name
—-
Import-XALegacyApplication
Import-XAPrintServer

Verb: Move
Name
—-
Move-XAApplication
Move-XAFolder
Move-XAServer

Verb: New
Name
—-
New-XAAdministrator
New-XAApplication
New-XAAutoReplicatedPrinterDriver
New-XAClientPrinter
New-XAFolder
New-XAHmrTest
New-XAIcaFile
New-XALoadEvaluator
New-XAPolicy
New-XAPrinterDriverCompatibility
New-XAPrinterDriverMapping
New-XAVirtualIPRange

Verb: Remove
Name
—-
Remove-XAAdministrator
Remove-XAAdministratorPrivilege
Remove-XAApplication
Remove-XAApplicationAccount
Remove-XAApplicationFileType
Remove-XAApplicationServer
Remove-XAAutoReplicatedPrinterDriver
Remove-XAClientPrinter
Remove-XAFolder
Remove-XAHmrTest
Remove-XALoadEvaluator
Remove-XALoadEvaluatorServer
Remove-XAPolicy
Remove-XAPrinterDriverCompatibility
Remove-XAPrinterDriverMapping
Remove-XAPrintServer
Remove-XAServer
Remove-XASessionPrinter
Remove-XAVirtualIPRange

Verb: Rename
Name
—-
Rename-XAApplication
Rename-XAFolder
Rename-XAHmrTest
Rename-XALoadEvaluator
Rename-XAPolicy
Rename-XAZone

Verb: Replicate
Name
—-
Replicate-XAPrinterDriver

Verb: Reset
Name
—-
Reset-XAClientPrinter

Verb: Send
Name
—-
Send-XASessionMessage

Verb: Set
Name
—-
Set-XAAdministrator
Set-XAAdministratorFolder
Set-XAApplication
Set-XAFarmConfiguration
Set-XAHmrTest
Set-XALoadEvaluator
Set-XAPolicy
Set-XAPolicyConfiguration
Set-XAPolicyFilter
Set-XAPrinterDriverCompatibility
Set-XAPrinterDriverMapping
Set-XAServerConfiguration
Set-XAServerEdition
Set-XAServerZone
Set-XASessionPrinter

Verb: Stop
Name
—-
Stop-XASession
Stop-XASessionProcess

Verb: Test
Name
—-
Test-XAConfigurationLog
Test-XALicenseServer

Verb: Update

Name
—-
Update-XAFileType
Update-XAPrinter

My R2/Win7 Experience

I have now been using Windows 2008 R2 for 2 months and Windows 7 client for about a month (two weeks on my production laptop) and I have to say I am thoroughly impressed. I have beta tested every MS OS since 2000 and this is the first time I can honestly say I am excited.

Lets start with Window 2008 R2.
This OS is rock solid. They could release it now and I think it would fair very well. It has enough of a feature increase it is worth the upgrade. I was impressed with 2008 but R2 simply blows it away. It is quicker and I love the taskbar. I am a bit OCD when it comes to my computer and R2 caters to this quite nicely. I wouldn’t be fooling anyone if I didn’t say I was excited about the native Powershell support, but I think that goes without mention. All and all… it is has exceeded any expectations I had. I haven’t had a chance to play with the advance functionality that was introduced, but I plan to get to that this week.

The client…
All I can say is WOW! I think this is first time MS changed the interface in a way that was simply just better. We all know MS has a way of changing the interface that drives people crazy, but this time the changes are relatively noninvasive and worth the aggravation of learning. They truly help efficiency and finally allow keyboard jockeys to put down the mouse and move seamlessly around the screen and apps with keyboard strokes. Some of the new changes seem trivial and just eye candy, but once you get a hold of the usefulness of the new GUI it will change the way you use your computer. GUI changes aren’t the only thing that is noticeable in Win7, the performance is awesome and everything seems snappier. I haven’t got to use the enterprise usability yet, but I hope to get a beta going at work.

Both
The last thing and this goes for both R2/Win7 is User Account Control (UAC.) This was introduced in Vista and while the idea was good, the execution was… ummmm, less than grand. The new OS’s continue down the UAC path (as they should) but have made the process more intelligent and it doesn’t annoy you as much.

The Future
These products are both Beta1 and I would guess a year or so off, but if the final product is even as good as the beta… it will be awesome. Shortly, I hope to start reviewing all the new Powershell cmdlets (+100) soon.

VMWare and Powershell, The Early Years… The Life Before VMWare Powershell CMDLets

I am on the CTP for the VMWare Powershell Toolkit, and although I am unable to release any Information. I thought it would be a good idea to post some Powershell VMWare commands (old school) before they go live with the REAL Deal.

Hal from TechProsaic wrote a blog post here http://halr9000.com/article/445 about Using Plink to get Information about ESX and creating a custom object for the VM’s that the ESX host currently runs. I really liked the script, but I wanted a little more out of it. So I modified it (sorry Hal) and add some functionality. Below is a list of things it does.

  • Get Virtual Machines Running on ESX Host. Returns Custom Object
  • Provides a similar function to Get-Process from the ESX Host
  • Will Run a generic Command on the ESX Host
  • NOTE: At lines 16/31/62 I am having some issues with syntax highlight changing these to email addresses. Please make user the end up as $user @ $srv (no spaces)

    You can also get a working copy here http://powershellcentral.com/scripts/54

    # Invoke-VMCommand.ps1
    # Purpose     : Run a remote command and return the results
    # Requirements: plink.exe from the Putty project must be in $env:path
    # Use -help parameter for instructions

    Param (
        $VMHost,
        $username,
        $Command,
        [switch]$Help,
        [switch]$Verbose
    )

    # Obtains list of VMX (config files) corresponding to each VM on a given ESX server
    function GetVMX ($user, $pass, $srv) {
        $cmd = "plink.exe $user@$srv -pw $pass"
        $cmd += " vmware-cmd -l"
        Write-Verbose "Command line: $cmd"
        $VMList = Invoke-Expression $cmd
        $collOut = @()
        $VmList | ForEach-Object {
            $objOut = "" | Select-Object VmHost, VmName, VMXpath, HasSnapshot # create our output object with desired properties
            $objOut.VmHost = $srv
            $objOut.VMXpath = $_
            $objOut.VmName = (Split-Path $_ -Leaf) -replace ".vmx$"
            $collOut += $objOut
        }
        $collOut
    }
    function Get-ESXProcess($user, $pass, $srv){
        $cmd =  "plink.exe -t $user@$srv -pw $pass "
        $cmd += "`"ps -Af | grep `’`’`""
        Write-Verbose "Command line: $cmd"
        $results = invoke-Expression $cmd
        $colObj = @()
        foreach($result in $results)
        {
            if($result -match "^UID"){continue}
            $myobj = "" | Select-Object UID,PID,PPID,C,STIME,TTY,TIME,CMD
            $ary = $result.split([string[]]" ",[System.StringSplitOptions]::RemoveEmptyEntries)
            $myobj.UID   = $ary[0]
            $myobj.PID   = $ary[1]
            $myobj.PPID  = $ary[2]
            $myobj.C     = $ary[3]
            $myobj.STIME = $ary[4]
            $myobj.TTY   = $ary[5]
            $myobj.Time  = $ary[6]
            $proc = $null
            write-verbose "Length: $($ary.Length)"
            for($i = 7;$i -le $ary.Length;$i++)
            {
                $proc = "$proc $($ary[$i])"
                write-Verbose "Adding [$i] $($ary[$i])"
            }
            Write-Verbose "COMMAND = $proc"
            $myobj.CMD   = $proc
            $colObj += $myobj
        }
        $colObj
    }
    function RunVMCommand ($user, $pass, $srv, $vmcmd) {
        $cmd = "plink.exe $user@$srv -pw $pass "
        $cmd += "`"$vmcmd | grep `’`’`""
        Write-Verbose "Command line: $cmd"
        invoke-Expression $cmd
    }
    function GetSecurePass ($SecurePassword) {
      $Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($SecurePassword)
      $password = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($Ptr)
      [System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($Ptr)
      $password
    }

    # Returns help text
    function ShowUsage {
      $helptext = @"

    Invoke-VMCommand
      Requirements: plink.exe from the Putty project must be in your Path

    INPUT:

      VMHost     : name or IP of ESX server(s) (REQUIRED)
      UserName   : User to ssh With (REQUIRED)
      Command    : Command to Run. This can be a GetVMX, PSList, or a Custome String (REQUIRED)
      Help       : shows usage

    "@
      Write-Host $helptext
    }

    # Main
    if ($help) { ShowUsage; exit; }
    if ($verbose) { $verbosepreference = "continue" }

    $password = (Read-Host "Enter Password" -AsSecureString)

    if($Command -eq "GetVMX"){GetVMX $username (GetSecurePass $password) $VMHost}
    elseif($command -eq "PSList"){Get-ESXProcess $username (GetSecurePass $password) $VMHost}
    else{RunVMCommand $username (GetSecurePass $password) $VMHost $Command}

    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

    ##########################################
    ####     Citrix Server Functions      ####
    ##########################################

    ## Publish Application to Server(s)
    ## -app: Name of Application to remove. This is required
    ## -Server: Name of Server
    ## PIPED: It will take Servers via Pipe. It expects a list or Citrix Server Object
    ## NOTE: App Name must include subfolders of the app.
    ##       If the app in in Applications\Test then app would be Test\MyApp
    ##       Example: Publish-CitrixApplication -server myserver -app Test\MyApp
    function Publish-CitrixApplication{
        Param([string]$server,[string]$app)
        Begin{
            Write-Host
            function gcs{
                Param($srv)
                $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$Server)
                $mfServer = [system.Activator]::CreateInstance($type)
                $mfServer.Initialize(6,$Server)
                $mfServer
            }
            function gca{
                Param($srv,$ma)
                $type = [System.Type]::GetTypeFromProgID("MetaFrameCOM.MetaFrameApplication",$Server)
                $mfApp = [system.Activator]::CreateInstance($type)
                $mfApp.Initialize(3,"Applications\$ma")
                $mfApp.LoadData($true)
                $mfApp
            }
            function cPublish {
                Param([string]$Srv,[string]$myapp)
                $Srv = $Srv.toUpper()
                $mfSrv = gcs $srv
                $mfApp = gca $srv $myapp
                $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
                }
            }
            $process = @()
        }
        Process{
            if($_){
                if($_.ServerName){
                    $process += $_.ServerName
                }
                else{
                    $process += $_
                }
            }
        }
        End{
            if($Server){$Process += $Server}
            foreach($s in $process){
                cPublish -srv $s -myapp $app
                Write-Host
            }
        }
    }

    ## UnPublishes ALL Application from Server(s)
    ## -Server: Name of Server
    ## PIPED: It will take Servers via Pipe. It expects a list or Citrix Server Object
    function UnPublish-CitrixServer{
        Param([string]$server)
        Begin{
            function gcs{
                Param($srv)
                $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$Server)
                $mfServer = [system.Activator]::CreateInstance($type)
                $mfServer.Initialize(6,$Server)
                $mfServer
            }
            function cUnPublish {
                Param([string]$Srv)
                $Srv = $Srv.toUpper()
                $mfSrv = gcs $srv
                If($mfSrv.Applications.Count -gt 0)
                {
                    Write-Host "Removing All Published Applications from $Srv" -ForegroundColor Red
                    Write-Host "===================================================" -ForegroundColor Green
                    ForEach($a in $mfSrv.Applications)
                    {
                        $myApp = $a.AppName
                        Write-Host "Removing App [$myApp] from Server [$Srv]" -ForegroundColor White
                        $a.RemoveServer($Srv)
                        $a.SaveData()
                    }
                }
                else
                {
                    Write-Host "No Published Applications for $Srv" -ForegroundColor Red
                }
            }
            Write-Host
            $process = @()
        }
        Process{
            if($_){
                if($_.ServerName)
                {
                    $process += $_.ServerName
                }
                else
                {
                    $process += $_
                }
            }
        }
        End{
            if($Server){$Process += $Server}
            foreach($s in $process){
                cUnPublish $s
                Write-Host
            }
        }
    }

    ## Remove Specific Application from Server(s)
    ## -app: Name of Application to remove. This is required
    ## -Server: Name Server.
    ## PIPED: It will take Servers via Pipe. It expects a list or Citrix Server Object
    function Remove-CitrixApplication {
        Param([string]$server,[string]$app)
        Begin{
            function gcs{
                Param($srv)
                $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeServer",$Server)
                $mfServer = [system.Activator]::CreateInstance($type)
                $mfServer.Initialize(6,$Server)
                $mfServer
            }
            function RemoveApp {
                Param([string]$Srv,[string]$myapp)
                $AppRemoved = $false
                $Srv = $Srv.toUpper()
                $mfSrv = gcs $srv
                If($mfSrv.Applications.Count -gt 0)
                {
                    ForEach($a in $mfSrv.Applications)
                    {
                        If(($a.AppName -eq "$myapp") -or ($a.BrowserName -eq "$myapp"))
                        {
                            Write-Host "Removing App [$myApp] from Server [$Srv]" -ForegroundColor Green
                            $a.RemoveServer($Srv)
                            $a.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
                }
            }
            Write-Host
            $process = @()
        }
        Process{
            if($_)
            {
                if($_.ServerName){

                    $process += $_.ServerName
                }
                else
                {
                    $process += $_
                }
            }
        }
        End{
            if($Server){$Process += $Server}
            if($process.Length -eq 0){$Process += get-content env:COMPUTERNAME}
            foreach($s in $process)
            {
                RemoveApp -Srv $s -myapp $app
                Write-Host
            }
        }
    }

    Citrix App Functions

    #########################################
    ####     Citrix App Functions        ####
    #########################################
    ## Returns Citrix Application for Farm
    ## -Server: Name of Farm Server. This is required
    ## -App: Name of Application to remove. This is required
    function Get-CitrixApp{
        Param($Server =$(throw ‘$Server is Required’),$App= $(throw ‘$FarmServer is Required’))
        $type = [System.Type]::GetTypeFromProgID("MetaFrameCOM.MetaFrameApplication",$Server)
        $mfApp = [system.Activator]::CreateInstance($type)
        $mfApp.Initialize(3,"Applications\$myapp")
        $mfApp.LoadData($true)
        $mfApp
    }

    ## Returns Users currently using APP
    ## -app: Name of Application. This is required
    ## -Server: Name of Farm Server. Defaults to local if not passed
    ## -count: Switch… if set just returns count of servers
    function Get-CitrixAppUsers {
        Param($app = $(throw ‘$app is required’),$server,[switch]$count)
        function gcf{
            param($srv)
            $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeFarm",$Server)
            $mfarm = [system.Activator]::CreateInstance($type)
            $mfarm.Initialize(1)
            return $mFarm
        }
        $ErrorActionPreference = "SilentlyContinue"
        Write-host
        if($server){$mfm = gcf $server}
        else{$mfm = New-Object -com MetaFrameCOM.MetaFrameFarm;$mfm.Initialize(1)}
        $users = $mfm.Applications | ?{($_.AppName -eq $app) -or ($_.BrowserName -eq $app)}
        $Users = $users.Sessions | sort -Property UserName
        if($count){
            Write-Host "Found [$($Users.Count)] Users for Application [$app]" -ForegroundColor White
            Write-Host
        }
        else{
            Write-Host ""
            Write-Host "Found [$($Users.Count)] Users for Application [$app]" -ForegroundColor White
            Write-Host "—————————————————–" -ForegroundColor gray
            foreach($user in $Users){
                If($User.SessionState -eq 1){
                    Write-Host ($User.UserName).PadRight(10) -ForegroundColor Green -NoNewline
                }
                else{
                    Write-Host ($User.UserName).PadRight(10) -ForegroundColor yellow -NoNewline
                }
            }
            Write-Host
            Write-Host "—————————————————–" -ForegroundColor gray
            Write-Host "Found [$($Users.Count)] Users for Application [$app]" -ForegroundColor White
            Write-Host
        }
    }

    ## Returns Servers currently published APP
    ## -app: Name of Application. This is required
    ## -Server: Name of Farm Server. Defaults to local if not passed
    ## -count: Switch… if set just returns count of servers
    function Get-CitrixAppServers {
        Param($app = $(throw ‘$app is required’),$Server,[switch]$count)
        function gcf{
            param($srv)
            $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeFarm",$Server)
            $mfarm = [system.Activator]::CreateInstance($type)
            $mfarm.Initialize(1)
            return $mFarm
        }
        if($server){$mfm = gcf $server}
        else{$mfm = New-Object -com MetaFrameCOM.MetaFrameFarm;$mfm.Initialize(1)}
        $Apps = $mfm.Applications | ?{($_.AppName -eq $app) -or ($_.BrowserName -eq $app)}
        # for XP farms
        $servers = $apps | %{$_.Servers} | sort -Property ServerName | Select-Object ServerName
        if(!$servers){
            # for 40/45 farms
            $servers = $Apps.Sessions | Select-Object ServerName | Sort-Object -unique ServerName
        }
        if($count)
        {
            Write-Host
            Write-Host "Found [$($Servers.Count)] Servers for Application [$app]" -ForegroundColor White
            Write-Host
        }
        else
        {
            Write-Host ""
            Write-Host "Found [$($Servers.Count)] Servers for Application [$app]" -ForegroundColor White
            Write-Host "———————————————–" -ForegroundColor gray
            foreach($server in $servers){Write-Host "$($server.ServerName)" -ForegroundColor Green}
            Write-Host "———————————————–" -ForegroundColor gray
            Write-Host "Found [$($Servers.Count)] Servers for Application [$app]" -ForegroundColor White
            Write-Host ""
        }
    }

    ## Returns Server(s) user is logged into via Citrix
    ## -LoginName: Login Name of user (Domain\User). This is Required
    ## -Server: Name of Farm Server. Defaults to local if not passed
    ## -Verbose: Details about User
    function Find-CitrixUser {
        Param([string]$LoginName,$Server,[switch]$verbose)
        $user = $LoginName.Split("\")[1]
        $Domain = $LoginName.Split("\")[0]
        if($server)
        {
            $type = [System.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeUser",$Server)
            $mfuser = [system.Activator]::CreateInstance($type)
            $mfuser.Initialize(1,$Domain,1,$user)
        }
        else
        {
            $mfuser = New-Object -ComObject MetaframeCOM.MetaframeUser
            $mfuser.Initialize(1,$Domain,1,$user)
        }
        Write-Host
        Write-Host "User: $($mfuser.UserName) found on the Following:"
        foreach ($s in $mfuser.Sessions)
        {
            if($verbose)
            {
                Write-Host
                Write-Host "$($s.ServerName)"
                Write-Host "-=-=-=-=-=-"
                Write-Host "AppName          : $($s.AppName)" -foregroundcolor yellow
                Write-Host "SessionName      : $($s.SessionName)" -foregroundcolor yellow
                Write-Host "SessionID        : $($s.SessionID)" -foregroundcolor yellow
                Write-Host "ClientAddress    : $($s.ClientAddress)" -foregroundcolor yellow
                Write-Host "ClientEncryption : $($s.ClientEncryption)" -foregroundcolor yellow
                Write-Host
                Write-Host "Processes"
                Write-Host "========="
                foreach ($proc in $s.Processes)
                {
                    Write-Host $proc.ProcessName -foregroundcolor Green
                }
                Write-host
            }
            else
            {
                write-Host "   -> $($s.ServerName)"
            }
        }
    }