Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use a parameterized script block with Where-Object in Powershell?

Tags:

powershell

Is there a better approach for passing information into script blocks in where-object filter scripts than using parent-scoped variables?

Background:

I have a script that looks for un-checked-in and/or modified source files vs. source control and has a parameter that allows it to do a more exhaustive search. I use where-object in a couple of places with a script block object contained in a script-scoped variable that I customize based on the input parameters to the script.

So, if you ask for a thorough search, the filter will compare the candidate file against all TFS files to see if the file isn't in source control, if you choose the less-thorough search, the filter will only compare against checked-out files to see if the file is modified but not checked out.

The customized script blocks refer to script-scoped variables containing the results of doing queries against source control.

So my problem is that I'd like to get rid of a global (script-level) variable and pass all the necessary information into the script blocks as parameters to the script blocks. If I was using invoke-command, I'd use the ArgumentList parameter to do this. Where-Object doesn't seem to have that. One downside of using parent-scoped variable references in the script blocks is that I can't change those variables, so I can't do lazy initialization (or at least I haven't figured out how yet, not being an expert on the scoping rules for Powershell.)

like image 870
David Gladfelter Avatar asked Feb 10 '11 17:02

David Gladfelter


People also ask

Which of these are parameters that can be used by where-object cmdlet?

The Where-Object cmdlet selects objects that have particular property values from the collection of objects that are passed to it. For example, you can use the Where-Object cmdlet to select files that were created after a certain date, events with a particular ID, or computers that use a particular version of Windows.

How do I run a PowerShell script with a parameter?

You can run scripts with parameters in any context by simply specifying them while running the PowerShell executable like powershell.exe -Parameter 'Foo' -Parameter2 'Bar' . Once you open cmd.exe, you can execute a PowerShell script like below.

What is the use of $_ in PowerShell?

$_ is an alias for automatic variable $PSItem (introduced in PowerShell V3. 0; Usage information found here) which represents the current item from the pipe. PowerShell (v6. 0) online documentation for automatic variables is here.

Is an alias for where-object command?

'?' is an alias to the Where-Object cmdlet. Where-Object takes a scriptblock (e.g '{...}') and evaluates its code. If the code evaluates to $true, the current object is written to the pipeline and is available to the next command in chain, otherwise ($false) the object is discarded.


1 Answers

Just to expand a bit on what Keith mentioned, you could do it like this:

ps> $x=2
ps> 1..5 | where (& {param($v); { $_ -eq $v }.getnewclosure() } $x )
2

I tried closing over implict $args to save the param declaration but $args seems exempt from capture. More likely it is being captured but just getting stomped on.

$x could easily be replaced with another function call like (get-x).

Essentially I'm calling a scriptblock that returns a scriptblock which closes over the outer scriptblocks parameter. Same implementation as Keiths essentially, just a little more succint [and obtuse.] Lambdas for the win.

I only wish there was a more pithy way to get closure semantics. That said, I'm glad the method got put in rather than not.

-Oisin

like image 170
x0n Avatar answered Nov 15 '22 10:11

x0n