VMware Cloud Community
markdjones82
Expert
Expert
Jump to solution

Script or function to accept pipeline?

So, I wrote a script to get the WWN's of a cluster but it requires manual input and can only get per cluster.  If I wanted to allow it to do something like this:

Get-Datacenter | Get-WWN

First, does it need to be a function can I pass to a script?  Second what would I put as a parameter to be able to take that pipeline?

#Set mandatory parameters for cluster and csvname
param (
[Parameter(Mandatory=$true)][string]$Cluster,
)

#Get cluster and all host HBA information and change format from Binary to hex
$list = Get-cluster $cluster | Get-VMhost | Get-VMHostHBA -Type FibreChannel | Select VMHost,Device,@{N="WWN";E={"{0:X}" -f $_.PortWorldWideName}} | Sort VMhost,Device

#Go through each row and put : between every 2 digits
foreach ($item in $list){
   $item.wwn = (&{for ($i = 0;$i -lt $item.wwn.length;$i += 2)   
                    {     
                        $item.wwn.substring($i,2)   
                    }}) -join ':' 
}

#Output CSV to current directory.
$list | export-csv -NoTypeInformation  WWN.csv
http://www.twitter.com/markdjones82 | http://nutzandbolts.wordpress.com
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

I would make that a function.

In the param you specify which parameter accepts pipeline input.

param (
    [CmdletBinding()]
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    [string]$Cluster)


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

0 Kudos
7 Replies
LucD
Leadership
Leadership
Jump to solution

I would make that a function.

In the param you specify which parameter accepts pipeline input.

param (
    [CmdletBinding()]
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    [string]$Cluster)


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Btw if you absolutely want to do this in a script, the pipeline objects you pass to the script can be retrieved from the $input special variable.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
markdjones82
Expert
Expert
Jump to solution

Thanks, got my questions answered on the function vs script!  The only reason I would want to do it as a script is some of the people here may not know exactly how to load the function wiht the . ./name and then run the command.  So, I was thinking I could give them instructions to just go there and do Get-datacenter name | get-wwn.ps1 and it work.  I am sure I can instruct them how to do it though.  I'll take a look at that $input special variable

function Get-WWN {    
    #Set mandatory parameters for cluster and csvname
    param (
    [CmdletBinding()]
    [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelinebyPropertyName=$True)]
    $VMObject,
    [Parameter(Mandatory=$true)]
    [string]$csv
    )

    #Get cluster and all host HBA information and change format from Binary to hex
    $list = $VMObject | Get-VMhost | Get-VMHostHBA -Type FibreChannel | Select VMHost,Device,@{N="WWN";E={"{0:X}" -f $_.PortWorldWideName}} | Sort VMhost,Device

    #Go through each row and put : between every 2 digits
    foreach ($item in $list){
       $item.wwn = (&{for ($i = 0;$i -lt $item.wwn.length;$i += 2)   
                        {     
                            $item.wwn.substring($i,2)   
                        }}) -join ':' 
    }

    #Output CSV to current directory.
    $list | export-csv -NoTypeInformation  $csv.csv

}

http://www.twitter.com/markdjones82 | http://nutzandbolts.wordpress.com
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can make sure that the users do not have to do the dot-sourcing by placing that line in the profile.

That way the function is loaded automatically when the PowerShell session starts.

And you can also look at creating a module, that way you store all your functions together.

And provided you don't explictely skip the load of modules, the functions will be known as well.

The advantage is you don't have to include all the dot-sourcing lines in one of the profile files.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
markdjones82
Expert
Expert
Jump to solution

The profile will need to ber set per user per box right? Module can be set at system?  Ill read up on it.  I did have a question on my join above, i got some helo from the powershell forums but the poster didnt explain it.  The & {} runs a script block and being in paenthesis returns all substring results? Then the -join is run against the result substrings? I assume that is another way of using the join string function?  Trying to teach myself to fish instead of having people feed me

http://www.twitter.com/markdjones82 | http://nutzandbolts.wordpress.com
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can have a profile per box for all users of that box, and even a profile for all users of all hosts.

See Profile Scripts: Automatic Scripts for some more info.

Module works differently, they are loaded, if you let PS do that, from the paths defined in $PSModulePath.

You could include a folder on a file share, so that could then also be for all hosts.

I have a slight preference to use modules, since they require less administration and their use is more "natural".

The call operator (&) will indeed execute the following script block (the stuff between the {}).

What happens in the code bloxk is that the string is split up in substrings of length 2, and then all these substrings are joined with the ':'character.

Note that this is the builtin join operator and not the [String]::Join method.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

markdjones82
Expert
Expert
Jump to solution

Thanks for the links Luc, helpful as always

http://www.twitter.com/markdjones82 | http://nutzandbolts.wordpress.com
0 Kudos