Posts RSS Comments RSS 117 Posts and 170 Comments till now

Archive for November, 2007

Citrix MFCom Enums

One of the biggest problems I run into when writing Citrix MFCom Scripts I normally like finding examples (Vbscript mostly.) Because the COM Object model is very picky about what is passed and how it is passed, it helps knowing how and what the COM object is expecting.

Most of these examples use MFCOM enumerations in the initializing of the object. So I always find my self trying to figure out what the value is suppose to be because the ENUM is a pain to do in Powershell. I finally decided to let Visual Studio do my dirty work and figure out the Enums for me.

Here is the list (it is not complete, but it has most of them. I will add more as I find them.) If you find any missing let me know!

You can either use this as reference for the values or you cut/paste this code in a script and ‘.’ Source the Script in your Citrix Scripts and call the Enums directly.

  1. # Window Type Enums
  2. $MFWinWindowUnknown = 0
  3. $MFWinWindow640X480 = 1
  4. $MFWinWindow800X600 = 2
  5. $MFWinWindow1024X768 = 3
  6. $MFWinWindow1280X1024 = 4
  7. $MFWinWindowCustom = 5
  8. $MFWinWindowPercent = 6
  9. $MFWinWindowFullScreen = 7
  10. $MFWinWindow1600X1200 = 8
  11.  
  12. # Color Enums
  13. $MFWinColorUnknown = 0
  14. $MFWinColor16 = 1
  15. $MFWinColor256 = 2
  16. $MFWinColor64K = 3
  17. $MFWinColor16M = 4
  18.  
  19. # Authentication Enums
  20. $MFAccountAuthorityUnknown = 0
  21. $MFAccountAuthorityNTDomain = 1
  22. $MFAccountAuthorityNDS = 2
  23. $MFAccountAuthorityADS = 3
  24. $MFAccountTypeUnknown = 0
  25. $MFAccountLocalUser = 1
  26. $MFAccountDomainUser = 2
  27. $MFAccountLocalGroup = 3
  28. $MFAccountGlobalGroup = 4
  29. $MFAccountUniversalGroup = 5
  30. $MFAccountDomainLocalGroup = 6
  31. $MFAccountFolder = 7
  32.  
  33. # Object Enums
  34. $MetaFrameUnknownObject = 0
  35. $MetaFrameWinFarmObject = 1
  36. $MetaFrameZoneObject = 2
  37. $MetaFrameWinAppObject = 3
  38. $MetaFrameLicenseObject = 4
  39. $MetaFrameAcctAuthObject = 5
  40. $MetaFrameWinSrvObject = 6
  41. $MetaFrameUserObject = 7
  42. $MetaFrameGroupObject = 8
  43. $MetaFrameProcessObject = 9
  44. $MetaFrameSessionObject = 10
  45. $MetaFrameChannelObject = 11
  46. $MetaFrameAppFolder = 12
  47. $MetaFrameSrvFolder = 13
  48. $MetaFrameIMSAppObject = 14
  49. $MetaFrameRMSAppObject = 15
  50. $MetaFrameUnixAppObject = 16
  51. $MetaFrameContentObject = 17
  52. $MetaFrameFileTypeObject = 18
  53. $MetaFrameUserPolicyObject = 19
  54. $MetaFrameSessionPolicyObject = 19
  55. $MetaFrameLicenseSetObject = 20
  56. $MetaFrameLicenseNumberObject = 21
  57. $MetaFrameAccountFolder = 22
  58. $MetaFramePrinterObject = 23
  59. $MetaFramePrinterDriverObject = 24
  60. $MetaFrameAdminObject = 25
  61. $MetaFrameMeObject = 26
  62. $MetaFrameLoadEvaluatorObject = 27
  63. $MetaFrameSessionPolFilterObject = 28
  64. $MetaFrameAppliedPolicyObject = 29
  65. $MetaFrameFileObject = 30
  66. $MetaFrameIconObject = 31
  67. $MetaFrameVIPRangeObject = 32
  68. $MetaFrameLMRuleObject = 33
  69. $MetaFrameAIEObject = 34
  70. $MetaFrameAIEFolder = 35
  71. $MetaFrameAIERuleObject = 36
  72. $MetaFrameHotfixObject = 37
  73. $MetaFrameStreamedAppObject = 38
  74. $MetaFrameIMPackageObject = 39
  75. $MetaFrameIMPackageGroup = 40
  76. $MetaFrameServerGroup = 41
  77. $MetaFrameMPFolder = 42
  78. $MetaFrameIMConfigObject = 43
  79. $MetaFrameIMJobObject = 44

