Archive: ‘Citrix’ Category

Thoughts on Server 2012 R2 Scale-out File Server and Provisioning Services

1 comment September 17th, 2013

When I read about all the new features and enhancements that comes with the Windows Server 2012 R2 release, I started to realize how much of it could be used to optimize and save costs when used in a PVS platform. Ill try to go through a few of the enhancements and features and share my thoughts of how they could be used.

Failover Clustering and Scale-out File Server

Ive never been a fan of Microsoft Clustering. The experiences i have and what ive heard from others using it is thats its very cumbersome to manage and troubleshoot. When something goes wrong its a pain to get it working again.
Well with failver clustering and Scale-out File server in server 2012 this seems to have been improved.

Now you have features like Cluster-Aware Updating that enables software updates to be applied automatically to the operating system or other system components on the nodes of a failover cluster while maintaining availability during the update process. This will reduce maintenance time by automating what was previously a very repetitive task.

With the introduction om SMB 3.0 and Storage Spaces you get performance, scalability and functionality that used to only be available in big expensive SAN solutions.

The Scale-out File Server (SoFS) role uses SMB 3.0 to enable you to build Active-Active fileclusters. SoFS will automatically redired I/O over SMB to an optimal node in the cluster. When the client connects to a share in the cluster it will connect to any of the nodes. However the file the client wants to open might actually be stored on one of the other nodes in the cluster. SoFS will detect this and automatically transition the SMB connection to the node where the file resides.

With the Server 2012 R2 release Failover Clustering and SoFS also supports data deduplication which can save you lots of storage space when your vDisks are stored on a SoFS share.

Storage Spaces

Until Windows Server 2012 was released, implementing storage virtualization required purchasing proprietary third-party SAN solutions that were expensive and required using their own set of management tools. Such solutions also required special training to implement, manage, and maintain them effectively. Storage Spaces, first introduced in Windows Server 2012, was designed to make storage virtualization affordable even for small businesses. Storage Spaces is simple to deploy and manage, and it can provide businesses with shared storage that can grow on demand to meet an organization’s changing needs.

 With Storage Spaces in Windows Server 2012 R2 Microsoft enables you to create a tiered storage that transparently delivers an appropriate balance between capacity and performance that can meet the needs of enterprise workloads. The result is that the workload’s most frequently accessed data (the working set) will automatically be stored on the SSD tier while the rest of the workload’s data is stored on the HDD tier.

Data deduplication

Data deduplication was introduced in Windows Server 2012 to help enterprises cope with exponentially increasing growth of data storage in their environments. Data deduplication allows Windows Server 2012 to store more data in less physical space to optimize the capacity of their storage fabric. Data deduplication is highly scalable, resource efficient, and nonintrusive in Windows Server 2012, and can run on multiple volumes simultaneously without affecting other workloads running on the server. Checksums, consistency, and identity validation are used to ensure data integrity, and redundant copies of file system metadata are maintained to ensure data is recoverable in the event of corruption.

Sadly this wont help save storage in you PVS environment as you might think. In server 2012 data deduplication can only be used with files that are closed. Your PVS vDisks are likely to be open most of the time as the target devices is running from them.

In server 2012 R2 thou Microsoft added a few improvements to the way data deduplication works. When used in a Failover Cluster data deduplication will work on open files aswell!

SMB 3.0

SMB 3.0 is at the core of the new SoFS functionality introduced previously in Windows Server 2012 and enables file-based storage solutions (file servers) to provide network storage for servers that have similar performance to expensive, proprietary SAN solutions. Using SMB 3.0 and the Windows Server 2012 platform, organizations can build low-cost scale-out storage fabrics that can meet the needs of a broad range of private and hosted cloud solutions.

Some of the key features of SMB 3.0 include:

  • SMB Scale Out
    Allows you to create file shares using Cluster Shared Volumes (CSV) to provide simultaneous access to data files, with direct I/O, through all nodes in a file server cluster. This results in improved utilization of network bandwidth, load balancing of SMB 3.0 clients, and optimized performance for server applications.
  • SMB Transparent Failover
    Allows you to perform hardware or software maintenance of nodes in a clustered SMB 3.0 file server (an SoFS) without interruption to server applications storing data on the file shares. If a hardware or software failure occurs on a cluster node, SMB 3.0 clients can transparently reconnect to another cluster node without interruption as well.
  • SMB Direct
    Supports using network adapters that have Remote Direct Memory Access (RDMA) capability, which allows them to function at full speed with very low latency and very low CPU utilization. When used with workloads, such as Hyper-V or SQL Server, the result is that a remote SMB 3.0 file server can resemble local storage in its performance.
  • SMB Multichannel
    Provides aggregation of network bandwidth and network fault tolerance when multiple paths are available between the SMB 3.0 client and the SMB 3.0 file server. This results in server applications taking full advantage of all available network bandwidth and being more resilient to network failure.

All these features boosts the SMB protocol performance significantly when used with supported hardware and adds resiliancy with multichannel and transparent failover. This for me takes the SMB protocol into the cloud era and enables it to be used in more critical infrastructural functions while still being easy to mange and setup.

If you put all this together and build a SoFS cluster to store your vDisks you get a centralized vDisk store and dont need to sync your vDisks between servers using local storage. You will save even more storage with deduplication as the vDisks is likely to be very similar to eachother.

Windows Server 2012 R2 SoFS is an inexpensive, valid and fully featured storage solution that can compete with many enterprise storage solutions out there.

There are many more features and enhancements in the new R2 release i havnt talked about as i think these are the most important ones that relate to Provisioning Services.

Problems with Internet Explorer when running seamless sessions, but working from Desktop

2 comments January 16th, 2013

So ive been running into this problems a few times, it started when xenapp 6 was released enabling to run citrix on server 2008. The problem occurs a new profile is created, ie new user or profile wipe, and running seamless applications. Mostly its affecting Internet Explorer, but can in some cases also affect other applications. When the user surfs the internet/intranet or to sites using addons/plugins to IE, IE behaves mysteriously, gpo settings might not be applied to the user, trusted sites dont work or IE security zones looks corrupt. But if you publish a desktop to the user it works fine, and after the user have logged on to the desktop the seamless apps starts behaving correctly as well. Its only affecting users who use seamless apps and not yet logged in and used a desktop session.

The reason for this behavior is because when you run a seamless session, your not using explorer as a shell. And when the profile is created it needs the explorer process to create lots of stuff that is needed by IE among others.

You can easily test this yourself. If you publish something like notepad or Internet Explorer to a user with no profile yet created. When that user has started the application and the profile is created you can have a look into his registry here:

Software/Microsoft/Windows/CurrentVersion/Internet Settings

There is going to be a few keys here but if you compare to a user that has started a desktop session its lots more. It wont create the security zones or trusted sites settings needed to use trusted sites.

A quick fix is to just push the Internet Settings key to your users if your not publishing a Desktop. But i would be careful using this and go through every key to see what i would need and not need on my platform.

Microsoft has a KB about this problem aswell where you run “runonce.exe /AlternateShellStartup” when the user logs on. And supposedly creates all the registry settings as if you would use explorer as a shell. I say supposedly because i havnt verified it. KB951048

Citrix has an article about this as well with the same solution so it should be a working solution. CTX127874

This will affect applications in your environment that relies on internet settings such as security zones like connecting to intranet sites or even cifs shares that should be trusted intranet sites.

 

Netscaler authentication based on nested groups

2 comments November 23rd, 2012

So i needed to create an LDAP authentication policy in the Netscaler where the users are divided into different groups (DEPT1, DEPT2, DEPT3), and those groups are themselves inside a group (MAINGRP). So i want to authenticate the users based on nested membership in MAINGRP.

Netscaler LDAP dialogue

Normally without nested groups you would use a LDAP filter with something like this:

memberOf=CN=DEPT1,OU=users,OU=subou,OU=ou,DC=domain,DC=com

Which would return a result to the Netscaler if the user were a member of that group.

But how would you go about if your user is in a nested group? Then you also need to find out if one of the groups the user is a member of is itself a member of the specified group. My first thought was to use the nested groups feature in the Netscaler LDAP auth dialogue. So I configured it to use 2 nested levels and the same kind of filter here as on the user. Sadly this didnt work, it turns out that the nested groups part is ONLY for authorization and not authentication. What this means is on the first part the user authenticates and if you have a filter it returns whatever you configured your filter to return. If it doesnt return anything, like a group, your not allowed to login. Once this is done the Netscaler will use the returned result and pars through it and do additional LDAP querys to find the nested groups, and by then the user is already authenticated. The result from the nested groups parsing is then passed on to whatever logic you have in AAA or session policys to do with what you want for authorization.

