none
How can I call a functin in ForEach -Parallel ? RRS feed

  • שאלה

  • Function Show($s) { $s }
    '1234','5678','asdf'| ForEach -Parallel { Show $_ }

    When running above, I got error below. what's wrong?

    Show : The term 'Show' is not recognized as the name of a cmdlet, function, script file, or operable program.
    Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At line:1 char:2
    +  Show $_
    +  ~~~~
    + CategoryInfo          : ObjectNotFound: (Show:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    יום ראשון 20 אוקטובר 2019 19:10

תשובות

  • I had time to update this machine to the latest preview. The Parallel works as expected and take a scriptblock as an argument:

    '1234','5678','asdf'|
    	ForEach-Object -Parallel {
    		function Show{
    			param($s)
    			$s
    		}
    		Show $_
    	}
    The code used uses a "PSTask" named runspace for the threads.


    \_(ツ)_/


    • נערך על-ידי jrvModerator יום שלישי 22 אוקטובר 2019 00:10
    • סומן כתשובה על-ידי Ian3 יום רביעי 23 אוקטובר 2019 02:51
    יום שלישי 22 אוקטובר 2019 00:09
    מנחה דיון

כל התגובות

  • Them function must be defined inside the scriptblock.

    Start learning how to use workflow by reading the documentation provided.  Also learn how scriptblocks that run in remote or external session need to be designed. This is all basic PowerShell 1010 which you need to know before trying to use PS 7.

    The error message is fundamental to all versions of PowerShell and tells you that the item complained about is out-of-scope or does not exisit in the current PS session.


    \_(ツ)_/

    יום ראשון 20 אוקטובר 2019 19:46
    מנחה דיון
  • If this is about powershell 7, there doesn't seem to be a way besides calling a script instead.  Scriptblock variables didn't work either.

    'param($s) $s' > Show.ps1  # utf8 no bom in ps 7
    echo 1234 5678 asdf | ForEach -Parallel { .\Show $_ }

    • נערך על-ידי JS2010 יום שני 21 אוקטובר 2019 15:05
    יום שני 21 אוקטובר 2019 03:38
  • The function must be included in the scriptblocks as always.

    '1234','5678','asdf'| 
    	ForEach -Parallel {
    		function Show($s){$s}
    		Show $_ 
    	}


    \_(ツ)_/

    יום שני 21 אוקטובר 2019 03:51
    מנחה דיון
  • This is the same "ForEach-Object" but with an added functionality.

    https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7


    \_(ツ)_/

    יום שני 21 אוקטובר 2019 04:02
    מנחה דיון
  • Scriptblock example, showing that it doesn't work.

    Function Show($s) { $s }
    $a = $function:show  # scriptblock
    '1234','5678','asdf'| ForEach -Parallel { & $using:a $_ }

    ForEach : A ForEach-Object -Parallel using variable cannot be a script block. Passed-in script block variables are not supported with ForEach-Object -Parallel, and can result in undefined behavior.
    At line:1 char:23
    + '1234','5678','asdf'| ForEach -Parallel { & $using:a $_ }
    +                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidType: (Microsoft.PowerShel…orEachObjectCommand:ForEachObjectCommand) [ForEach-Object], PSArgumentException
    + FullyQualifiedErrorId : ParallelUsingVariableCannotBeScriptBlock,Microsoft.PowerShell.Commands.ForEachObjectCommand

    • נערך על-ידי JS2010 יום שני 21 אוקטובר 2019 15:10
    יום שני 21 אוקטובר 2019 14:03
  • Scriptblock example, showing that it doesn't work.

    Function Show($s) { $s }
    $a = $function:show  # scriptblock
    '1234','5678','asdf'| ForEach -Parallel { & $using:a $_ }

    ForEach : A ForEach-Object -Parallel using variable cannot be a script block. Passed-in script block variables are not supported with ForEach-Object -Parallel, and can result in undefined behavior.
    At line:1 char:23
    + '1234','5678','asdf'| ForEach -Parallel { & $using:a $_ }
    +                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidType: (Microsoft.PowerShel…orEachObjectCommand:ForEachObjectCommand) [ForEach-Object], PSArgumentException
    + FullyQualifiedErrorId : ParallelUsingVariableCannotBeScriptBlock,Microsoft.PowerShell.Commands.ForEachObjectCommand

    What does this have to do with the original question?


    \_(ツ)_/

    יום שני 21 אוקטובר 2019 17:55
    מנחה דיון
  • It would be almost like running a pre-defined function in the foreach.
    יום שני 21 אוקטובר 2019 18:04
  • A ForEach -Parallel executes the ScriptBlock in a new runspace for each iteration. That runspace is a new copy of PowerShell that cannot see the scope that the code is called from. Because of this we need to include all variables and functions in the scriptblocks.

    There is an alternate form used with ForEach that we can also use.  A ForEach has three useful parameters "Begin/Process/nd" that allow us to set up the pipeline.  (Remember that ForEach-Object only works in a pipeline.

    '1234','5678','asdf'| 
    	ForEach-Object -Begin {
    			function Show{
    				param($s)
    				$s
    			}
    			Write-Host 'Begin completed'
    		} -Process {
    			Show $_ 
    		} -End{
    			Write-Host 'End completed'
    		} -Parallel
    
    Run this with and without the "-Parallel" and it will work the same way but the "Parallel" version will use multiple runspaces.


    \_(ツ)_/

    יום שני 21 אוקטובר 2019 18:32
    מנחה דיון
  • It gives me an error:


    ForEach-Object : Missing an argument for parameter 'Parallel'. Specify a parameter of type 'System.Management.Automation.ScriptBlock' and try again.

    • נערך על-ידי JS2010 יום שני 21 אוקטובר 2019 18:52
    יום שני 21 אוקטובר 2019 18:51
  • It gives me an error:


    ForEach-Object : Missing an argument for parameter 'Parallel'. Specify a parameter of type 'System.Management.Automation.ScriptBlock' and try again.

    You are not running the correct versions of Core and PS 7.

    ForEach-Object -Parallel also also experimental in the latest preview so it may not work correctly.  Move the Parallel to the start of the list to see if that helps although it shouldn't.

    In all cases you cannot access exter5nal variables or functions for any "Parallel" operations in runspaces, jobs or workflows.  That has always been true.

    I also checked the docs and begin/process/end are not supported when "Parallel" is used.   THis will likely be changed in a future release.  Runspaces support startup code and the end-invoke can be used to supply "End" functionality.  Maybe the guys writing this will revisit and provide more consistency.

    For issue with PS7 preview you must post in UserVoice or the PowerShell Core forums.

    For now just add the function to the ScriptBlock.


    \_(ツ)_/

    יום שני 21 אוקטובר 2019 19:22
    מנחה דיון
  • I had time to update this machine to the latest preview. The Parallel works as expected and take a scriptblock as an argument:

    '1234','5678','asdf'|
    	ForEach-Object -Parallel {
    		function Show{
    			param($s)
    			$s
    		}
    		Show $_
    	}
    The code used uses a "PSTask" named runspace for the threads.


    \_(ツ)_/


    • נערך על-ידי jrvModerator יום שלישי 22 אוקטובר 2019 00:10
    • סומן כתשובה על-ידי Ian3 יום רביעי 23 אוקטובר 2019 02:51
    יום שלישי 22 אוקטובר 2019 00:09
    מנחה דיון