简体   繁体   中英

How to pass output from a PowerShell cmdlet to a script?

I'm attempting to run a PowerShell script with the input being the results of another PowerShell cmdlet. Here's the cross-forest Exchange 2013 PowerShell command I can run successfully for one user by specifying the -Identity parameter:

.\Prepare-MoveRequest.ps1 -Identity "user@domain.com" -RemoteForestDomainController "dc.remotedomain.com" $Remote -UseLocalObject -OverwriteLocalObject -Verbose

I want to run this command for all MailUsers. Therefore, what I want to run is:

Get-MailUser | select windowsemailaddress | .\Prepare-MoveRequest.ps1 -RemoteForestDomainController "dc.remotedomain.com" $Remote -LocalForestDomainController "dc.localdomain.com" -UseLocalObject -OverwriteLocalObject -Verbose

Note that I removed the -Identity parameter because I was feeding it from each Get-MailUser 's WindowsEmailAddress property value. However, this returns with a pipeline input error.

I also tried exporting the WindowsEmailAddress property values to a CSV, and then reading it as per the following site, but I also got a pipeline problem: http://technet.microsoft.com/en-us/library/ee861103(v=exchg.150).aspx

Import-Csv mailusers.csv | Prepare-MoveRequest.ps1 -RemoteForestDomainController DC.remotedomain.com -RemoteForestCredential $Remote

What is the best way to feed the windowsemailaddress field from each MailUser to my Prepare-MoveRequest.ps1 script?

EDIT : I may have just figured it out with the following foreach addition to my Import-Csv option above. I'm testing it now:

Import-Csv mailusers.csv | foreach { Prepare-MoveRequest.ps1 -Identity $_.windowsemailaddress -RemoteForestDomainController DC.remotedomain.com -RemoteForestCredential $Remote }

You should declare your custom function called Prepare-MoveRequest instead of simply making it a script. Then, dot-source the script that declares the function, and then call the function. To accept pipeline input into your function, you need to declare one or more parameters that use the appropriate parameter attributes, such as ValueFromPipeline or ValueFromPipelineByPropertyName . Here is the official MSDN documentation for parameter attributes.

For example, let's say I was developing a custom Stop-Process cmdlet. I want to stop a process based on the ProcessID (or PID ) of a Windows process. Here is what the command would look like:

function Stop-CustomProcess {
    # Specify the CmdletBinding() attribute for our
    # custom advanced function.
    [CmdletBinding()]
    # Specify the PARAM block, and declare the parameter
    # that accepts pipeline input
    param (
        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [int] $Id
    )

    # You must specify the PROCESS block, because we want this
    # code to execute FOR EACH process that is piped into the
    # cmdlet. If we do not specify the PROCESS block, then the
    # END block is used by default, which only would run once.
    process {
        Write-Verbose -Message ('Stopping process with PID: {0}' -f $ID);
        # Stop the process here
    }
}

# 1. Launch three (3) instances of notepad
1..3 | % { notepad; };

# 2. Call the Stop-CustomProcess cmdlet, using pipeline input
Get-Process notepad | Stop-CustomProcess -Verbose;

# 3. Do an actual clean-up
Get-Process notepad | Stop-Process;

Now that we've taken a look at an example of building the custom function ... once you've defined your custom function in your script file, dot-source it in your "main" script.

# Import the custom function into the current session
. $PSScriptRoot\Prepare-MoveRequest.ps1
# Call the function
Get-MailUser | Prepare-MoveRequest -RemoteForestDomainController dc.remotedomain.com $Remote -LocalForestDomainController dc.localdomain.com -UseLocalObject -OverwriteLocalObject -Verbose;
# Note: Since you've defined a parameter named `-WindowsEmailAddress` that uses the `ValueFromPipelineByPropertyName` attribute, the value of each object will be bound to the parameter, as it passes through the `PROCESS` block.

EDIT : I would like to point out that your edit to your post does not properly handle parameter binding in PowerShell. It may achieve the desired results, but it does not teach the correct method of binding parameters in PowerShell. You don't have to use the ForEach-Object to achieve your desired results. Read through my post, and I believe you will increase your understanding of parameter binding.

我的foreach循环成功了。

Import-Csv mailusers.csv | foreach { Prepare-MoveRequest.ps1 -Identity $_.windowsemailaddress -RemoteForestDomainController DC.remotedomain.com -RemoteForestCredential $Remote }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM