It took me a while to develop something that took the accepted answer and turned it into a robust function.
I am not sure about others, but I work in an environment with machines on both PowerShell version 2 and 3, so I needed to handle both. The following function offers a graceful fallback:
Function Get-PSScriptRoot
{
$ScriptRoot = ""
Try
{
$ScriptRoot = Get-Variable -Name PSScriptRoot -ValueOnly -ErrorAction Stop
}
Catch
{
$ScriptRoot = Split-Path $script:MyInvocation.MyCommand.Path
}
Write-Output $ScriptRoot
}
It also means that the function refers to the Script scope rather than the parent's scope as outlined by Michael Sorens in one of his blog posts.