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

    21/صفر/1441 07: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 23/صفر/1441 12:10 ص
    • تم وضع علامة كإجابة بواسطة Ian3 24/صفر/1441 02:51 ص
    23/صفر/1441 12: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.


    \_(ツ)_/

    21/صفر/1441 07: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 22/صفر/1441 03:05 م
    22/صفر/1441 03:38 ص
  • The function must be included in the scriptblocks as always.

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


    \_(ツ)_/

    22/صفر/1441 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


    \_(ツ)_/

    22/صفر/1441 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 22/صفر/1441 03:10 م
    22/صفر/1441 02: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?


    \_(ツ)_/

    22/صفر/1441 05:55 م
    المشرف
  • It would be almost like running a pre-defined function in the foreach.
    22/صفر/1441 06: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.


    \_(ツ)_/

    22/صفر/1441 06: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 22/صفر/1441 06:52 م
    22/صفر/1441 06: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.


    \_(ツ)_/

    22/صفر/1441 07: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 23/صفر/1441 12:10 ص
    • تم وضع علامة كإجابة بواسطة Ian3 24/صفر/1441 02:51 ص
    23/صفر/1441 12:09 ص
    المشرف