none
How to find the Count of Objects in a pipeline Input for advanced functions ? RRS feed

  • Question

  • Hi,

    I have a question regarding the pipeline input for advanced functions.

    How do I know how many total no of objects are in the pipeline ?

    The process block does it one by one. So how do I get the total number ?

    For the below example, how do I know the count of servers in the text file a user would be specifying and use it for my function to build a progress bar may be ?

    EX:

    Function Test-PipeLineInput {

    Param(

    [Parameter(

    Valuefrompipeline = $True

    )]

    $ComputerName

    )

    Process{

    Get-Process -computername $ComputerName

       }

    }

    Get-content $home\desktop\servers.txt | Test-PipeLineInput


    If you find this helpful, kindly mark as answer. If you have any queries, please post back as a reply. Will look forward to your feedback. Thanking You Soumyajyoti Biswas

    Thursday, May 19, 2016 11:02 AM

Answers

  • Preview method:

    function test{
    	Param([Parameter(ValueFromPipeline)]$x)
    	end{
    		Write-Host "Count: $($input.Count)" -fore green
    		$input
    	}
    }
    PS D:\scripts> 1..10|test
    10
    dir \test\*.txt |test | Remove-Item -WhatIf

    There is only one way to get the count out of the pipeline.  Run it in  separate runspace and assign the value to a synced hash.


    \_(ツ)_/

    Thursday, May 19, 2016 1:39 PM

All replies

  • I think this will get you the total .

    End{
        $input.Count
    }


    \_(ツ)_/

    Thursday, May 19, 2016 12:12 PM
  • Yes - it works as expected:
     PS D:\scripts> function test{
    >> Param([Parameter(ValueFromPipeline)]$x)
    >> end{$input.Count}
    >> }
    PS D:\scripts> 1..10|test
    10


    \_(ツ)_/

    Thursday, May 19, 2016 12:14 PM
  • Interesting it only works in the end block, (it doesn't for me in the begin or process blocks) which implies that it won't help this particular situation.

    Does this have anything to do with block vs stream processing for pipeline events?

    Thursday, May 19, 2016 12:35 PM
  • I think this will get you the total .

    End{
        $input.Count
    }


    \_(ツ)_/

    Interesting.. This works if the end block is by itself, but doesn't if you introduce a process block.

    PS C:\Scripts\PowerShell Scripts\Misc Testing\5-19-2016> function test{
    Param([Parameter(ValueFromPipeline)]$x)
    process {$x}
    end{$input.count}
    }
    
    1..5|test
    1
    2
    3
    4
    5
    0

    I've done this in the past, but it's likely overkill:

    Function Test-Function {
    
        [CmdletBinding()]
    
        param(
            [Parameter(Mandatory,ValueFromPipeline)]
            [string[]]
            $ComputerName
        )
        
        begin {
    
            $totalCount = 0
            $computerList = @()
    
        }
    
        process {
    
            foreach ($computer in $ComputerName) {
    
                $totalCount++
                $computerList += $computer
    
            }
    
        }
    
        end {
    
            Write-Host "Total count is $totalCount" -ForegroundColor Yellow
    
            foreach ($computer in $computerList) {
    
                Write-Host "Working on $computer" -ForegroundColor Green
    
            }
    
        }
    
    }
    
    Get-Content .\pcList.txt | Test-Function
    Test-Function -ComputerName 'PC1','PC2','PC3'


    Thursday, May 19, 2016 12:39 PM
  • It does if you use the same variable, so in the original post $computerName and $computerName.Count in the end block.

    edit: or am I missing something?

    Thursday, May 19, 2016 12:47 PM
  • Hi,

    Well I needed it to work out in the process block somehow.

    The process block executes for each object in the pipeline and then comes down to end block.

    In such cases, end block will have $input as 0 as all objects would have been processed

    So would beat my purpose of creating a progress bar using the total count of objects and the current object index using a loop.


    Thursday, May 19, 2016 1:08 PM
  • We would add a dummy function to the pipeline with only an end block.  It will pass everything correctly and should then see the full object.

    The other method is to just count in the process block:

    function test{
    	Param(
    		[Parameter(ValueFromPipeline)]$x
    	)
    	Begin{$count=0}
            Process{ $_;$count++}
    	End{Write-Host "Count: $count" -fore green }
    }
    
    PS D:\scripts> dir \test\*.txt |test
    
    
        Directory: D:\test
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        4/30/2016  12:36 PM          26700 dir.txt
    -a----        4/30/2016  12:36 PM            996 direrr.txt
    -a----         5/2/2016   8:00 AM           2068 rstest.txt
    Count: 3


    \_(ツ)_/

    Thursday, May 19, 2016 1:31 PM
  • Hi,

    Well I needed it to work out in the process block somehow.

    The process block executes for each object in the pipeline and then comes down to end block.

    In such cases, end block will have $input as 0 as all objects would have been processed

    So would beat my purpose of creating a progress bar using the total count of objects and the current object index using a loop.



    What you are trying to do will not work. There is no way to get the count inside of the active pipeline.  Either count objects in advance or guess.

    \_(ツ)_/

    Thursday, May 19, 2016 1:32 PM
  • Hi,

    Well I needed it to work out in the process block somehow.

    The process block executes for each object in the pipeline and then comes down to end block.

    In such cases, end block will have $input as 0 as all objects would have been processed

    So would beat my purpose of creating a progress bar using the total count of objects and the current object index using a loop.



    Function Test-Function {
    
        [CmdletBinding()]
    
        param(
            [Parameter(Mandatory,ValueFromPipeline)]
            [string[]]
            $ComputerName
        )
        
        begin {
    
            $totalCount = 0
            $computerList = @()
    
        }
    
        process {
    
            foreach ($computer in $ComputerName) {
    
                $totalCount++
                $computerList += $computer
    
            }
    
        }
    
        end {
    
            $counter = 1
    
            Write-Host "Total count is $totalCount" -ForegroundColor Yellow
    
            foreach ($computer in $computerList) {
    
                Write-Host "Working on $computer" -ForegroundColor Green
                Write-Progress -Activity 'Processing computers' -Status "Processing $computer" -PercentComplete ($counter / $totalCount * 100)
                Start-Sleep -Seconds 1 # PoC purposes only
                $counter++
    
            }
    
        }
    
    }
    
    Get-Content .\pcList.txt | Test-Function
    Test-Function -ComputerName 'PC1','PC2','PC3'


    Thursday, May 19, 2016 1:37 PM
  • Preview method:

    function test{
    	Param([Parameter(ValueFromPipeline)]$x)
    	end{
    		Write-Host "Count: $($input.Count)" -fore green
    		$input
    	}
    }
    PS D:\scripts> 1..10|test
    10
    dir \test\*.txt |test | Remove-Item -WhatIf

    There is only one way to get the count out of the pipeline.  Run it in  separate runspace and assign the value to a synced hash.


    \_(ツ)_/

    Thursday, May 19, 2016 1:39 PM
  • This is great.
    Thursday, May 19, 2016 3:08 PM