This meant that in order to use nested groups for authentication i needed to extract the nested group in the first filter and this is how you would do that:

memberOf:1.2.840.113556.1.4.1941:=CN=MAINGRP,OU=subou,OU=ou,DC=domain,DC=com

By using something called OID in the LDAP query you will make LDAP do the parsing of the nested groups and return a result if it finds the group you are looking for.

from Microsoft Technet:

1.2.840.113556.1.4.1941 LDAP_MATCHING_RULE_IN_CHAIN This rule is limited to filters that apply to the DN. This is a special “extended match operator that walks the chain of ancestry in objects all the way to the root until it finds a match.

And there you go!

XenClient and Provisioning Services

1 comment January 28th, 2011

So! I was supposed to go and have a lecture on Provisioning Services a few weeks ago and i needed a demo. As im running XenClient on my laptop, and with the SP1 update XenClient gets support to provisioning services! So i thought why not set up an internal Provisioning Server on my XenClient? How hard can it be!

Well it wasnt that hard, you just need a little bit of Linux knowlege to be able to do it!

I started out by installing a Server 2003 with provisioning services, only problem I had with this was to get XenClient tools installed but it works good.  I configured local storage and the PVS server was up and running. Oh and i also installed the Licens Server, to be able to get licensing going for the PVS.

I had to decide on which network to use for provisioning thou, i dont want it spam dhcp stuff outside of my laptop, so first i thought hey lets use the internal network option in xenclient to isolate the network. Turns out there is a bug thou in XenClient that wont turn on the internal network unless there is a cable plugged in the physical network port. That sucked! What about the wireless?

In xenclient all guests share the wireless and they all get an internal address, so it suited me fine! Now all i needed to do was to add the dhcp options to the internal dhcp server. XenClient uses dnsmasq as a dhcp server and dns forwarder.  All i needed to do was to edit /etc/dnsmasq.brwireless and add the options there! Awesome. So now all i need to do is install a Master Target Device!

I created a new guest, called it MTD and installed XP on it. When it was finished I installed the PVS tools to make an image of it and runned the wizard. Of course i configured the guest to also use the wireless network. It prepared XP to be sucked into PVS and rebooted. When it was rebooting I turned it of and set it to only boot on network. Started it again, crossed my fingers and waited for it to boot on the network. It started good I saw it got the bootfilename to boot from, but it wouldnt boot! It timed out all the time. When i looked closer it tried to boot from the PVS netboot image, but from the wrong server! The ip i had specified in the dhcp-option wasnt used. It tried to connect to xxx.xxx.xxx.1 which is the XenClient host OS. After some fiddling around with dnsmasq and confirming that i entered the correct ip to the PVS server i found somewhere on google that some networkcards have problems with that option. And they default to dhcp server. This meant i couldnt get it to boot from the PVS unless the PVS was the dhcp server!

Well no problem, i disabled dhcp part of dnsmasq and installed the builtin dhcp-service from windows and configured it with the same options. Tried to boot the MTD again and voila! I was making a Golden Image of my XP!

All i had to do then was to create a new guest, called it TD1 and make it boot from the network! I had to make a local drive to the guest as you have to create a disc with every XenClient guest. But made it just 1 gb so thats no biggie.

So now i have my laptop running a provisioned XP client wherever i go. Im going to make a win7 guest that i can use as my private image. This works really good and as im a consultant can use a clean image at every new job!

Downsides thou that i havnt had time yet to work out, shouldnt be a problem thou, is that i always have to be connected to a wireless network as the guest will thing the network is disabled otherwise! But all i need to do is to figure out how to activate the network manually. Or wait until citrix fixes that bug to be able to use the dedicated internal network!

VB script to get VirtualIP

3 comments January 26th, 2011

