问题
Some PowerShell commandlets accept pipeline input ByProperyName, some do it ByValue, others do it for both. What does this mean? How does it impact our PowerShell scripts?
回答1:
The ValueFromPipeline parameter attribute will map the parameter value to whatever object type is passed in from the pipeline. If you use the ValueFromPipelineByPropertyName parameter attribute, then a specific property will be used from the objects that are piped into the command+parameter.
ValueFromPipeline Example
Get-Process | Stop-Process; # Stop-Process expects to receive a Process object
<#
-InputObject <Process[]>
Stops the processes represented by the specified process objects. Enter a variable that contains the objects, or
type a command or expression that gets the objects.
Required? true
Position? 1
Default value
Accept pipeline input? true (ByValue)
Accept wildcard characters? false
#>
ValueFromPipelineByPropertyName Example
# Get-Process looks for a ComputerName property on the incoming objects
[PSCustomObject]@{
ComputerName = 'localhost';
} | Get-Process;
<#
-ComputerName <String[]>
Gets the processes running on the specified computers. The default is the local computer.
Type the NetBIOS name, an IP address, or a fully qualified domain name of one or more computers. To specify the
local computer, type the computer name, a dot (.), or "localhost".
This parameter does not rely on Windows PowerShell remoting. You can use the ComputerName parameter of Get-Process
even if your computer is not configured to run remote commands.
Required? false
Position? named
Default value Local computer
Accept pipeline input? True (ByPropertyName)
Accept wildcard characters? false
#>
回答2:
OverView
PowerShell commandlets return objects and accept objects as parameters. Objects are always of one particular Type and have many Properties.
E.g., the Get-Service commandlet returns a System.ServiceProcess.ServiceController object that has properties including Name, RequiredServices, CanPauseAndContinue, and DisplayName.
When we pass an object across the pipeline to another commandlet, the second commandlet either matches the TypeName (ByValue) of the object or matches one of the object's PropertyNames.
Accept pipeline input ByValue
In this case, the TypeName of the first commandlet must be the same as a Parameter Type of the second commandlet.
Example
The Get-Service TypeName is ServiceController, and the Stop-Service commandlet has a ByValue parameter called InputObject of Parameter Type ServiceController.
This works because System.ServiceProcess.ServiceController is the same type sa ServiceController[]. In other words, they match ByValue. Here's proof.
C:\> get-service | get-member | select typename -first 1
TypeName
--------
System.ServiceProcess.ServiceController
C:\> get-help stop-service
-InputObject <ServiceController[]>
Accept pipeline input? true (ByValue)
Accept pipeline input ByPropertyName
In this case, the Type of the first commandlet must have a Property Name that is the same as a Parameter Name of the second commandlet.
Example
The ServiceController class has a property called Name, and the Stop-Service commandlet has a ByPropertyName parameter called name. Thus, they match ByPropertyName. Here's proof:
C:\> get-service | gm | where MemberType -like "*property" | select Name
Name
----
Name
RequiredServices
CanPauseAndContinue
CanShutdown
CanStop
Container
DependentServices
DisplayName
MachineName
ServiceHandle
ServiceName
ServicesDependedOn
ServiceType
Site
Status
C:\> get-help stop-service -Name <String[]>
Accept pipeline input? true (ByPropertyName, ByValue)
This is quite confusing to understand.For me it helps to remember that ByValue really means ByTypeName.
来源:https://stackoverflow.com/questions/21117947/when-a-commandlet-accepts-pipeline-input-what-is-the-difference-between-byprope