Posts RSS Comments RSS 253 Posts and 408 Comments till now

RE:Blog Geek Speak VDI Vendors Speak Out

This event is going to ROCK! The god of VDI himself (http://www.shawnbass.com) is going to nail the VDI vendors to the wall… well not really but I know for fact he has some good questions for them.

Catch it on March 2, 2010.

More Detail: http://community.citrix.com/display/ocb/2010/02/23/Geek+Speak+Virtual+-Desktop+Virtualization+Vendors+Speak+Out-+March+2+2010

blog: Heads up on an upcoming codeplex project.

Active Directory Replication Module

Purpose:
Provide administrators with simple task-based set of cmdlets to manage and trouble-shoot Active Directory Replication.

Overview:
This will provide several cmdlets for working with Active Directory focusing on Replication. As AD replication is build on domain/forest infrastructure we are also including a set of Domain and Forest management cmdlets.

Target:
Windows 2003 Domain and above (although most cmdlets will still work against 2000.)

Status:
Work as already begun on the project and I am hoping to release alpha code in the next month or so.

Example of cmdlets to be provided (not complete:)
  • Test-ADRReplication
  • Get-ADRDomain
  • Get-ADRDomainController
  • Get-ADRForest
  • Get-ADRGlobalCatalog
  • Get-ADRMetaData
  • Get/Set/Test-ADRProperty
  • Get/Set/New-ADRSite
  • Get/Set/New-ADRSiteLink
  • Get/Set/New-ADRSubNet

Please let us know if there is feature you would like to see or any general feedback.

List of 2008 R2 Group Policy cmdlets

Rick Sheikh asked me about the Windows 2008 R2 GP cmdlets on blog post Build Lab w/ Quest AD CMDLets.

Here is a list (you have to add it via features.) and how to find them

import-module GroupPolicy
Get-Command -Module GroupPolicy | %{$_.Name}

Backup-GPO
Copy-GPO
Get-GPInheritance
Get-GPO
Get-GPOReport
Get-GPPermissions
Get-GPPrefRegistryValue
Get-GPRegistryValue
Get-GPResultantSetOfPolicy
Get-GPStarterGPO
Import-GPO
New-GPLink
New-GPO
New-GPStarterGPO
Remove-GPLink
Remove-GPO
Remove-GPPrefRegistryValue
Remove-GPRegistryValue
Rename-GPO
Restore-GPO
Set-GPInheritance
Set-GPLink
Set-GPPermissions
Set-GPPrefRegistryValue
Set-GPRegistryValue

blog: Getting AD Schema information from Powershell

The other day a friend asked me how I would get Active Directory Schema information using Powershell. I knew of the schema property on the DirectoryServices.ActiveDirectory.Forest class and that is where I started.

Initially I just called the static method GetCurrentForest on the Forest class and then accessed the schema using the property like this.
  1. $Forest = [DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
  2. $Forest.Schema
This worked find and gave me the Schema object I was after but information I got back was minimal. It only returned Schema Role Owner and the Distinguished Name. I found that if you want to get real data like the classes and properties you needed to call methods on object (DirectoryServices.ActiveDirectory.ActiveDirectorySchema) returned from Schema property.

At this point it is not all that complicated but I thought it would be nice to have functions that would abstract all this.

Below is a couple of functions you may find useful. They work both V1 and V2 of Powershell.

Get-Forest : Gets the Forest Object
- DomainController [optional] - DNS Name of the Host to connect to
- Credential [optional] - Network credentials to use.

Get-ADSchema : Gets the Schema
- DomainController [optional] - DNS Name of the Host to connect to
- Credential [optional] - Network credentials to use.

Get-ADSchemaClass : Gets a specific Schema Class
- Class [optional] - Class Object to get (Default is all)
- DomainController [optional] - DNS Name of the Host to connect to
- Credential [optional] - Network credentials to use.

Get-ADSchemaProperty : Gets a specific Schema Property
- Property [optional] - Property to get (Default is all)
- DomainController [optional] - DNS Name of the Host to connect to
- Credential [optional] - Network credentials to use.

NOTE: These will be included in my "Soon to be available" BSONPOSH module (v2 only.)
  1. function Get-Forest
  2. {
  3. Param($DomainController,[Management.Automation.PSCredential]$Credential)
  4.  
  5. if(!$DomainController)
  6. {
  7. [DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
  8. return
  9. }
  10.  
  11. if($Creds)
  12. {
  13. $Context = new-object DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer",$DomainController,$Creds.UserName,$Creds.GetNetworkCredential().Password)
  14. }
  15. else
  16. {
  17. $Context = new-object DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer",$DomainController)
  18. }
  19. [DirectoryServices.ActiveDirectory.Forest]::GetForest($Context)
  20. }
  1. function Get-ADSchema
  2. {
  3. Param($DomainController,[Management.Automation.PSCredential]$Credential)
  4. if($DomainController -and !$Credential)
  5. {
  6. $Forest = Get-Forest -DNSName $DomainController
  7. }
  8. elseif($DomainController -and $Credential)
  9. {
  10. $Forest = Get-Forest -DNSName $DomainController -Credential $Credential
  11. }
  12. else
  13. {
  14. $Forest = Get-Forest
  15. }
  16. $Forest.Schema
  17. }
  1. function Get-ADSchemaClass
  2. {
  3. Param($Class = ".*",$DomainController,[Management.Automation.PSCredential]$Credential)
  4.  
  5. if($DomainController -and !$Credential)
  6. {
  7. $Forest = Get-Forest -DNSName $DomainController
  8. }
  9. elseif($DomainController -and $Credential)
  10. {
  11. $Forest = Get-Forest -DNSName $DomainController -Credential $Credential
  12. }
  13. else
  14. {
  15. $Forest = Get-Forest
  16. }
  17.  
  18. $Forest.Schema.FindAllClasses() | ?{$_.Name -match "^$Class`$"}
  19. }
  1. function Get-ADSchemaProperty
  2. {
  3. Param($Property = ".*",$DomainController,[Management.Automation.PSCredential]$Credential)
  4.  
  5. if($DomainController -and !$Credential)
  6. {
  7. $Forest = Get-Forest -DNSName $DomainController
  8. }
  9. elseif($DomainController -and $Credential)
  10. {
  11. $Forest = Get-Forest -DNSName $DomainController -Credential $Credential
  12. }
  13. else
  14. {
  15. $Forest = Get-Forest
  16. }
  17.  
  18. $Forest.Schema.FindAllProperties() | ?{$_.Name -match "^$Property`$"}
  19.  
  20. }

blog: Discovery options with R2 AD Cmdlets

Last week I talked about how to "discover" information using the built in .NET classes for ActiveDirectory. This week I would like to show how you can do similar things with the ActiveDirectory cmdlets that ship with Win7 and R2.

The first task we discussed was getting Forest information like Domains, Sites, ForestMode, RootDomain, and Forest masters.

With .NET we do this
  1. $Forest = [DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
With the cmdlets we do this
  1. $Forest = Get-ADForest

Next we discussed getting Domain information like Domain Controllers, DomainMode, Domain Masters, and Forest Root.
  1. $Domain = [DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
With the cmdlets we do this
  1. $Domain = Get-ADDomain

Now the object we get back is slightly different so lets take a look

First lets look at what $Forest has to offer
  1. PS C:UsersAdministrator> $Forest
  2.  
  3. ApplicationPartitions : {}
  4. CrossForestReferences : {}
  5. DomainNamingMaster : Win2K8R2DC1.R2.Dev.Lab
  6. Domains : {R2.Dev.Lab}
  7. ForestMode : Windows2008R2Forest
  8. GlobalCatalogs : {Win2K8R2DC1.R2.Dev.Lab}
  9. Name : R2.Dev.Lab
  10. PartitionsContainer : CN=Partitions,CN=Configuration,DC=R2,DC=Dev,DC=Lab
  11. PSShowComputerName : {}
  12. RootDomain : R2.Dev.Lab
  13. SchemaMaster : Win2K8R2DC1.R2.Dev.Lab
  14. Sites : {Default-First-Site-Name}
  15. SPNSuffixes : {}
  16. UPNSuffixes : {}
  17. WriteErrorStream : {}

Finally, Lets look at $Domain
  1. PS C:UsersAdministrator> $domain
  2.  
  3. AllowedDNSSuffixes : {}
  4. ChildDomains : {}
  5. ComputersContainer : CN=Computers,DC=R2,DC=Dev,DC=Lab
  6. DeletedObjectsContainer : CN=Deleted Objects,DC=R2,DC=Dev,DC=Lab
  7. DistinguishedName : DC=R2,DC=Dev,DC=Lab
  8. DNSRoot : R2.Dev.Lab
  9. DomainControllersContainer : OU=Domain Controllers,DC=R2,DC=Dev,DC=Lab
  10. DomainMode : Windows2008R2Domain
  11. DomainSID : S-1-5-21-4244231903-4101880959-1987002231
  12. ForeignSecurityPrincipalsContainer : CN=ForeignSecurityPrincipals,DC=R2,DC=Dev,DC=Lab
  13. Forest : R2.Dev.Lab
  14. InfrastructureMaster : Win2K8R2DC1.R2.Dev.Lab
  15. LastLogonReplicationInterval :
  16. LinkedGroupPolicyObjects : {CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,CN=System,DC=R2,DC=Dev,DC=Lab}
  17. LostAndFoundContainer : CN=LostAndFound,DC=R2,DC=Dev,DC=Lab
  18. ManagedBy :
  19. Name : R2
  20. NetBIOSName : R2
  21. ObjectClass : domainDNS
  22. ObjectGUID : c2d8e67d-2a49-4352-a795-de2b6508b1dc
  23. ParentDomain :
  24. PDCEmulator : Win2K8R2DC1.R2.Dev.Lab
  25. QuotasContainer : CN=NTDS Quotas,DC=R2,DC=Dev,DC=Lab
  26. ReadOnlyReplicaDirectoryServers : {}
  27. ReplicaDirectoryServers : {Win2K8R2DC1.R2.Dev.Lab}
  28. RIDMaster : Win2K8R2DC1.R2.Dev.Lab
  29. SubordinateReferences : {CN=Configuration,DC=R2,DC=Dev,DC=Lab}
  30. SystemsContainer : CN=System,DC=R2,DC=Dev,DC=Lab
  31. UsersContainer : CN=Users,DC=R2,DC=Dev,DC=Lab

Here are some more specific examples on how to use these variables:

To see the forest roles
  1. $forest | select SchemaMaster,DomainNamingMaster
To see the domain roles
  1. $domain | select PDCEmulator,RIDMaster,InfrastructureMaster
To see what application partitions your forest has
  1. $forest.ApplicationPartitions

NOTE: you can use this command to see all the AD Cmdlets have to offer
  1. get-command -Module ActiveDirectory

blog: More details on Select-Object

I often to get asked what I mean by "Select-Object changes the object type." I believe this one of those things that is easier to illustrate than just explain. First let me show the object type Change
  1. PS> ($dir = Get-item C:\temp).Gettype()
  2.  
  3. IsPublic IsSerial Name BaseType
  4. -------- -------- ---- --------
  5. True True DirectoryInfo System.IO.FileSystemInfo
  6.  
  7. PS> ($dir = Get-item C:\temp | select-Object Fullname,Name,Parent).Gettype()
  8.  
  9. IsPublic IsSerial Name BaseType
  10. -------- -------- ---- --------
  11. True False PSCustomObject System.Object
  12.  
  13. Even if you specifiy PSBASE you have new object type.
  14.  
  15. PS> ($dir = Get-item C:\temp).psbase.Gettype()
  16.  
  17. IsPublic IsSerial Name BaseType
  18. -------- -------- ---- --------
  19. True True DirectoryInfo System.IO.FileSystemInfo
  20.  
  21. PS> ($dir = Get-item C:\temp | select-Object Fullname,Name,Parent).psbase.Gettype()
  22.  
  23. IsPublic IsSerial Name BaseType
  24. -------- -------- ---- --------
  25. True False PSCustomObject System.Object
Now look at what you lose using this method.

First you will notice you have 21 items returned from Get-Member (I only included Properties for simplicity, but methods work the same way.)
  1. PS> get-item C:\temp | Get-Member -MemberType Properties | ft Name
  2.  
  3. Name
  4. ----
  5. PSChildName
  6. PSDrive
  7. PSIsContainer
  8. PSParentPath
  9. PSPath
  10. PSProvider
  11. Attributes
  12. CreationTime
  13. CreationTimeUtc
  14. Exists
  15. Extension
  16. FullName
  17. LastAccessTime
  18. LastAccessTimeUtc
  19. LastWriteTime
  20. LastWriteTimeUtc
  21. Name
  22. Parent
  23. Root
  24. Mode
  25. ReparsePoint
  26.  
  27. ## After piping to Select-Object you now only have 3
  28.  
  29. PS> Get-Item C:\temp | Select-Object Name,Fullname,Parent | Get-Member -MemberType Properties | ft name
  30.  
  31. Name
  32. ----
  33. FullName
  34. Name
  35. Parent
  36.  
  37. ## Now.. methods before "Conversion"
  38.  
  39. PS> Get-item C:\temp | Get-Member -MemberType Methods | ft name
  40.  
  41. Name
  42. ----
  43. Create
  44. CreateObjRef
  45. CreateSubdirectory
  46. Delete
  47. Equals
  48. GetAccessControl
  49. GetDirectories
  50. GetFiles
  51. GetFileSystemInfos
  52. GetHashCode
  53. GetLifetimeService
  54. GetObjectData
  55. GetType
  56. get_Attributes
  57. get_CreationTime
  58. get_CreationTimeUtc
  59. get_Exists
  60. get_Extension
  61. get_FullName
  62. get_LastAccessTime
  63. get_LastAccessTimeUtc
  64. get_LastWriteTime
  65. get_LastWriteTimeUtc
  66. get_Name
  67. get_Parent
  68. get_Root
  69. InitializeLifetimeService
  70. MoveTo
  71. Refresh
  72. SetAccessControl
  73. set_Attributes
  74. set_CreationTime
  75. set_CreationTimeUtc
  76. set_LastAccessTime
  77. set_LastAccessTimeUtc
  78. set_LastWriteTime
  79. set_LastWriteTimeUtc
  80. ToString
  81.  
  82. ## After
  83.  
  84. PS> Get-item C:\temp | select-object FullName,Name,Parent | Get-Member -MemberType Methods | ft name
  85.  
  86. Name
  87. ----
  88. Equals
  89. GetHashCode
  90. GetType
  91. ToString
As you can see... Effectively they are all gone on the new object. When I first experienced this.. I thought maybe the methods were just hidden... but try to access them
  1. PS> $dir = Get-Item C:\temp
  2. PS> $dir.GetDirectories()
  3.  
  4. Mode LastWriteTime Length Name
  5. ---- ------------- ------ ----
  6. d---- 5/22/2007 1:58 PM Console
  7. d---- 5/10/2007 4:36 PM test32
  8.  
  9. PS> $dir = Get-Item C:\temp | Select-Object FullName,Name,Parent
  10. PS> $dir.GetDirectories()
  11. Method invocation failed because [System.Management.Automation.PSCustomObject] doesn't contain a method named 'GetDirectories'.
  12. At line:1 char:20
I want to be clear... This is not a bug. Its not even a bad idea. I find it useful, but I think it confuses a lot of people. Like most people I didn't read the help before I used it or I would have seen this excerpt from get-help Select-Object:
If you use Select-Object to select specified properties, it copies the values of those properties from the input objects and creates new objects that have the specified properties and copied values.
So, the moral of the story is don't be shocked when your object changes after using Select-Object. Embrace the change :)

blog: Creating Custom Objects with “Select-Object”

Once you grab a hold of the "Object" concept in Powershell it brings a whole new light to scripting. The power that is at your finger tips is basically limitless, but to harness this power you not only need to know how to use objects but also create them as well.

Here is my way of creating objects.
  1. $myobj = ""| select-Object Server,Result
IMO this is the simplest way to create custom objects.

Effectively what happens is you set your $myobj to a empty string and pipe to select-object. While this may seem odd, its actually quite useful because what select-object returns is a PSCustomObject with the properties that you specify. This allows you to create you object with defined properties that you can fill out later in one line.

The "proper" way to create a custom object is to do this.
  1. $myobj = new-object System.Object
  2. $myobj | add-member -membertype noteproperty -name Server -value $sname
  3. $myobj | add-member -membertype noteproperty -name Result -value $sResult
While this isn't that much more work... I think its harder to read (and more typing) so I go with this shortcut
  1. $myobj = "" | select-Object Server,Result
  2. $myobj.Server = $sname
  3. $myobj.Result = $sResult
I will give you one warning about select-object (not related, but while I'm on this subject.) select-object does Change the object type and therefore you lose methods and properties you may expect to be there. I have seen numerous post on the news groups that have this exact problem.

If you pipe Get-ChildItem to Get-member you get tons of methods and properties for both System.IO.FileInfo and System.IO.DirectoryInfo
  1. PS> get-childitem | gm
Now pipe it to select-object and do a Get-Member
  1. PS> (get-childitem | select-object Fullname,length) | gm
  2.  
  3. TypeName: System.Management.Automation.PSCustomObject
  4.  
  5. Name MemberType Definition
  6. ---- ---------- ----------
  7. Equals Method System.Boolean Equals(Object obj)
  8. GetHashCode Method System.Int32 GetHashCode()
  9. GetType Method System.Type GetType()
  10. ToString Method System.String ToString()
  11. FullName NoteProperty System.String FullName=C:WindowsSystem32409
  12. length NoteProperty length=null
Just be careful to remember this. I actually avoid using select-object to filter objects simply because of this. Instead... I just use the properties.

blog: Sick of WMI timeouts stopping your script? Try Test-Host!

I manage a large number of servers and this management involves a ton of WMI queries. A long time back I got sick of waiting and waiting for my WMI queries so I developed a little script called Test-Port that would do a WMI ping or would test a specific port (for firewalls) and pass the object on if connectivity passed.

You can see more details about that script here: Test-Port (kinda like portqry without verbose output)

With v2 just on the horizon I wanted to see what I could improve using Powershell v2 and decided to re-write the code (found below.)

Some of the new features are:
- Rename to Test-Host
- Built in Help and examples (biggy)
- Parameter Binding
- Added more logging with -verbose switch

This can be very useful if you ever have the need to do a task on a number of Computers (specifically WMI.) For example, If I needed to get all the machines running x64 in my domain I could something like this:

  1. $computers = Get-QADComputer -search $OU | %{$_.dnshostname} | Test-Host -tcp 135
  2. $query = "SELECT * FROM win32_processor WHERE addresswidth='64'"
  3. Get-WMIObject -query $query -comp $computers -asJob

Here is the code for Test-Host
Can download here: Test-Host.ps1 (from Poshcode.org)
  1. function Test-Host
  2. {
  3.  
  4. [CmdletBinding()]
  5.  
  6. Param(
  7. [Parameter(ValueFromPipeline=$true,Mandatory=$True)]
  8. [string]$Server,
  9. [Parameter()]
  10. [int]$TCPPort,
  11. [Parameter()]
  12. [int]$timeout=1000,
  13. [Parameter()]
  14. [string]$property
  15. )
  16. Begin
  17. {
  18. function TestPort {
  19. Param($srv,$tport,$tmOut)
  20. Write-Verbose " [TestPort] :: Start"
  21. Write-Verbose " [TestPort] :: Setting Error state = 0"
  22. $Error\3ActionPreference = "SilentlyContinue"
  23.  
  24. Write-Verbose " [TestPort] :: Creating [system.Net.Sockets.TcpClient] instance"
  25. $tcpclient = New-Object system.Net.Sockets.TcpClient
  26.  
  27. Write-Verbose " [TestPort] :: Calling BeginConnect($srv,$tport,$null,$null)"
  28. $iar = $tcpclient.BeginConnect($srv,$tport,$null,$null)
  29.  
  30. Write-Verbose " [TestPort] :: Waiting for timeout [$timeout]"
  31. $wait = $iar.AsyncWaitHandle.WaitOne($tmOut,$false)
  32. # Traps
  33. trap
  34. {
  35. Write-Verbose " [TestPort] :: General Exception"
  36. Write-Verbose " [TestPort] :: End"
  37. return $false
  38. }
  39. trap [System.Net.Sockets.SocketException]
  40. {
  41. Write-Verbose " [TestPort] :: Exception: $($_.exception.message)"
  42. Write-Verbose " [TestPort] :: End"
  43. return $false
  44. }
  45. if(!$wait)
  46. {
  47. $tcpclient.Close()
  48. Write-Verbose " [TestPort] :: Connection Timeout"
  49. Write-Verbose " [TestPort] :: End"
  50. return $false
  51. }
  52. else
  53. {
  54. Write-Verbose " [TestPort] :: Closing TCP Sockett"
  55. $tcpclient.EndConnect($iar) | out-Null
  56. $tcpclient.Close()
  57. }
  58. if($?){Write-Verbose " [TestPort] :: End";return $true}
  59. }
  60. function PingServer {
  61. Param($MyHost)
  62. Write-Verbose " [PingServer] :: Pinging $MyHost"
  63. $pingresult = Get-WmiObject win32_pingstatus -f "address='$MyHost'"
  64. Write-Verbose " [PingServer] :: Ping returned $($pingresult.statuscode)"
  65. if($pingresult.statuscode -eq 0) {$true} else {$false}
  66. }
  67. }
  68. Process
  69. {
  70. Write-Verbose ""
  71. Write-Verbose " Server : $Server"
  72. if($TCPPort)
  73. {
  74. Write-Verbose " Timeout : $timeout"
  75. Write-Verbose " Port : $TCPPort"
  76. if($property)
  77. {
  78. Write-Verbose " Property : $Property"
  79. if(TestPort $Server.$property -tport $TCPPort -tmOut $timeout){$Server}
  80. }
  81. else
  82. {
  83. if(TestPort $Server -tport $TCPPort -tmOut $timeout){$Server}
  84. }
  85. }
  86. else
  87. {
  88. if($property)
  89. {
  90. Write-Verbose " Property : $Property"
  91. if(PingServer $Server.$property){$Server}
  92. }
  93. else
  94. {
  95. Write-Verbose " Simple Ping"
  96. if(PingServer $Server){$Server}
  97. }
  98. }
  99. Write-Verbose ""
  100. }
  101. }

blog: Why use LDAP filters (Powershell)

A common problem when dealing with Active Directory is the end user trying to parse the results themselves.

Let take this example
  1. $selector = New-Object DirectoryServices.DirectorySearcher
  2. $selector.SearchRoot = [ADSI]""
  3. $selector.pagesize = 1000
  4. $adobj= $selector.findall() | where {$_.properties.objectcategory -match "CN=Person"}
  5. foreach ($person in $adobj) {
  6. $date120DaysAgo = [DateTime]::Now.AddDays(-120).ToFileTime()
  7. $LL1 = $person.properties.lastlogontimestamp
  8. if(($LL1 -le $date120DaysAgo) -and ($person.GetDirectoryEntry().psbase.invokeget('AccountDisabled'))){$person}
  9. }

Instead of doing the parsing on results side... we should let the server do the work. How do we do that?

With LDAP filters. Here is an example.
  1. $filter = "(&(objectcategory=user)(userAccountControl:1.2.840.113556.1.4.803:=2)(lastlogontimestamp>=$date))"
  2. $ds = New-Object DirectoryServices.DirectorySearcher([ADSI]"",$filter)
  3. $ds.PageSize = 1000
  4. $users = $ds.FindAll()
  5. $users

Or with Quest tools... even easier!
  1. $date = (Get-Date).AddDays(-120).ToFileTime()
  2. $filter = "(lastlogontimestamp>=$date)"
  3. Get-QADUser -LdapFilter $filter -disabled

I think you will find with an LDAP filter you can save a TON of time.

Here is the output of measure-command for the two examples above (this was a very small sample.)

Without Filter
--------------
Days : 0
Hours : 0
Minutes : 0
Seconds : 3
Milliseconds : 477
Ticks : 34776670

With Filter
-----------
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 34
Ticks : 340740

If you were to do this on a large AD the difference in time would be HUGE! Here is an example with 600K users...

With Filter
------------
Days : 0
Hours : 0
Minutes : 0
Seconds : 17
Milliseconds : 353
Ticks : 173535605

I can't post one with out filter... because it has been hours and it is still not done :)

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

Next »