I built this script to get the virtual ip of the usersession as i needed to send that to the application when the user started. I built two versions of it one using mfcom, the user needs to have certain admin rights in the farm to get this going which I dont like, and the other uses WMI and the registry to figure it out. Its not perfect and should be modified to fit your situation. It will only get the last sessions virtualip, as thats all i needed. So if the user has 2 sessions going you will only get the last one of them.

It is very not documented as i was in abit of rush writing it. Sorry for that! =)

** Updated with bug fix discussed in the comments thnx Augustin **

Here is the script (sesInfo.vbs):

‘ Written by Roger Eklund (roger.eklund at envokeit.com)
‘ Use at your own risk!
‘ To get the Client Virtual IP run “sesInfo.vbs ip”
‘ To get the Client hostname run “sesInfo.vbs clientname”

Const HKCR = &H80000000 ‘HKEY_CLASSES_ROOT
Const HKCU = &H80000001 ‘HKEY_CURRENT_USER
Const HKLM = &H80000002 ‘HKEY_LOCAL_MACHINE
Const HKU  = &H80000003 ‘HKEY_USERS
Const HKCC = &H80000005 ‘HKEY_CURRENT_CONFIG
Const REG_SZ        =1
Const REG_EXPAND_SZ =2
Const REG_BINARY    =3
Const REG_DWORD     =4
Const REG_MULTI_SZ  =7
Const MetaFrameWinFarmObject = 1
Const MetaFrameWinSrvObject = 6
Const Active=1
Const Connected=2
SessionID=GetSessionID

args = WScript.Arguments.Count

If args < 1 then
WScript.Echo “usage: sesInfo.vbs [ip|clientname]”
wscript.echo “Will get either VirtualIP of the client”
wscript.echo “or the Clientname”
WScript.Quit
end If

choice = ucase(wscript.arguments.item(0))

Select Case choice
Case “CLIENTNAME”
hkey=HKU
Set oReg = GetObject( “winmgmts:!root/default:StdRegProv” )
curUser = GetCurrentUser(“.”)
uSid = GetSIDFromUser(curUser)
wscript.echo vbCrLf & GetVal(hkey,uSid+”\Volatile Environment” , “CLIENTNAME”)
Case “IP”
Set oReg = GetObject( “winmgmts:!root/default:StdRegProv” )
hkey=HKLM
path = “SOFTWARE\Citrix\VIP\” & SessionID
Vip = GetVal(hkey,path , “VIPAddress”)
wscript.echo hex2ip(Vip)
Case Else
wscript.echo “omg”
End Select
Function hex2ip(hex)
Dim oct1
Dim oct2
Dim oct3
Dim oct4
Dim IPadress

If len(hex) = 7 Then
hex = “0″ & hex
end if

if len(hex) > “8″ or len(hex) < “8″ Then
wscript.echo “Not a Hex number: ” & hex
wscript.quit(0)
end if

oct1 = (Mid(hex, 1, 2))
oct2 = (Mid(hex, 3, 2))
oct3 = (Mid(hex, 5, 2))
oct4 = (Mid(hex, 7, 2))
hexNumber1 = “&H” & oct1
hexNumber2 = “&H” & oct2
hexNumber3 = “&H” & oct3
hexNumber4 = “&H” & oct4
int1 = CLng(hexNumber1)
int2 = CLng(hexNumber2)
int3 = CLng(hexNumber3)
int4 = CLng(hexNumber4)
hex2ip = int1 & “.” & int2 & “.” & int3 & “.” & int4
End Function
Function convertIP(BinIP)

Dim x
Dim Num
Dim IPNumeric
Dim IPAddy

IPNumeric = BinIp

For x = 1 To 4

Num = int(IPNumeric / 255 ^ (4 – x))
IPNumeric = IPNumeric – (Num * 255 ^ 4 – x)

If Num > 255 Then
IPConvert = “0.0.0.0″
wscript.echo(“fail” & Num)
wscript.quit
End If

If x = 1 Then
IPAddy = Num
Else
IPAddy = IPAddy & “.” & Num
End If

Next
convertIP=IPAddy

End Function
Function GetVal( strHive, strTree, strKey )

‘ Read all keys and their values for the entire section into an array
If oReg.EnumValues( strHive, strTree, sKeys, iKeyType ) Then
GetVal = “-None-”
Else
For Count = 0 to UBound( sKeys )
‘ Select the requested key
If strKey = sKeys( Count )  Then
‘ Format the output

Select Case iKeyType( Count)
Case REG_SZ
oReg.GetStringValue strHive, strTree, sKeys( Count ), sValue
GetVal = sValue
Case REG_EXPAND_SZ
oReg.GetExpandedStringValue strHive, strTree, sKeys( Count ), sValue
GetVal = sValue
Case REG_BINARY
oReg.GetBinaryValue strHive, strTree, sKeys( Count ), aValue
GetVal =  Join( aValue,”” )
Case REG_DWORD
oReg.GetDWORDValue strHive, strTree, sKeys( Count ), lValue
GetVal = hex(lValue)
Case REG_MULTI_SZ
oReg.GetMultiStringValue strHive, strTree, sKeys( Count ), sValue
GetVal =  Join( sValue,”” )
End Select
End If
Next
GetVal = GetVal
End If
End Function

Function GetCurrentUser(sstrComputer)
On Error Resume Next
Dim sstrKeyPath,sstrCU,sstrCUD,sstrCurrentUser,sstrCurrentUserDomain
sHKEY_LOCAL_MACHINE = &H80000002
Set sobjRegistry = GetObject(“winmgmts:\\” & sstrComputer & “\root\default:StdRegProv”)
sstrKeyPath = “SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon”
sstrCU = “DefaultUserName”
sstrCUD = “DefaultDomainName”
sobjRegistry.GetStringValue sHKEY_LOCAL_MACHINE, sstrKeyPath, sstrCU, sstrCurrentUser
sobjRegistry.GetStringValue sHKEY_LOCAL_MACHINE, sstrKeyPath, sstrCUD, sstrCurrentUserDomain
GetCurrentUser = sstrCurrentUserDomain & “\” & sstrCurrentUser
End Function
Function GetSIDFromUser(UserName)

Dim DomainName, Result, WMIUser
If InStr(UserName, “\”) > 0 Then
DomainName = Mid(UserName, 2, InStr(2,UserName, “\”) -2)
UserName = Mid(UserName, InStr(2, UserName, “\”) + 1)
Else
DomainName = CreateObject(“WScript.Network”).UserDomain
End If
On Error Resume Next
Set WMIUser = GetObject(“winmgmts:{impersonationlevel=impersonate}!” _
& “/root/cimv2:Win32_UserAccount.Domain=’” & DomainName & “‘” _
& “,Name=’” & UserName & “‘”)
If Err = 0 Then Result = WMIUser.SID Else Result = “”
On Error GoTo 0
GetSIDFromUser = Result
End Function
Function GetSessionID()
Dim TheFarm, TheSession, TheSession2
Dim sessionID, strComputerName
SessionID = -1

Set objWSHNet = CreateObject(“WScript.Network”)
strServerName = objWSHNet.ComputerName
Set TheFarm = CreateObject(“MetaFrameCOM.MetaFrameFarm”)
theFarm.Initialize(MetaFrameWinFarmObject)
Set TheSession = theFarm.GetSession(MetaFrameWinSrvObject, strServerName, SessionID)
strSessionID = TheSession.SessionID
GetSessionID = strSessionID
End Function

KB975777: There is a delay when you shut down, restart, or log off a computer that is running Windows 7 or Windows Server 2008 R2

No comments October 14th, 2010

If your users are having trouble loging out form your servers, getting the message

1 program still needs to close:
(Waiting for) Task Host Window

Then this KB is for you. This will patch taskhost.exe to handle the problem.

From the KB article:

Symptoms:

Consider the following scenario:

  • You have a computer that is running Windows 7 or Windows Server 2008 R2.
  • You try to shut down, restart, or log off the computer.

In this scenario, the logoff process stops for about six seconds. Additionally, you receive the following message:
1 program still needs to close:
(Waiting for) Task Host Window
Cause:
This problem occurs because the TaskHost.exe process stops handling messages during system shutdown, during system restart, and during system logoff.

Here is the link to the KB.

HOWTO: Remove Favorites from Explorer Folder View

No comments October 14th, 2010

