locked
Using Invoke-AsWorkflow with Error handling Powershell 5 for parallel processing expressions RRS feed

  • Question

  • This just drives me crazy, i am trying to do a simple script that using parallel processing of a Powershell expression, as it seems this is a new command in Powershell 5 that makes this process very fast and easy to work with. the problem is that Computers with only Powershell 4 or lower need a different script for running. What happens if i run this command on a Powershell 4 is it returns this

    A parameter cannot be found that matches parameter name 'InformationAction'.
    At line:452 char:25
    + ...             Receive-Job -Job $job -Wait -Verbose -Debug -ErrorAction  ...
    +                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [Invoke-Expression], ParameterBindingException
        + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.InvokeExpressionCommand
        + PSComputerName        : [localhost]

    Im new to catch/try but as i see it, i need to figure out a way to return the computer names of the computers with and exception/error and run it with the Powershell 4 Script that is slower

    I could find a lot of example where they use the foreach -parallel but this will not work because i can end up using expressions that don't support the -computer parameter and Workflows is also limited so i can't use other Invoke commands inside the workflow.

    The command i try to work with

    Invoke-AsWorkflow -Expression "$invokeexpression" -PSComputerName $Servers
       

    I hope a kind soul would be able to help me out on this.



    Danny Nilsson

    Tuesday, October 31, 2017 3:16 PM

Answers

  • I found a solution today. there is a script called invoke-parallel that exactly do the thing i was searching for, and a lot more

    https://github.com/RamblingCookieMonster/Invoke-Parallel

    But it was a bit unclear from the documentation how to use the scriptblock remotely, the script has a -computer but it only runs locally, so i came up with this line that solves my problem. it might be that the computer parameter only works with Ps1 files, i havn't looked much into the code yet.

    $server | Invoke-Parallel -ScriptBlock {invoke-command -computername $_.computername -scriptblock {$PSVersionTable.PSVersion}}

    Another working alternative that was more like the run jobas https://github.com/proxb/PoshRSJob.

    i didn't think that a nested invoke command would have worked. so for correcting some of my own script i should have started creating my own -scriptblock variable instead of inventing a new way to store powershell expressions. that would have been more correct.


    Danny Nilsson

    • Marked as answer by Mooock Wednesday, November 1, 2017 12:01 PM
    Wednesday, November 1, 2017 12:01 PM

