2012-06-28 4 views
8

Wenn Sie ein .NET-Objekt von PowerShell verwenden, und es einen Dateinamen akzeptiert, scheint es immer relativ zu C:\Windows\System32 zu sein.Warum verwenden .NET-Objekte in PowerShell nicht das aktuelle Verzeichnis?

Zum Beispiel:

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

... wird C:\Windows\System32\hello.txt schreiben, anstatt C:\Current\Directory\hello.txt

Warum Powershell dies tun? Kann dieses Verhalten geändert werden? Wenn es nicht geändert werden kann, wie kann ich es umgehen?

Ich habe versucht, Resolve-Path, aber das funktioniert nur mit Dateien, die bereits existieren, und es ist viel zu ausführlich, die ganze Zeit zu tun.

+1

möglich Duplikat [Warum ist Powershell-Lösung Pfade von $ home anstelle des aktuellen Verzeichnisses?] (http://stackoverflow.com/questions/4071775/why-is-powershell-resolving-paths-from-home-instead-of-the-current-directory) –

Antwort

7

Die Gründe Powershell nicht halten die .NET Begriff des aktuellen Arbeitsverzeichnis in Synchronisierung mit Powershell Vorstellung des Arbeits dir sind:

  1. Powershell arbeiten dirs in einem Provider sein kann, das nicht einmal System basierend zB Datei ist HKLM: \ Software
  2. Ein einzelner PowerShell-Prozess kann mehrere Runspaces haben. Jeder Runspace kann in eine andere Datei System-Speicherort cd`d. Allerdings ist das .NET/Prozess "Arbeitsverzeichnis" im Wesentlichen eine globale für den Prozess und würde nicht für ein Szenario arbeiten, in dem es mehrere Arbeits-Dirs (eine pro Runspace) sein kann.
+1

Fair genug. Kann der normale PowerShell-Prozess mehrere Runspaces haben? –

+2

@RogerLipscombe Es ist nicht sehr verbreitet, dass AFAICT für PowerShell.exe mehrere Runspaces verwendet, aber die PowerShell-Engine bietet diese Funktion. Andere Hosts wie PowerShell_ISE und PowerGUI nutzen mehrere Runspaces in einem einzigen Prozess. Starten Sie ISE, drücken Sie Strg + T (neue Powershell-Registerkarte) und führen Sie $ pid gefolgt von $ ExecutionContext.Host.Runspace.InstanceId in jedem Register aus. Beachten Sie, dass die Prozess-ID identisch ist, die Runspace-ID jedoch anders ist. –

0

Das liegt wahrscheinlich daran, dass PowerShell in System32 ausgeführt wird. Wenn Sie in ein Verzeichnis in PowerShell wechseln, wird das Arbeitsverzeichnis von powershell.exe nicht geändert.

See:

PowerTip article on syncing the two directories

Channel9 forum thread

+0

Stellt sich heraus, dass Dies ist ein Duplikat von http: // stackoverflow.com/questions/4071775/why-is-powershell-resolving-paths-from-home-statt-des-aktuellen-verzeichnisses, aber weil ich ausgeführt werde, ist es nicht $ HOME. –

+0

Ja, das würde es tun - obwohl, wenn du nicht erhöht wärst und du 'cd $ folder' hättest, würdest du auf' $ HOME' operieren. Aber das ist der Grund, warum $ PWD nicht respektiert wurde - weil dieser Code Windows tatsächlich nach dem Prozessarbeitsverzeichnis fragte, aber die Variable $ PWD ist ein PowerShell-Artefakt, kein Windows-Objekt. – JohnL

0

Wenn Sie Dateinamen in .NET-Methoden verwenden, die beste Praxis ist voll qualifizierte Pfadnamen zu verwenden. Oder verwenden

`$pwd\foo.cer` 

Wenn Sie in Powershell-Konsole tun aus:

C:\> [Environment]::CurrentDirectory 

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

Sie können sehen, welche Ordner .net Verwendung.

+1

Fair genug in Skripten. Wird in der Befehlszeile schnell alt. –

0

Ich lief in das gleiche Problem vor langer Zeit und nun folgendes an den Anfang meines Profils ich hinzufügen:

# 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 
} 
+0

Das antwortet, warum es System32 ist, in meinem Kommentar, danke; aber es beantwortet nicht direkt die Frage. –

15

Sie können .net arbeiten dir ändern Arbeitsverzeichnis zu Powershell:
[Environment]::CurrentDirectory = (Get-Location -PSProvider FileSystem).ProviderPath
Nach dieser Linie alle .net Methoden wie [io.path]::GetFullPath und [IO.File]::WriteAllText wird ohne Probleme funktionieren

Verwandte Themen