Home > Citrix, PowerShell Scripting, XenApp, XenDesktop > Friday Fun: Powershell with Citrix PNAgent.

Friday Fun: Powershell with Citrix PNAgent.

This is something I was playing with for a while. I couldn’t quite get the conversions right without over complicating the script. But as with everything I do, Remko Weijnen, the legend that he is read my mind from afar and published the following fantastic article: Scripting Citrix Online Plugin Settings which basically made my script look like it was written by a two year old!

So with his much improved code I set about writing a script to query the Program Neighbourhood Agent’s applications and launching them too with powershell.

By default, when Program Neighbourhood Agent launches, it populates the Application Model key(s) in HKEY_CURRENT_USER\Software\Citrix\PNAgent.

After the launch, we can use powershell to convert these binary keys into useable data, stick them all together then pull the application details.

With the below script, you can:

Query applications published:

Filter query published applications:

Launch Published applications:

And if you’re crazy, auto launch all applications:


The script can be found after the jump below:

function get-pnapplication {

    $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("CurrentUser", [String]::Empty)
    # Read our Key (with write access)
    $key = $Reg.OpenSubKey("Software\Citrix\PNAgent", $true)

    # Read value as Byte Array
    $key.GetValueNames() | where {$_ -like "application model*"} | %{
        $bytesIn += $Key.GetValue("$_")}

    # Copy the Bytes to a String
    $encode = New-Object System.Text.ASCIIEncoding
    $rawData = $Encode.GetString($bytesIn)

    # Replace spaces in element names with underscores
    $data = $rawData | Foreach-Object {
        [regex]::replace($_,‘<([^>]+)>’,{$args[0] -replace ‘  ‘,‘ ’})

    # Add dummy Root element
    $data = "<root>$data</root>"

    # Load the data into XML Object
    $xml = New-Object Xml.XmlDocument

    foreach ($app in $xml.root.appdata){

        if ($app.details.settings.appisdesktop -eq "true"){$type="Desktop"}
        if ($showdisabled -ne $true){
            if ($app.details.settings.appisdisabled -eq $true){continue}
         $item=new-object PSObject -Property @{
        }#end report
    }#end for

        return $report
}#end function

function start-pnapplication{
        [string]$PnAgentPath="C:\Program Files (x86)\Citrix\ICA Client\pnagent.exe")

    if (!(test-path $Pnagentpath)){write-warning "cannot find Pnagent, breaking"}

    start-process $pnagentpath -ArgumentList "/qlaunch ""$inname"""

  1. February 24, 2012 at 10:46 am

    Nice! And thanks for all the compliments, I am blushing 😀

    May I suggest a small improvement? Read the ICA CLIENT folder location from the registry (HKEY_LOCAL_MACHINE\SOFTWARE(\Wow6432Node)\Citrix\Install\ICA Client instead of hardcoding path.

    Since you are not writing to it you could open the regkey in readonly mode:
    $key = $Reg.OpenSubKey(“Software\Citrix\PNAgent”)

    Keep up the good work!

  2. Gilles
    February 7, 2013 at 10:25 am

    these are very interesting scripts.
    I’d like to use them with pnagent.exe as shell.
    Which process need to be launch first to create the ‘Application Model X’ keys ?


    • February 8, 2013 at 10:28 am

      pnagent launches pnamain which creates the keys.

  1. February 24, 2012 at 3:40 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

<span>%d</span> bloggers like this: