9

What I want:

I have a script, which copies CAB-Files to over a hundred Servers, and works with it on them. This script runs for over a week. As I learned about the Foreach-Object -parallel Feature, I thought this would speed up the script considerably. But I ran into a problem. Since I am not very PowerShell knowledgeable, and I didn't find a post about this problem anywhere, I thought, I going to try my luck and ask here:

Expected and actual results

I want to pass a variable to the executed scriptblock in the foreach-object cmdlet, like here:

$test = "123"
1..3|foreach-object -parallel {param($test);echo "$_, $test"} -ArgumentList($test)

What I expect:

1, 123
2, 123
3, 123

What I get:

ForEach-Object: Parameter set cannot be resolved using the specified named parameters. One or more parameters issued cannot be used together or an insufficient number of parameters were provided.

What am I doing wrong?

It might be an trivial problem. But since I don't get anywhere and don't find any post/code example. I post it here. I am thankful for answers.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Sukram22
  • 93
  • 1
  • 4
  • 2
    If the script runtime is _over a week_, I think you'd need a major rewrite in the architecture. Parallel processing might be one approach, but there likely are other and smarter ways. – vonPryz Sep 16 '20 at 07:42
  • i suspect you need a total rework of the process. one way would be to drop the copy command to the remote systems & let them do the copy. your current outline gives the impression that you are copying from a source, to the system that is running the code, and - finally - to the destination. a faster method would be from the source to the destination - and have it controlled on the destination side. – Lee_Dailey Sep 16 '20 at 08:01
  • @Lee_Dailey Exactly this is what I am trying to do. I got the script like you mentioned like this: foreach Server copy cab-file, do stuff. I am doing it now like this: servers|foreach-object -parallel{invoke command to server (copy cab-file, do stuff)}. To ensure readability, I want to define the variables, functions outside of the foreach-object, and pass them. There I ran into my problem. – Sukram22 Sep 16 '20 at 08:26
  • ah! i don't see that in your Question ... but it looks like MartinBrandl has pointed out the problem & the fix. excellent! [*grin*] – Lee_Dailey Sep 16 '20 at 08:46

1 Answers1

14

You can simplify that by using the using keyword :-)

$test = "123"
1..3 | foreach-object -parallel { echo "$_, $($using:test)" } 
Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
  • I wonder why I couldn't find something like this on the M$ help pages that fill the search results. Thank you! – Pascal Nov 03 '20 at 14:03
  • There's a note about `-Parallel` and `$using` in the notes section of [`ForEach-Object`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7.1#notes). – Robert Dennis Sep 14 '21 at 20:56