New Powershell Podcast is out and I am a guest!!!

The new PodCast is out and avaible here http://powerscripting.wordpress.com/2007/11/09/powerscripting-podcast-episode-12

I was happy and proud to be the first guest. Thanks GUYs!

Using Switch -RegEx to create Custom Object (Getting HBA Info)

The other day I had a need to collect HBA (Host Base Fiber Adapters) from all my Servers. So the first place I looked was at WMI, but unfortunately… no dice. It didnt have the information I needed. The only way I knew to get the info I needed was to use was HBACmd.exe (utility to collect HBA information remotely.) So I went to writing a wrapper script in powershell to call the exe and then grep the text for what I was looking for, but I thought… HEY! Thats not the powershell thing to do! We do objects not text. So I went to parsing the text and making an object out of it. The script below is the result and while I dont believe many of you will find it particularly useful as it has a VERY specific use, I wanted to share with you how I went about objectizing the output.

Here is a littel Q and A on the script

Q: Purpose?
A: To get all the HBA information include Type, Firmware, Bios, Target Lun, WWN and a slew of other stuff.

Q: Why Did I objectize my text?
A: Because I know can simply use properties to filter and output data. Like what Machines have what Bios and what type of HBAs they have. Before I would have the parse the text for every different senario… now I just use where-object and filter away.

I few things that I wanted to point out here are the use of Switch to create the Custom Objects. IMO, Switch is one of the most powerful commands in the Powershell Language. It is INSANELY Powerfull. To be honest, It is pretty much the only one you need.

To compare it “Select Case” in vbscript would be insulting, but it can peform a similar function Like

  1. switch ($a){
  2.      Value1    {"It was Value 1"}
  3.      Value2    {"It was Value 2"}
  4.      Value3    {"It was Value 3"}
  5.      Value4    {"It was Value 4"}
  6. }

It would take a whole series of post to completely cover switch, but for this one I only want to go over -regex use. For complete use read the help located:
PS> Get-help About_Switch # Read it, Learn it, Love it

Some Quick Notes about Switch
- Can use RegEx, WildCard, Exact, CaseSensitive, or File options.
- It takes input via Pipeline {expression} or File. The cool thing is the pipeline can be any expression that results in piped output.
- For each match it can perform any ScritpBlock use $_ as the current Item
- It performs EVERY match on each element unless you use Continue after a match to stop processing that record

Like I said, Switch is insanely powerful. Just one of those powers is using RegEx for comparison.

Here is an example of using the -RegEx option

  1. switch -RegEx (Get-ChildItem C:\test)
  2. {
  3.     "^\d"                  {"Starts with number:          " + $_.FullName}
  4.     "\d"                   {"Has a number in it:          " + $_.FullName}
  5.     "[^A-Za-z]"            {"Does NOT start with Number:  " + $_.FullName}
  6.     "tmp"                  {"Has ‘tmp’ in it:             " + $_.FullName}
  7.     # Notice that you can even use and expression to match
  8.     {$_.Mode -match "-a"}  {"Has Archive Bit Set:         " + $_.FullName}
  9. }

Now.. lets look at the script below. You will noticed I used RegEx to decide what value gets put in to what property of the object.

The script converts the output of three commands into two different objects. Lets look at one of them

It takes text like This

  1. Manageable HBA List
  2.  
  3. Port WWN   : 10:00:00:00:11:11:11:11
  4. Node WWN   : 20:00:00:00:11:11:11:11
  5. Fabric Name: 00:00:00:00:00:00:00:00
  6. Flags      : 0000f0a5
  7. Host Name  : Server1
  8. Mfg        : Emulex Corporation
  9.  
  10. Port WWN   : 10:00:00:00:22:22:22:22
  11. Node WWN   : 20:00:00:00:22:22:22:22
  12. Fabric Name: 00:00:00:00:00:00:00:00
  13. Flags      : 0000f0a5
  14. Host Name  : Server1
  15. Mfg        : Emulex Corporation

