I have 2 functions written in PowerShell 5. Each has code that is identical at the top and bottom but the code in the middle varies. Like this simplified version (but more complex in practice there are 9 of them not 2).
function Get-PingData {
param(
[string[]]$computers
)
# Generic stuff
Write-Host "Starting..."
# Specific stuff
$resultsArray = @()
foreach( $computer in $computers ) {
$result = Test-Connection -ComputerName $computer -Quiet
$resultsArray += $result
}
# Generic stuff
$output = ( $resultsArray -join "," )
Write-Host "Done!"
$output
}
function Test-TCPConnection {
param(
[string[]]$computers
)
# Generic stuff
Write-Host "Starting..."
# Specific stuff
$resultsArray = @()
foreach( $computer in $computers ) {
$result = ( Test-NetConnection -Port 3389 -ComputerName $computer ).TcpTestSucceeded
$resultsArray += $result
}
# Generic stuff
$output = ( $resultsArray -join "," )
Write-Host "Done!"
$output
}
$servers = @("server1", "server2")
Get-PingData $servers
Test-TCPConnection $servers
The code works but there is much commonality between them. So, I decided to make the function generic and pass a code block each time, like this:
function Get-GenericStuff {
param(
[string[]]$computers,
[scriptblock]$sb
)
# Generic stuff
Write-Host "Starting..."
# Specific stuff
$resultsArray = @()
foreach( $computer in $computers ) {
$result = $sb.Invoke()
$resultsArray += $result
}
# Generic stuff
$output = ( $resultsArray -join "," )
Write-Host "Done!"
$output
}
$servers = @("server1", "server2")
$codeblock = { Test-Connection -ComputerName $computer -Quiet }
Get-GenericStuff $servers $codeblock
$codeblock = { ( Test-NetConnection -Port 3389 -ComputerName $computer ).TcpTestSucceeded }
Get-GenericStuff $servers $codeblock
This is much shorter and also works. However, I am very uncomfortable with the fact that the codeblocks include a variable name ("$computer") that is used inside the function: if the function decides, for example, to change the variable name from $computer to $server, the codeblock also needs to be changed and this makes the code liable to break in the future.
This leads me to think that I am going about the problem incorrectly. Is there a better way to do this such that I maintain a single generic function but also avoid this brittleness?
+=) to create a collection as it is ineffective.