This is how you remove the Favorites Link in the explorer folder view:

  1. Open regedit and go to [HKEY_CLASSES_ROOT\CLSID\{323CA680-C24D-4099-B94D-446DD2D7249E}\ShellFolder]
  2. Open regedit and go to [HKEY_CLASSES_ROOT\CLSID\{323CA680-C24D-4099-B94D-446DD2D7249E}\ShellFolder]
  3. In “ShellFolder” go to ‘Attributes’ and change the value from 0xa0900100 to 0xa400100. (Or to 0xa9400100)
  4. Reboot your machine. If everything is done correctly “Favorites” should now be disabled completely when your system is rebooted.

Enjoy

UPM using 100% cpu

1 comment October 8th, 2010

I have seen the UPM taking 100% cpu a few times, or taking 100% cpu from one core as its not multi-threaded. In all of the cases a corrupt UPM cache file was the problem. Its located in C:\Program Files\Citrix\User Profile Manager and called “UserProfileManager_C.cache”. I just deleted it and restarted the UPM service and problem solved.

Im thinking of making a policy that deletes that file on every reboot as its only a cache file and it wont make a difference if its not there when the UPM starts, as it creates a new one when it needs it.

Citrix on VMWare

No comments October 8th, 2010

I ran into a problem with one of my servers on vmware the other day. HGFS, vmware shared folders, was activated for some reason. The symptoms was that the desktop background image disappeared after each log off which made the user always get a black background every time he logged on. I also noticed that it never deleted any profiles from the server. So when you logged on it just created a new one like user.dom.000 and next time user.dom.001 and so on. To diagnose the problem i turned full logging on in the UPM. I found this:

DeleteAnyFile: Deleting the file <C:\Users\user.dom.013\AppData\Local\VMware\hgfs.dat> failed with: The process cannot access the file because it is being used by another process.

I started google it and found this. Which says how to disable hgfs through the registry.

In the registry find the key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order\ and edit ProviderOrder. Remove hgfs from there and reboot the machine.

After this everything worked perfect.

Create a Set of Default Applications

No comments October 2nd, 2010

Where I work we create a default set of applications to all of our customers. So I wrote this script to do it for me. It can easily be customized to anyones needs if someone wants something similar. This is for Xenapp 6 and needs to be modified to run on Xenapp 5.

Download


cls
Write-Host
Write-Host
Write-Host "#########################################################################################"
Write-Host "## Before you run this scripte there are a few thing you need to have create before. ##"
Write-host "## 1. The officeremotedesktopusers group of the company. ##"
Write-Host "## 2. The officeusers group. ##"
write-host "## 3. a workergroup named after the company. ##"
Write-Host "## 4. And a folder named after the company in the citrix console. ##"
Write-Host "## ##"
Write-Host "## Written By Roger Eklund (gobba@sajberhagen.com) ##"
Write-Host "#########################################################################################"
Write-Host
Write-Host
Write-Host "Allright Lets Start!"
Write-Host
Write-Host "Company name:(Demo) " -NoNewline
$Company = read-host
Write-Host "Upn Suffix:(demo.org) " -NoNewline
$Upn = Read-Host
Write-Host "Server Where applications is installed:(servername) " -NoNewline
$Server = Read-Host

# Desktop
New-XAApplication -ApplicationType "ServerDesktop" -DisplayName "Desktop" -Description "$Company Desktop" -FolderPath "Applications/$Company" -BrowserName "$Company Desktop"
Add-XAApplicationWorkerGroup -BrowserName "$Company Desktop" -WorkerGroupNames $Company
Add-XAApplicationAccount -BrowserName "$Company Desktop" -Accounts "OfficeRemoteDesktopUsers@$Upn"

# Word
$icon = Get-CtxIcon "\\$Server\C$\Program Files (x86)\Microsoft Office\Office12\WINWORD.EXE" -Index 0
New-XAApplication -ApplicationType "ServerInstalled" -DisplayName "Word" -Description "$Company Word" -FolderPath "Applications/$Company" -BrowserName "$Company Word" -CommandLineExecutable '"C:\Program Files (x86)\Microsoft Office\Office12\WINWORD.EXE"' -WorkingDirectory "C:\Program Files (x86)\Microsoft Office\Office12" -EncodedIconData $icon
Add-XAApplicationAccount -BrowserName "$Company Word" -Accounts "OfficeUsers@$Upn"
Add-XAApplicationWorkerGroup -BrowserName "$Company Word" -WorkerGroupNames $Company

