Posts RSS Comments RSS 117 Posts and 170 Comments till now

Archive for June, 2007

Using Aliases in Scripts or in your Examples.

Richard has a post on his blog about this The Over Use of Aliases?

I dont like duplicating other peoples post, but I think this one is worth it.

If you are an experienced Powershell person and you provide help or scripts to people. PLEASE do not use aliases. It makes it very hard for people. I am guilty myself. I mean gc % ? gm are SO tempting, but it really doesn’t help the person learn (it may even hinder.) IMO, using aliases can confuse newcomers… remember to them when you type gc… they think it is gc.exe not get-content. Peoples first impression is key… lets not make it a confusing one :)
Basically, I think aliases are best use for interactive use, but should be avoided in scripts or sample code.

p.s. COMMENT… COMMENT… COMMENT… Comments in code help a ton for people learning.

UPDATE:
Jeffrey brought up a good point that I over looked. Numerous Powershell IDE’s like PrimalScript and Powershell Analzyer automatically expand built in aliases. I find this very useful. I will be writing another post about IDE’s and why I think they are VERY important.

More on Select-Object

I had a few question on what I meant by “select-object does Change the object type and therefore you lose methods and properties you may expect to be there.” So Here is an example to help clarify.

First let me show the object type Change

  1.  
  2. 26# ($dir = Get-item C:\temp).Gettype()
  3.  
  4. IsPublic IsSerial Name                                     BaseType
  5. ——– ——– —-                                     ——–
  6. True     True     DirectoryInfo                            System.IO.FileSystemInfo
  7.  
  8. 27# ($dir = Get-item C:\temp | select-Object Fullname,Name,Parent).Gettype()
  9.  
  10. IsPublic IsSerial Name                                     BaseType
  11. ——– ——– —-                                     ——–
  12. True     False    PSCustomObject                           System.Object
  13.  

Even if you specifiy PSBASE you have new object type.

  1.  
  2. 28# ($dir = Get-item C:\temp).psbase.Gettype()
  3.  
  4. IsPublic IsSerial Name                                     BaseType
  5. ——– ——– —-                                     ——–
  6. True     True     DirectoryInfo                            System.IO.FileSystemInfo
  7.  
  8.  
  9. 29# ($dir = Get-item C:\temp | select-Object Fullname,Name,Parent).psbase.Gettype()
  10.  
  11. IsPublic IsSerial Name                                     BaseType
  12. ——– ——– —-                                     ——–
  13. True     False    PSCustomObject                           System.Object
  14. >/pre>
  15.  
  16. Now look at what you lose using this method.
  17.  
  18. First you will notice you have 21 items returned from Get-Member
  19. (I only included Properties for simplicity, but methods work the same way.)
  20. <pre lang="posh">
  21. 18# get-item c:\temp | Get-Member -MemberType Properties | ft Name
  22.  
  23. Name
  24. —-
  25. PSChildName
  26. PSDrive
  27. PSIsContainer
  28. PSParentPath
  29. PSPath
  30. PSProvider
  31. Attributes
  32. CreationTime
  33. CreationTimeUtc
  34. Exists
  35. Extension
  36. FullName
  37. LastAccessTime
  38. LastAccessTimeUtc
  39. LastWriteTime
  40. LastWriteTimeUtc
  41. Name
  42. Parent
  43. Root
  44. Mode
  45. ReparsePoint
  46.  

After piping to Select-Object you now only have 3

  1.  
  2. 24# Get-Item C:\temp | Select-Object Name,Fullname,Parent | Get-Member -MemberType Properties | ft name
  3.  
  4. Name
  5. —-
  6. FullName
  7. Name
  8. Parent
  9.  

Now.. methods before “Conversion”

  1.  
  2. 32# Get-item C:\temp | Get-Member -MemberType Methods | ft name
  3.  
  4. Name
  5. —-
  6. Create
  7. CreateObjRef
  8. CreateSubdirectory
  9. Delete
  10. Equals
  11. GetAccessControl
  12. GetDirectories
  13. GetFiles
  14. GetFileSystemInfos
  15. GetHashCode
  16. GetLifetimeService
  17. GetObjectData
  18. GetType
  19. get_Attributes
  20. get_CreationTime
  21. get_CreationTimeUtc
  22. get_Exists
  23. get_Extension
  24. get_FullName
  25. get_LastAccessTime
  26. get_LastAccessTimeUtc
  27. get_LastWriteTime
  28. get_LastWriteTimeUtc
  29. get_Name
  30. get_Parent
  31. get_Root
  32. InitializeLifetimeService
  33. MoveTo
  34. Refresh
  35. SetAccessControl
  36. set_Attributes
  37. set_CreationTime
  38. set_CreationTimeUtc
  39. set_LastAccessTime
  40. set_LastAccessTimeUtc
  41. set_LastWriteTime
  42. set_LastWriteTimeUtc
  43. ToString
  44.  

