You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
"Actual" current directory and PowerShell current directory mismatch when using .NET BCL methods #3428
Take a process-wide lock when BCL methods are directly invoked (except for cmdlets), if multiple runspaces exist (I don't know to what extent it would impact the performance)
Switch the current directory to a dummy, default directory whenever the number of runspaces > 1 (to make the mistake clear)
Only honor the $pwd of the main runspace
Provide something like using-current-directory{ [IO.File]::WriteAllText() } that acts as a process-wide lock that sets the real current directory.
antiufo (@antiufo) Process-wide lock will not going to work, unless everyone agreed to use it and performance implication are not very good. Also, not every process host PowerShell just for sake of hosting PowerShell. Process may have its own work to do and unlikely be happy if you just change its working directory to dummy one. And as Runspaces can come and gone at process wish, it may be hard to say which one is main.
Besides, IMHO, there is good enough solution for this already:
This behavior is by design and it's been this way since version 1.0. We considered options like those proposed above but none of them were viewed as satisfactory for various reasons. Acquiring a global lock, then setting the process pwd, then calling a method is a lot of overhead when the majority of .NET APIs don't depend on pwd. Doing this also greatly complicates a host application's (e.g. exchange UI, VMM console, etc.) use of the current working directory since it can't depend on PWD anymore. The workaround for .NET APIs that take paths is to, as mentioned in another comment, resolve the path before passing It to the API which need not be onerous e.g. WriteAllText("$pwd\fileincurrentdir.txt")
Too bad that there's no good solution, because the behavior is a perennial pain point.
The "$pwd\fileincurrentdir.txt" shortcut is alluring, but - aside from assuming that the current location is a filesystem location (an assumption that will often, but not always hold) - it fails with current filesystem locations based on PS drives.
Remedying that doesn't take much extra effort, fortunately:
PetSerAl's ConvertTo-FileSystemPath helper function is the most robust and flexible approach, but anything that doesn't ship with PowerShell is unlikely to see widespread adoption.
However, what this function does could be folded into the standard Convert-Path cmdlet - see #7197
I think you've missed a use-case, and that's libraries that don't know anything about PS.
For example, Terminal.Gui has at least three APIs (related, but still - FileDialog, OpenDialog, SaveDialog) that initialize the displayed folder from [system.environment]::currentdirectory. So I have to set it to what PS thinks the working directory is before initializing any of those APIs.
Activity
PetSerAl commentedon Mar 26, 2017
If I have process with multiple
Runspaces and each one have different current location. Which one$pwdshould be honored by .NET methods?antiufo commentedon Mar 26, 2017
Possible solutions I can think of:
$pwdof the main runspaceusing-current-directory{ [IO.File]::WriteAllText() }that acts as a process-wide lock that sets the real current directory.PetSerAl commentedon Mar 26, 2017
antiufo (@antiufo) Process-wide lock will not going to work, unless everyone agreed to use it and performance implication are not very good. Also, not every process host PowerShell just for sake of hosting PowerShell. Process may have its own work to do and unlikely be happy if you just change its working directory to dummy one. And as
Runspaces can come and gone at process wish, it may be hard to say which one is main.Besides, IMHO, there is good enough solution for this already:
BrucePay commentedon Mar 28, 2017
This behavior is by design and it's been this way since version 1.0. We considered options like those proposed above but none of them were viewed as satisfactory for various reasons. Acquiring a global lock, then setting the process pwd, then calling a method is a lot of overhead when the majority of .NET APIs don't depend on pwd. Doing this also greatly complicates a host application's (e.g. exchange UI, VMM console, etc.) use of the current working directory since it can't depend on PWD anymore. The workaround for .NET APIs that take paths is to, as mentioned in another comment, resolve the path before passing It to the API which need not be onerous e.g.
WriteAllText("$pwd\fileincurrentdir.txt")mklement0 commentedon Jun 27, 2018
Too bad that there's no good solution, because the behavior is a perennial pain point.
The
"$pwd\fileincurrentdir.txt"shortcut is alluring, but - aside from assuming that the current location is a filesystem location (an assumption that will often, but not always hold) - it fails with current filesystem locations based on PS drives.Remedying that doesn't take much extra effort, fortunately:
If you also want to guard against the current location being on a different provider's drive:
PetSerAl's
ConvertTo-FileSystemPathhelper function is the most robust and flexible approach, but anything that doesn't ship with PowerShell is unlikely to see widespread adoption.However, what this function does could be folded into the standard
Convert-Pathcmdlet - see #7197essentialexch commentedon Dec 14, 2023
I think you've missed a use-case, and that's libraries that don't know anything about PS.
For example, Terminal.Gui has at least three APIs (related, but still - FileDialog, OpenDialog, SaveDialog) that initialize the displayed folder from [system.environment]::currentdirectory. So I have to set it to what PS thinks the working directory is before initializing any of those APIs.