patternshellMinor
Enforcing Paired Statements Using ScriptBlock
Viewed 0 times
enforcingstatementspairedusingscriptblock
Problem
I really like c#'s
I realised that something similar can be achieved in PowerShell; e.g.
e.g.
To me this seems like a logical approach / looks neater than manually checking that all pushes are correctly paired with pops.
The only potential issue is if someone includes a
This also gives us the advantage that code won't blindly run on thinking it's in a different directory to the one specified if the
As a concept does this seem logical / have I missed anything.
NB: I'm aware it's not currently following
Using statement as it allows you to pair Open statements with their corresponding Close/Dispose statements in an elegant way which matches C#'s syntax.I realised that something similar can be achieved in PowerShell; e.g.
Push-Location should be paired with a Pop-Location, and this can be enforced by creating a function which allows you to use a USING-like syntax.e.g.
function PushDPopD {
[CmdletBinding()]
param (
[string]$Path
,
[scriptblock]$Code
)
process {
if (Push-Location $Path -PassThru) { #only proceed with this function's logic if our pushd were successful
try {
$Code.Invoke()
} finally { #ensure that whatever happens in user code, we always popd after our pushd
Pop-Location
}
}
}
}
function ShowCurrentLocation {
("You are in: {0}" -f (Get-Location).Path)
}
Clear-Host
[string]$localVariable = "We keep variables even in scriptblock context"
write-host "`n`n==Healthy Demo==`n`n" -ForegroundColor cyan
ShowCurrentLocation
PushDPopD 'c:\Users' {
"hello"
ShowCurrentLocation
$localVariable
"bye"
}
ShowCurrentLocation
write-host "`n`n==Exception Demo==`n`n" -ForegroundColor cyan
ShowCurrentLocation
PushDPopD 'c:\ThisPathDoesNotExist' {
"hello"
ShowCurrentLocation
$localVariable
"bye"
}
ShowCurrentLocationTo me this seems like a logical approach / looks neater than manually checking that all pushes are correctly paired with pops.
The only potential issue is if someone includes a
popd in the scriptblock itself; but that's no worse than the original scenario, so isn't a big drawback.This also gives us the advantage that code won't blindly run on thinking it's in a different directory to the one specified if the
pushd fails.As a concept does this seem logical / have I missed anything.
NB: I'm aware it's not currently following
verb-noun conveSolution
To be honest I feel this might be overcomplicating things.
I use
For the most part I think one should avoid changing the current location and instead reference the desired path (either relative or absolute). So something like:
rather than:
As you've seen, there are also some issues with using scriptblocks in that way. You might have scope issues with variables, and call stack/execution context will be a bit different. This might get complicated further when you consider pipelines.
So in summary I'd rather avoid changing the working directory and then not obfuscate the process when I do so it's clear what's going on.
I use
Push-Location/Pop-Location in try/finally blocks when needed (like when loading the SQLPS module), but that's almost never.For the most part I think one should avoid changing the current location and instead reference the desired path (either relative or absolute). So something like:
$p = $BasePath | Join-Path -ChildPath 'subfolder'
Get-ChildItem -Path $prather than:
$p = $BasePath | Join-Path -ChildPath 'subfolder'
Push-Location $p
try {
Get-ChildItem
} finally {
Pop-Location
}As you've seen, there are also some issues with using scriptblocks in that way. You might have scope issues with variables, and call stack/execution context will be a bit different. This might get complicated further when you consider pipelines.
So in summary I'd rather avoid changing the working directory and then not obfuscate the process when I do so it's clear what's going on.
Code Snippets
$p = $BasePath | Join-Path -ChildPath 'subfolder'
Get-ChildItem -Path $p$p = $BasePath | Join-Path -ChildPath 'subfolder'
Push-Location $p
try {
Get-ChildItem
} finally {
Pop-Location
}Context
StackExchange Code Review Q#110550, answer score: 4
Revisions (0)
No revisions yet.