After

  1.  
  2. 33# Get-item C:\temp | select-object FullName,Name,Parent | Get-Member -MemberType Methods | ft name
  3.  
  4. Name
  5. —-
  6. Equals
  7. GetHashCode
  8. GetType
  9. ToString
  10.  

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.  
  2. 42# $dir = Get-Item C:\temp
  3. 43# $dir.GetDirectories()
  4.  
  5. Mode           LastWriteTime       Length Name
  6. —-           ————-       —— —-
  7. d—-     5/22/2007  1:58 PM              Console
  8. d—-     5/10/2007  4:36 PM              test32
  9.  
  10.  
  11. 44# $dir = Get-Item C:\temp | Select-Object FullName,Name,Parent
  12. 45# $dir.GetDirectories()
  13. Method invocation failed because [System.Management.Automation.PSCustomObject] doesn‘t contain a method named ‘GetDirectories‘.
  14. At line:1 char:20
  15. + $dir.GetDirectories( <<<< )
  16.  

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 didnt read the help before I used it or I would have seen this excerpt from get-help Select-Object:

[code]
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.
[/code]

Creating Custom Objects

halr9000 Asked “can you explain this construct for me?”

[code]$myobj = “”| select-Object Server,Result[/code]

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.

I guess the “proper” way to create a custom object is to do this.

[code]
$myobj = new-object System.Object
$myobj | add-member -membertype noteproperty -name Server -value $sname
$myobj | add-member -membertype noteproperty -name Result -value $sResult
[/code]

While this isnt that much more work… I think its harder to read so I go with my shortcut like

[code]
$myobj = “” | select-Object Server,Result
$myobj.Server = $sname
$myobj.Result = $sResult
[/code]

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
[code]4# get-childitem | gm[/code]

Now pipe it to select-object and do a Get-Member
[code]
5# (get-childitem | select-object Fullname,length) | gm

TypeName: System.Management.Automation.PSCustomObject

Name MemberType Definition
—- ———- ———-
Equals Method System.Boolean Equals(Object obj)
GetHashCode Method System.Int32 GetHashCode()
GetType Method System.Type GetType()
ToString Method System.String ToString()
FullName NoteProperty System.String FullName=C:\Windows\System32\0409
length NoteProperty length=null
[/code]

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.

How to Manage Multiple Citrix Farms

Chris left a comment on Powershelling Citrix (The Good, Bad, and The Code)

Here is a function that returns a farm object for Server that is passed.

  1. function Get-CitrixFarm {
  2.    Param([string]$server)
  3.    $type = [system.Type]::GetTypeFromProgID("MetaframeCOM.MetaFrameFarm",$server)
  4.    $farm = [system.Activator]::CreateInstance($type)
  5.    $farm.Initialize(1)
  6.    return $farm
  7. }
  8.  

Here is an example to find a Server that a User is on.

  1. function Find-CitrixUser {
  2.     Param([string]$user,[string]$server,[string]$domain,[switch]$verbose)
  3.     $type = [system.Type]::GetTypeFromProgID("MetaframeCOM.MetaframeUser",$server)
  4.     $mfuser = [system.Activator]::CreateInstance($type)
  5.     $mfuser.Initialize(1,$domain,1,$user)
  6.     Write-Host
  7.     Write-Host "User: $($mfuser.UserName) found on the Following:"
  8.     foreach ($s in $mfuser.Sessions)
  9.     {
  10.         if($verbose)
  11.         {
  12.             Write-Host
  13.             Write-Host "$($s.ServerName)"
  14.             Write-Host "-=-=-=-=-=-"
  15.             Write-Host "AppName          : $($s.AppName)" -foregroundcolor yellow
  16.             Write-Host "SessionName      : $($s.SessionName)" -foregroundcolor yellow
  17.             Write-Host "SessionID        : $($s.SessionID)" -foregroundcolor yellow
  18.             Write-Host "ClientAddress    : $($s.ClientAddress)" -foregroundcolor yellow
  19.             Write-Host "ClientEncryption : $($s.ClientEncryption)" -foregroundcolor yellow
  20.             Write-Host
  21.             Write-Host "Processes"
  22.             Write-Host "========="
  23.             foreach ($proc in $s.Processes)
  24.             {
  25.                 Write-Host $proc.ProcessName -foregroundcolor Green
  26.             }
  27.             Write-host
  28.         }
  29.         else
  30.         {
  31.             write-Host "   -> $($s.ServerName)"
  32.         }
  33.     }
  34. }