All replies

  • Don't use "InformationAction" and see what happens.

    Your questions is too vague for us to be of much help.  I suggest that you should learn basic PowerShell before trying to use advanced capabilities like workflow.


    \_(ツ)_/

    Tuesday, October 31, 2017 3:45 PM
  • i don't use anything with informationaction, as you can see i only write this command, and it comes from powershell not understanding the command invoke-asworkflow with -expression
    Invoke-AsWorkflow -Expression "$invokeexpression" -PSComputerName $Servers

    Danny Nilsson

    Tuesday, October 31, 2017 3:57 PM
  • What is $invokeexpression and why is it in quotes?  We don't want to quote strings.


    \_(ツ)_/

    Tuesday, October 31, 2017 4:36 PM
  • The $invokeexpression is used to call a Powershell command from a function parameter. so for that to recognize as powershell command i came up with this solution. the script function would be something similar to invoke-command but just multithreaded parallel, but run into a lot of limitations because not all my servers are able to run Powershell 5 where everything works

    Danny Nilsson

    Tuesday, October 31, 2017 5:10 PM
  • Why would you use Invoke-Expression to do this?  That makes no sense.  Just execute the PS1 file or the function. 


    \_(ツ)_/

    Tuesday, October 31, 2017 5:12 PM
  • At the moment i try to test out some Workflow inlinescript where i can use the normal powershell scripts, but then i don't know if i still are able to benefit from parallel processing, and if invoke commands still not are allowed here

    Danny Nilsson

    Tuesday, October 31, 2017 5:15 PM
  • You are still being way to vague.  We cannot help when you are not clear with your script.


    \_(ツ)_/

    Tuesday, October 31, 2017 5:19 PM
  • Why would you use Invoke-Expression to do this?  That makes no sense.  Just execute the PS1 file or the function. 


    \_(ツ)_/

    This is not and normal invokeexpression its, Invoke-AsWorkflow -Expression "get-childitem c:\" could have been the variable, the full script queries a lots of AD computers where i want to be able to run all commands en parallel as a function, so here it could be get-WBComputers -invokeexpressions "$PSVersionTable.PSVersion" for a powershell command this to work from a variable it needs the expression parameter,

    the full script is a lot bigger, but wanted to keep it as simple as possible to not make confusion.

    Danny Nilsson

    Tuesday, October 31, 2017 5:22 PM
  • Invoke-expression works with a foreach loop i made but is slow when using many computers. so thats why i try to optimize the speed with the Invoke-AsWorkflow that only works with Powershell 5.

    so to be clear i look for a way to retrive computername if the Invoke-AsWorkflow fails to run, so i can start using a different set of commands,

    it wouldnt make sense to post the full script, because it depends on a lot other functions and a very specific for the current environment.

    Danny Nilsson

    Tuesday, October 31, 2017 5:26 PM
  • Use Invoke-AsWorkflow -CommandName <your powershell command> -Arguments <your argumenat>

    See the examples in help for more variations.

    "_Expression" is used to execute non-PowerShell commands like "IPCONFIG /ALL" on remote systems.

    You cannot turn a set of PowerShell commands  into a string and have them work here.


    \_(ツ)_/

    Tuesday, October 31, 2017 5:42 PM
  • Use Invoke-AsWorkflow -CommandName <your powershell command> -Arguments <your argumenat>

    See the examples in help for more variations.

    "_Expression" is used to execute non-PowerShell commands like "IPCONFIG /ALL" on remote systems.

    You cannot turn a set of PowerShell commands  into a string and have them work here.


    \_(ツ)_/

    As i wrote earlier the Invoke-AsWorkflow works fine as long the computer has powershell version 5. so the script needs some erroraction in case it won't execute, i used an array of computers without issues, but all the ps4 computers came up with the error i wrote in the first message. i can't update these servers because they have been running for over 600 days and don't have the permission for that. but all the ps4 servers work fine with the slower Invoke-Command so how do i catch the error from the Invoke-AsWorkflow and which computers that failed

    Danny Nilsson

    Tuesday, October 31, 2017 6:07 PM
  • Run Invoke-Command on all computers as a job.  They will run in parallel.

    Invoke-Command -AsJob

    You can collect errors on any CmdLet with "ErrorVariable"


    \_(ツ)_/

    Tuesday, October 31, 2017 6:17 PM
  • Run Invoke-Command on all computers as a job.  They will run in parallel.

    Invoke-Command -AsJob

    You can collect errors on any CmdLet with "ErrorVariable"


    \_(ツ)_/

    I was also thinking about that from the start, but didnt seem like the correct approch, compared to workflow. if i run asjob i will never know when the jobs are done on all computers, do you know if there are any examples of Asjob and multiply computers? because if the Invoke-Command could work in parallel then i would not need the error handling at all.

    I can see from the documentation that they run it like i would
    Invoke-AsWorkflow -CommandName "Get-ExecutionPolicy" -PSComputerName (Get-Content Servers.txt)
    https://docs.microsoft.com/en-us/powershell/module/psworkflowutility/invoke-asworkflow?view=powershell-5.1

    but then how to errorhandle the computers where the invoke not was running correctly

    Danny Nilsson


    • Edited by Mooock Tuesday, October 31, 2017 6:39 PM
    Tuesday, October 31, 2017 6:24 PM
  • I think you need to start by learning basic PowerShell. Start by learning how to use help in a usefule way.

    help help -online

    Then you will learn how to use jobs

    help about_jobs

    By learning the basics you will avoid getting stuck and not knowing how to ask a question that will get you a quick answer. 

    There are tens of thousands of CmdLets.  They all come with comprehensive help.  If you have to ask in a forum for each  new CmdLet you will never get anywhere.

    help get-job -online

    look at the examples.


    \_(ツ)_/

    Tuesday, October 31, 2017 6:42 PM
  • I have used help, google, youtube videos, and used a lot of handson with powershell. so its not that i havn't read up on this before i came to ask a question. if you read up on the Invoke-AsWorkflow you will see it is the correct way to go, the Asjob seems more like a workaround that are not ment for this kind of job.


    Danny Nilsson

    Tuesday, October 31, 2017 7:00 PM
  • Well if you have an answer that can overcome the limitations of PowerShell I am sure we would all like to hear it.

    Reading posts and forums is not the same thing as taking a structured course in PowerShell.  Guessing cannot teach you the fundamentals.

    Using AsJob will allow you to gain parallelism on systems that do not support your workflow.

    There is no way to guess as to what your script is doing so there is no way to address your issue.  We can only guess and you can see how good guessing is.


    \_(ツ)_/

    Tuesday, October 31, 2017 7:36 PM
  • I found a solution today. there is a script called invoke-parallel that exactly do the thing i was searching for, and a lot more

    https://github.com/RamblingCookieMonster/Invoke-Parallel

    But it was a bit unclear from the documentation how to use the scriptblock remotely, the script has a -computer but it only runs locally, so i came up with this line that solves my problem. it might be that the computer parameter only works with Ps1 files, i havn't looked much into the code yet.

    $server | Invoke-Parallel -ScriptBlock {invoke-command -computername $_.computername -scriptblock {$PSVersionTable.PSVersion}}

    Another working alternative that was more like the run jobas https://github.com/proxb/PoshRSJob.

    i didn't think that a nested invoke command would have worked. so for correcting some of my own script i should have started creating my own -scriptblock variable instead of inventing a new way to store powershell expressions. that would have been more correct.


    Danny Nilsson

    • Marked as answer by Mooock Wednesday, November 1, 2017 12:01 PM
    Wednesday, November 1, 2017 12:01 PM
  • My end result looks like this, and works perfectly

    $scriptblock = {$PSVersionTable.PSVersion}
    $blockcode = [Scriptblock]::Create($scriptblock)
    $Computers | Invoke-Parallel -ImportVariables -ScriptBlock {Invoke-command -computername $_ -scriptblock $blockcode}

    so in my current script i use a switch for setting the variable for the scriptblock



    Danny Nilsson

    Thursday, November 2, 2017 12:45 PM
  • The following creates a script block:

    $scriptblock = {$PSVersionTable.PSVersion}

    There is no need to do it twice

    There is also no need to use Invoke-Command.

    $computers | Invoke-Parallel -ImportVariables -ScriptBlock $scriptblock

    You need to read the help and examples for this carefully.  Note that it also has little to do with your original question as this is not a workflow. It is more related to using jobs.


    \_(ツ)_/

    Thursday, November 2, 2017 2:30 PM
  • Hi

    the first scriptblock i don't use in the full script, it comes from a parameter switch, i only added it to show the example. but the invoke is needed, i started out without using it and couldn't understand why my script only ran on the local computer. that because the invoke-parallel have a lot of different operations like running ps1 scripts locally in parallel, so if i don't do the invoke part it will only run the command on local computer

    so if this part PSVersionTable.PSVersion comes from a command parameter and put into a variable, then it can not be passed to the $scriptblock and be identified as a powershell command, that was why i did a convert of string to scriptblock


    Danny Nilsson

    Thursday, November 2, 2017 2:43 PM
  • Unfortunately you don't understand what is happening which is why you are having trouble with the code and the suggested answers.  Take some time to learn basic PowerShell.  You need to get a much deeper understanding of both programming and how PowerShell implements fundamental processes.

    A script block is automatically executed in the remote context.  The function you downloaded only works correctly if you use it correctly.  YOU are not using it correctly so you are fudging your code to make it appear to work.

    Since you are never posting actual code it is impossible to tell you why your code is failing.


    \_(ツ)_/

    Thursday, November 2, 2017 2:53 PM
  • Note that this works exactly as expected.

    Invoke-AsWorkflow -Expression {$env:computername} -PSComputerName ws701,ws702,ws703,ws704

    It runs the script block on each of the listed computers an it runs it in parallel.  A simple command like that will not appear to run parallel because all job, workflows and runspaces have a large amount of overhead to get started.  Larger scripts will show improved performance as the setup only happens once per invocation.

    Again - learning basic PowerShell and learning how the subsystems work will help you avoid the kind of confusion and thrashing you are now caught up in.


    \_(ツ)_/

    Thursday, November 2, 2017 2:58 PM
  • I apologize for not being an Powershell expert and thought it was ok to ask a question for something i don't know. I have done my best to make my question as simple as possible and responded to everything i was asked. I am aware that i still have a lot to learn, but also do my best to gather all the information i can to get better.

    but have you even tried the script invoke-parallel? as i have wrote earlier the script is a part of many functions so i only took the piece that was a part of the actual function that caused challenges, so i don't see what wrong by doing that?

    the Invoke-parallel don't work like Invoke-Command as it could seems like, and is a 3rd party function


    Danny Nilsson

    Thursday, November 2, 2017 3:04 PM
  • Note that this works exactly as expected.

    Invoke-AsWorkflow -Expression {$env:computername} -PSComputerName ws701,ws702,ws703,ws704

    It runs the script block on each of the listed computers an it runs it in parallel.  A simple command like that will not appear to run parallel because all job, workflows and runspaces have a large amount of overhead to get started.  Larger scripts will show improved performance as the setup only happens once per invocation.

    Again - learning basic PowerShell and learning how the subsystems work will help you avoid the kind of confusion and thrashing you are now caught up in.


    \_(ツ)_/

    This example you did only works for powershell 5, but its a very nice command though.
    this is my result on one ps4 and ps5 server
    PS C:\Windows\system32> Invoke-AsWorkflow -Expression {$env:computername} -PSComputerName apptest01
    APPTEST01
    PS C:\Windows\system32> Invoke-AsWorkflow -Expression {$env:computername} -PSComputerName apptest02
    A parameter cannot be found that matches parameter name 'InformationAction'.
        + CategoryInfo          : InvalidArgument: (:) [Invoke-Expression], ParameterBindingException
        + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.InvokeExpressionCommand
        + PSComputerName        : [localhost]
    
    PS C:\Windows\system32>


    Danny Nilsson

    Thursday, November 2, 2017 3:08 PM
  • I suspect that you PS 4 system has a problem. THe same code works for me on PS4 with no issues.  The error reported indicates some form of corruption to the PS4 system.


    \_(ツ)_/

    Thursday, November 2, 2017 3:13 PM
  • I suspect that you PS 4 system has a problem. THe same code works for me on PS4 with no issues.  The error reported indicates some form of corruption to the PS4 system.


    \_(ツ)_/

    This is how the computers look
    Major  Minor  Build  Revision PSComputerName                                                                                                                                                                                                                     
    -----  -----  -----  -------- --------------                                                                                                                                                                                                                     
    5      1      14409  1012     APPTEST01                                                                                                                                                                                                                          
    4      0      -1     -1       APPTEST02                                                                                                                                                                                                                          
    We have the same problem on all our servers when i try to use the Invoke-AsWorkflow

    Danny Nilsson

    Thursday, November 2, 2017 3:16 PM
  • You are likely missing a Net version upgrade.


    \_(ツ)_/

    Thursday, November 2, 2017 3:18 PM
  • its for sure something is not updated on these servers, that is why i started a script that was backward compatible and maybe solve it by the catch,try when this error came up. 

    but the invoke-parallel returns result down to version 2 of Powershell. Did you mange to get Invoke-Parallel working without invoke-command?


    Danny Nilsson

    Thursday, November 2, 2017 3:28 PM