Let's say I have a simple scope that is book-ended with Push-Location and Pop-Location:
Function MyFunction($Location)
{
Push-Location $Location
# do other stuff here
Pop-Location
}
Is there any way to set it up at the beginning of the scope so that I don't have to remember to put the Pop-Location at the end? Something like this:
Function MyFunction($Location)
{
Setup-BothPushAndPopHere $Location
# do other stuff here
# at the end of the scope, Pop-Location is automatically called
}
Short answer: No.
My take on Push-Location
and Pop-Location
is that you should generally avoid them, and adapt your script to use the path names in commands instead; in other words, instead of:
Push-Location $Location
Get-ChildItem
Pop-Location
Just do:
Get-ChildItem $Location
(simplified example)
If you must use the pattern, consider try
/finally
:
Push-Location $Location
try {
# ...
} finally {
Pop-Location
}
As this helps with unexpected exceptions or the user interrupting program execution.
I typically use the try
/finally
pattern when the code is outside my control; most often when loading the SQLPS
module since it changes the current location to the SQL server provider which in my experience causes everything that uses the current location to become much slower.
As Eris points out, it's also useful when dealing with native applications. This can be especially true if it's painful to escape quotes around path names with spaces, or the application wouldn't handle it correctly anyway.
Depending on what you try to do in the #do other stuff here
code, you could try executing those commands as a script block in a child process. A skeleton-code example:
$ScriptBlock = {
Push-Location $Location
#commands
}
$Job = Start-Job -ScriptBlock $ScriptBlock # Add other arguments if needed
# Check the status of the task:
Get-Job $Job
# Wait for the job state to be 'Completed' (do-while, maybe?)
# If your ScriptBlock writes any output, collect in a variable:
$Output = Receive-Job $Job
# Clean up:
Remove-Job $Job
The point of this approach is that you spawn a job to do the work (in the background) and you needn't worry about Pop-Location
as you just let that child scope exit while you carry on doing whatever you need to do in your main script.
There are other posts here on StackExchange that go into more detail about powershell-jobs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With