Почему объекты.NET в PowerShell не используют текущий каталог?

Когда вы используете.NET-объект из PowerShell, и он принимает имя файла, он всегда выглядит относительно C:\Windows\System32,

Например:

[IO.File]::WriteAllText('hello.txt', 'Hello World')

...напишет C:\Windows\System32\hello.txt, скорее, чем C:\Current\Directory\hello.txt

Почему PowerShell делает это? Можно ли изменить это поведение? Если это нельзя изменить, как мне обойти это?

я пробовал Resolve-Path, но это работает только с файлами, которые уже существуют, и это слишком многословно, чтобы делать все время.

6 ответов

Решение

PowerShell не поддерживает синхронизацию понятия.NET текущего рабочего каталога с понятием рабочего каталога PowerShell:

  1. Рабочие каталоги PowerShell могут быть у поставщика, который даже не основан на файловой системе, например, HKLM:\Software
  2. Один процесс PowerShell может иметь несколько пространств выполнения. Каждое пространство выполнения может быть записано в отдельную папку файловой системы. Однако "рабочий каталог".NET/process по сути является глобальным для процесса и не будет работать для сценария, в котором может быть несколько рабочих каталогов (по одному на каждое пространство выполнения).

Вы можете изменить.net working dir на powershell working dir:
[Environment]::CurrentDirectory = (Get-Location -PSProvider FileSystem).ProviderPath
После этой строки все методы.net вроде [io.path]::GetFullPath а также [IO.File]::WriteAllText будет работать без проблем

Для удобства я добавил следующее prompt функция, так что она запускается всякий раз, когда команда завершается:

# Make .NET's current directory follow PowerShell's
# current directory, if possible.
if ($PWD.Provider.Name -eq 'FileSystem') {
    [System.IO.Directory]::SetCurrentDirectory($PWD)
}

Это не обязательно хорошая идея, потому что это означает, что некоторые сценарии (предполагающие, что рабочий каталог Win32 отслеживает рабочий каталог PowerShell) будут работать на моем компьютере, но не обязательно на других.

Когда вы используете имена файлов в методах.Net, рекомендуется использовать полные пути. Или использовать

`$pwd\foo.cer`

Если вы делаете в консоли PowerShell из:

C:\> [Environment]::CurrentDirectory

C:\WINDOWS\system32\WindowsPowerShell\v1.0

Вы можете увидеть, какую папку.net использовать.

Это, вероятно, потому что PowerShell работает в System32. Когда вы переходите в каталог в PowerShell, он фактически не меняет рабочий каталог powershell.exe.

Увидеть:

PowerTip статья о синхронизации двух каталогов

Канал 9 ветка форума

Я столкнулся с той же проблемой давным-давно, и теперь я добавляю следующее в начало моего профиля:

# Setup user environment when running session under alternate credentials and
# logged in as a normal user.
if ((Get-PSProvider FileSystem).Home -eq "")
{
    Set-Variable HOME $env:USERPROFILE -Force
    $env:HOMEDRIVE = Split-Path $HOME -Qualifier
    $env:HOMEPATH = Split-Path $HOME -NoQualifier
    (Get-PSProvider FileSystem).Home = $HOME
    Set-Location $HOME
}
Другие вопросы по тегам