[msh] Parameter input from argument or pipeline?

Discussion in 'Scripting' started by Nick, Feb 5, 2006.

  1. Nick

    Nick Guest

    I'm trying to design a cmdlet that, for one of the parameters, takes data
    from the pipeline if it's there, and if not takes it from the first argument
    (it's a specialized copy command). So, I want all of these to do the same

    ls ~/* | copy-custom C:\
    copy-custom ~/* C:\
    copy-custom -Source ~/* -Destination C:\

    where copy-custom has one property Source that takes data from the pipeline
    (first command), argument by position (second), or argument by name (third).

    How do I do this? I notice that the copy-item cmdlet (CopyItemCoreCommand)
    doesn't allow this; is it not possible?

    One a somewhat related note, how do you use the
    ValueFromPipelineByPropertyName property on the Parameter attribute? I
    initially expected it to solve exactly this problem, but it doesn't seem to.
    It is set on CopyItemCoreCommand.Path, but copy-item doesn't accept pipeline
    input, as far as I can tell.

    Nick Howell
    Nick, Feb 5, 2006
    1. Advertisements

  2. Nick

    Nick Guest

    OK, I figured out the problem (for the most part):

    when I tried to do

    ls * | copy-custom C:\

    it failed, but if I explicitly specify:

    ls * | copy-custom -Destination C:\

    it works. So now worries; it would be nice if I didn't have to specify the
    parameter name, though.

    Nick, Feb 6, 2006
    1. Advertisements

  3. The parameter binder cannot disambiguate the two conditions without
    specifying the destination as a named parameter. Basically what it is doing
    is first binding all the named parameters, then binding all the positional
    arguments to the parameters that have not yet been bound, and then taking
    pipeline input. (Note, there is really a lot more going on but I am
    simplifying for this discussion.) Since you want to support Source as a
    positional parameter with higher priority than Destination you have to give
    it a lower number. This means that whenever you have a positional argument
    specified on the command line and Source hasn't been explicitly set then the
    positional argument will be bound to it before it will be bound to
    Destination. The pipeline input isn't processed until all named and
    positional arguments have been processed.

    ValueFromPipelineByPropertyName tells the parameter binder to shred the
    incoming object and look for a property of that object that matches the name
    (or alias) of the parameter. For instance, copy-item has
    ValueFromPipelineByPropertyName on the Path (alias of MshPath) parameter.
    This allows objects coming from get-childitem item which have a property of
    MshPath to be piped into the Path (alias of MshPath) parameter. However,
    the parameter will not take a string directly as the Path parameter via
    pipeline input unless ValueFromPipeline is also specified.

    Jeff Jones [MSFT]
    Monad Development
    Microsoft Corporation
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Jeff Jones [MSFT], Feb 6, 2006
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.