Answered by:
Using Invoke-AsWorkflow with Error handling Powershell 5 for parallel processing expressions

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.
\_(ツ)_/
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.
\_(ツ)_/
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 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 scriptblockDanny 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 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.
\_(ツ)_/
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-AsWorkflowDanny 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