And converts Into an object like This

  1.   TypeName: System.Management.Automation.PSCustomObject
  2.  
  3. Name        MemberType   Definition
  4. —-        ———-   ———-
  5. Equals      Method       System.Boolean Equals(Object obj)
  6. GetHashCode Method       System.Int32 GetHashCode()
  7. GetType     Method       System.Type GetType()
  8. ToString    Method       System.String ToString()
  9. Fabric      NoteProperty System.String Fabric=00:00:00:00:00:00:00:00
  10. Flags       NoteProperty System.String Flags=0000f0a5
  11. HBADetail   NoteProperty System.Object[] HBADetail=System.Object[]
  12. Host        NoteProperty System.String Host=Server1
  13. LUN         NoteProperty System.String LUN=01
  14. MFG         NoteProperty System.String MFG=Emulex Corporation
  15. NodeWWN     NoteProperty System.String NodeWWN=20:00:00:00:11:11:11:11
  16. PortWWN     NoteProperty System.String PortWWN=10:00:00:00:11:11:11:11

Here is the Script

  1. Param($List,$HostName,[switch]$FullDetail,[switch]$Verbose)
  2. Begin{
  3.     $erroractionpreference = "SilentlyContinue"
  4.     $HBACMDPath = "<path To HbaCmd.exe>"
  5.     function CreateHBAListObj{
  6.         Param($srv)
  7.         $objCol = @()
  8.         $result = &"$HBACMDPath" "h=$srv" ListHBAs
  9.         foreach($item in $result)
  10.         {
  11.             $parsd = $item.split([string[]](": "),[system.StringSplitOptions]::RemoveEmptyEntries)
  12.             switch -regex ($parsd[0])
  13.             {
  14.                 "^Port" {
  15.                             $myobj = "" | Select-Object Host,PortWWN,NodeWWN,Fabric,Flags,LUN,MFG
  16.                             $myobj.PortWWN = $parsd[1]
  17.                             $myobj.Lun = GetTargetLun $srv $myobj.PortWWN
  18.                         }
  19.                 "^Node" {$myobj.NodeWWN = $parsd[1]}
  20.                 "^Fabr" {$myobj.Fabric  = $parsd[1]}
  21.                 "^Flag" {$myobj.Flags   = $parsd[1]}
  22.                 "^Host" {$myobj.Host    = $parsd[1]}
  23.                 "^MFG " {
  24.                             $myobj.MFG     = $parsd[1]
  25.                             $objCol += $myObj
  26.                         }
  27.             }
  28.         }
  29.         $objCol
  30.     }
  31.     function CreateHBAInfoObj{
  32.         Param($srv,$wwn)
  33.         $objCol = @()
  34.         $result = &"$HBACMDPath" "h=$srv" HBAAttrib $wwn
  35.  
  36.         $myobj = "" |Select-Object Host,MFG,SN,Model,ModelDesc,NodeWWN,NodeSymname,
  37.                                    HWVersion,ROM,FW,VenderID,Ports,DriverName,DeviceID,HBAType,
  38.                                    OpFW,SLT1FW,SLT2FW,IEEEAddress,BootBios,DriverVer,KernelVer
  39.         foreach($item in $result)
  40.         {
  41.             $parsd = $item.split([string[]](": "),[system.StringSplitOptions]::RemoveEmptyEntries)
  42.             switch -regex ($parsd[0])
  43.             {
  44.                 "^Host"         {$myobj.Host         = $parsd[1]}
  45.                 "^Manufacturer" {$myobj.MFG          = $parsd[1]}
  46.                 "^Serial"       {$myobj.Sn           = $parsd[1]}
  47.                 "^Model  "      {$myobj.Model        = $parsd[1]}
  48.                 "^Model Desc"   {$myobj.ModelDesc    = $parsd[1]}
  49.                 "^Node WWN "    {$myobj.NodeWWN      = $parsd[1]}
  50.                 "^Node Symname" {$myobj.NodeSymname  = $parsd[1]}
  51.                 "^HW"           {$myobj.HWVersion    = $parsd[1]}
  52.                 "^Opt"          {$myobj.ROM          = $parsd[1]}
  53.                 "^FW"           {$myobj.FW           = $parsd[1]}
  54.                 "^Vender"       {$myobj.VenderID     = $parsd[1]}
  55.                 "^Number"       {$myobj.Ports        = $parsd[1]}
  56.                 "^Driver Name"  {$myobj.DriverName   = $parsd[1]}
  57.                 "^Device"       {$myobj.DeviceID     = $parsd[1]}
  58.                 "^HBA Type"     {$myobj.HBAType      = $parsd[1]}
  59.                 "^Operational"  {$myobj.OpFW         = $parsd[1]}
  60.                 "^SLI1 FW"      {$myobj.SLT1FW       = $parsd[1]}
  61.                 "^SLI2 FW"      {$myobj.SLT2FW       = $parsd[1]}
  62.                 "^IEEE"         {$myobj.IEEEAddress  = $parsd[1]}
  63.                 "^Boot "        {$myobj.BootBios     = $parsd[1]}
  64.                 "^Driver Ver"   {$myobj.DriverVer    = $parsd[1]}
  65.                 "^Kernel "      {$myobj.KernelVer    = $parsd[1]
  66.                                  $objCol += $myObj}
  67.             }
  68.         }
  69.         $objCol
  70.     }
  71.     function GetTargetLun{
  72.         Param($srv,$wwn)
  73.         $objCol = @()
  74.         $result = &"$HBACMDPath" "h=$srv" TargetMapping $wwn
  75.         [int]$lun = 0
  76.         switch -regex ($result)
  77.         {
  78.             "^SCSI OS Lun" {$lun = $_.split([string[]](": "),[system.StringSplitOptions]::RemoveEmptyEntries)[1].trim()}
  79.         }
  80.         "{0:x}" -f $lun
  81.     }
  82.     function Ping-Server {
  83.         Param([string]$srv)
  84.         if($srv -eq ""){return $false}
  85.         $pingresult = Get-WmiObject win32_pingstatus -f "address=’$srv’"
  86.         if($pingresult.statuscode -eq 0) {$true} else {$false}
  87.     }
  88.     Write-Host
  89.     if($verbose){$VerbosePreference = "Continue"}
  90. }
  91. Process{
  92.     if($_)
  93.     {
  94.         Write-Host "Getting HBA Info from $_"
  95.         if($FullDetail)
  96.         {
  97.             $MyObject = CreateHBAListObj $_
  98.             $HBADetail = $MyObject | %{CreateHBAInfoObj $_.Host $_.PortWWN}
  99.             $MyObject | add-Member -Name HBADetail -type NoteProperty -Value $HBADetail -force
  100.             $MyObject
  101.         }
  102.         else
  103.         {
  104.             $MyObject = CreateHBAListObj $_
  105.             $MyObject
  106.         }
  107.     }
  108. }
  109. End{
  110.     if($list)
  111.     {
  112.         $servers = Get-Content $list
  113.         Write-Host "Running HBA Check against Servers in $list"
  114.         foreach($server in $servers)
  115.         {
  116.             if($server -ne "")
  117.             {
  118.                 if(ping-server $server)
  119.                 {
  120.                     Write-Host "Getting HBA Info from $server"
  121.                     if($FullDetail)
  122.                     {
  123.                         $MyObject = CreateHBAListObj $server
  124.                         $HBADetail = $MyObject | %{CreateHBAInfoObj $_.Host $_.PortWWN}
  125.                         $MyObject | add-Member -Name HBADetail -type NoteProperty -Value $HBADetail -force
  126.                         $MyObject
  127.                     }
  128.                     else
  129.                     {
  130.                         $MyObject = CreateHBAListObj $server
  131.                         $MyObject
  132.                     }
  133.                 }
  134.                 else
  135.                 {
  136.                     Write-Host "$Server not Pingable `n" -foregroundcolor RED
  137.                 }
  138.             }
  139.         }
  140.     }
  141.     if($HostName)
  142.     {
  143.         Write-Host "Running HBA Check against Servers in $HostName"
  144.         if(ping-server $HostName)
  145.         {
  146.             Write-Host "Getting HBA Info from $HostName"
  147.             if($FullDetail)
  148.             {
  149.                 $MyObject = CreateHBAListObj $HostName
  150.                 $HBADetail = $MyObject | %{CreateHBAInfoObj $_.Host $_.PortWWN}
  151.                 $MyObject | add-Member -Name HBADetail -type NoteProperty -Value $HBADetail -force
  152.                 $MyObject
  153.             }
  154.             else
  155.             {
  156.                 $MyObject = CreateHBAListObj $HostName
  157.                 $MyObject
  158.             }
  159.         }
  160.         else
  161.         {
  162.             Write-Host "$HostName not Pingable `n" -foregroundcolor RED
  163.         }
  164.     }
  165.     Write-Host
  166. }

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

    1. # Invoke-VMCommand.ps1
    2. # Purpose     : Run a remote command and return the results
    3. # Requirements: plink.exe from the Putty project must be in $env:path
    4. # Use -help parameter for instructions
    5.  
    6. Param (
    7.     $VMHost,
    8.     $username,
    9.     $Command,
    10.     [switch]$Help,
    11.     [switch]$Verbose
    12. )
    13.  
    14. # Obtains list of VMX (config files) corresponding to each VM on a given ESX server
    15. function GetVMX ($user, $pass, $srv) {
    16.     $cmd = "plink.exe $user@$srv -pw $pass"
    17.     $cmd += " vmware-cmd -l"
    18.     Write-Verbose "Command line: $cmd"
    19.     $VMList = Invoke-Expression $cmd
    20.     $collOut = @()
    21.     $VmList | ForEach-Object {
    22.         $objOut = "" | Select-Object VmHost, VmName, VMXpath, HasSnapshot # create our output object with desired properties
    23.         $objOut.VmHost = $srv
    24.         $objOut.VMXpath = $_
    25.         $objOut.VmName = (Split-Path $_ -Leaf) -replace ".vmx$"
    26.         $collOut += $objOut
    27.     }
    28.     $collOut
    29. }
    30. function Get-ESXProcess($user, $pass, $srv){
    31.     $cmd =  "plink.exe -t $user@$srv -pw $pass "
    32.     $cmd += "`"ps -Af | grep `’`’`""
    33.     Write-Verbose "Command line: $cmd"
    34.     $results = invoke-Expression $cmd
    35.     $colObj = @()
    36.     foreach($result in $results)
    37.     {
    38.         if($result -match "^UID"){continue}
    39.         $myobj = "" | Select-Object UID,PID,PPID,C,STIME,TTY,TIME,CMD
    40.         $ary = $result.split([string[]]" ",[System.StringSplitOptions]::RemoveEmptyEntries)
    41.         $myobj.UID   = $ary[0]
    42.         $myobj.PID   = $ary[1]
    43.         $myobj.PPID  = $ary[2]
    44.         $myobj.C     = $ary[3]
    45.         $myobj.STIME = $ary[4]
    46.         $myobj.TTY   = $ary[5]
    47.         $myobj.Time  = $ary[6]
    48.         $proc = $null
    49.         write-verbose "Length: $($ary.Length)"
    50.         for($i = 7;$i -le $ary.Length;$i++)
    51.         {
    52.             $proc = "$proc $($ary[$i])"
    53.             write-Verbose "Adding [$i] $($ary[$i])"
    54.         }
    55.         Write-Verbose "COMMAND = $proc"
    56.         $myobj.CMD   = $proc
    57.         $colObj += $myobj
    58.     }
    59.     $colObj
    60. }
    61. function RunVMCommand ($user, $pass, $srv, $vmcmd) {
    62.     $cmd = "plink.exe $user@$srv -pw $pass "
    63.     $cmd += "`"$vmcmd | grep `’`’`""
    64.     Write-Verbose "Command line: $cmd"
    65.     invoke-Expression $cmd
    66. }
    67. function GetSecurePass ($SecurePassword) {
    68.   $Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($SecurePassword)
    69.   $password = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($Ptr)
    70.   [System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($Ptr)
    71.   $password
    72. }
    73.  
    74. # Returns help text
    75. function ShowUsage {
    76.   $helptext = @"
    77.  
    78. Invoke-VMCommand
    79.  Requirements: plink.exe from the Putty project must be in your Path
    80.  
    81. INPUT:
    82.  
    83.  VMHost     : name or IP of ESX server(s) (REQUIRED)
    84.  UserName   : User to ssh With (REQUIRED)
    85.  Command    : Command to Run. This can be a GetVMX, PSList, or a Custome String (REQUIRED)
    86.  Help       : shows usage
    87.  
    88. "@
    89.   Write-Host $helptext
    90. }
    91.  
    92. # Main
    93. if ($help) { ShowUsage; exit; }
    94. if ($verbose) { $verbosepreference = "continue" }
    95.  
    96. $password = (Read-Host "Enter Password" -AsSecureString)
    97.  
    98. if($Command -eq "GetVMX"){GetVMX $username (GetSecurePass $password) $VMHost}
    99. elseif($command -eq "PSList"){Get-ESXProcess $username (GetSecurePass $password) $VMHost}
    100. else{RunVMCommand $username (GetSecurePass $password) $VMHost $Command}

    Citrix, albeit a little slow… Gets It!

    From IForum07

    “Citrix is getting high on PowerShell and intend to rewrite the APIs to make everything available from Powershell scripting. There will be a single console, of sorts. Everything will go to MMC snap-ins, and multiple snap-ins will exist that are more task oriented, allowing you to create a MMC console with just the snap-ins you need (or all of them)”

    Full Post here: http://www.brianmadden.com/blog/iForum07/iForumApp-Delivery-Expo-Final-Notes

    As side note: Plans are in the works for a full complete set of Citrix Snapins that work off MFCom. How many would be interested even if its for a small fee?