# Excel
$icon = Get-CtxIcon "\\$Server\C$\Program Files (x86)\Microsoft Office\Office12\excel.EXE" -Index 0
New-XAApplication -ApplicationType "ServerInstalled" -DisplayName "Excel" -Description "$Company Excel" -FolderPath "Applications/$Company" -BrowserName "$Company Excel" -CommandLineExecutable '"C:\Program Files (x86)\Microsoft Office\Office12\EXCEL.EXE"' -WorkingDirectory "C:\Program Files (x86)\Microsoft Office\Office12" -EncodedIconData $icon
Add-XAApplicationAccount -BrowserName "$Company Excel" -Accounts "OfficeUsers@$Upn"
Add-XAApplicationWorkerGroup -BrowserName "$Company Excel" -WorkerGroupNames $Company

# Outlook
$icon = Get-CtxIcon "\\$Server\C$\Program Files (x86)\Microsoft Office\Office12\OUTLOOK.EXE" -Index 0
New-XAApplication -ApplicationType "ServerInstalled" -DisplayName "Outlook" -Description "$Company Outlook" -FolderPath "Applications/$Company" -BrowserName "$Company Outlook" -CommandLineExecutable '"C:\Program Files (x86)\Microsoft Office\Office12\OUTLOOK.EXE"' -WorkingDirectory "C:\Program Files (x86)\Microsoft Office\Office12" -EncodedIconData $icon
Add-XAApplicationAccount -BrowserName "$Company Outlook" -Accounts "OfficeUsers@$Upn"
Add-XAApplicationWorkerGroup -BrowserName "$Company Outlook" -WorkerGroupNames $Company

# Powerpoint
$icon = Get-CtxIcon "\\$Server\C$\Program Files (x86)\Microsoft Office\Office12\POWERPNT.EXE" -Index 0
New-XAApplication -ApplicationType "ServerInstalled" -DisplayName "Powerpoint" -Description "$Company Powerpoint" -FolderPath "Applications/$Company" -BrowserName "$Company Powerpoint" -CommandLineExecutable '"C:\Program Files (x86)\Microsoft Office\Office12\POWERPNT.EXE"' -WorkingDirectory "C:\Program Files (x86)\Microsoft Office\Office12" -EncodedIconData $icon
Add-XAApplicationAccount -BrowserName "$Company Powerpoint" -Accounts "OfficeUsers@$Upn"
Add-XAApplicationWorkerGroup -BrowserName "$Company Powerpoint" -WorkerGroupNames $Company

# Explorer
$icon = Get-CtxIcon "C:\Windows\explorer.exe" -Index 0
New-XAApplication -ApplicationType "ServerInstalled" -DisplayName "Explorer" -Description "$Company Explorer" -FolderPath "Applications/$Company" -BrowserName "$Company Explorer" -CommandLineExecutable '"C:\Program Files\Internet Explorer\iexplore.exe" -e h:\' -WorkingDirectory "%windir%" -EncodedIconData $icon
Add-XAApplicationAccount -BrowserName "$Company Explorer" -Accounts "OfficeRemoteDesktopUsers@$Upn"
Add-XAApplicationWorkerGroup -BrowserName "$Company Explorer" -WorkerGroupNames $Company

# Internet Explorer
$icon = Get-CtxIcon "C:\Program Files\Internet Explorer\iexplore.exe" -Index 0
New-XAApplication -ApplicationType "ServerInstalled" -DisplayName "Internet Explorer" -Description "$Company Internet Explorer" -FolderPath "Applications/$Company" -BrowserName "$Company Internet Explorer" -CommandLineExecutable "C:\Program Files\Internet Explorer\iexplore.exe" -WorkingDirectory "C:\Program Files (x86)\Internet Explorer\" -EncodedIconData $icon
Add-XAApplicationAccount -BrowserName "$Company Internet Explorer" -Accounts "OfficeRemoteDesktopUsers@$Upn"
Add-XAApplicationWorkerGroup -BrowserName "$Company Internet Explorer" -WorkerGroupNames $Company