2010-02-08 6 views
21

Gibt es eine Möglichkeit, ein Arbeitsverzeichnis für den Start-Job-Befehl anzugeben?PowerShell Start-Job-Arbeitsverzeichnis

Use-Case:

ich in einem Verzeichnis bin, und ich möchte eine Datei Emacs öffnen für die Bearbeitung verwendet wird. Wenn ich das direkt mache, wird PowerShell blockiert, bis ich Emacs schließe. Aber die Verwendung von Start-Job versucht, Emacs aus meinem Home-Verzeichnis auszuführen, so dass Emacs eine neue Datei statt der von mir gewünschten öffnet.

Ich habe versucht, den vollständigen Pfad mit $ pwd anzugeben, aber Variablen im Skriptblock werden nicht aufgelöst, bis sie im Start-Job-Kontext ausgeführt werden. Eine Möglichkeit, das Auflösen der Variablen im Shell-Kontext zu erzwingen, wäre auch eine akzeptable Antwort darauf.

So, hier ist was ich versucht habe, nur der Vollständigkeit halber:

Start-Job { emacs RandomFile.txt } 
Start-Job { emacs "$pwd/RandomFile.txt" } 

Antwort

13

Eine mögliche Lösung, die ein "Kicker-Skript" wäre zu erstellen:

Start-Job -filepath .\emacs.ps1 -ArgumentList $workingdir, "RandomFile.txt" 

Ihr Skript aussehen würde, dies:

Hoffe das hilft.

+1

Das funktionierte wirklich gut. Die -ArgumentList ist genau die Art von Dingen, die ich gesucht habe. – jdmichal

+0

Beachten Sie, dass dies nur funktioniert, wenn '$ workingdir' keine Leerzeichen oder andere Sonderzeichen enthält. – DiscoInfiltrator

+0

@DiscoInfiltrator: Die Übergabe von '$ workingdir' funktioniert problemlos in PowerShell, selbst mit eingebetteten Leerzeichen und anderen Shell-Metazeichen (Sie denken wahrscheinlich an POSIX-ähnliche Shells); verifizieren Sie mit '$ dir = 'C: \ Programme \'; Funktion foo() {set-location $ args [0]}; foo $ dir'. – mklement0

2

Nur der Vollständigkeit halber, hier ist das letzte Skript, das ich auf Filburt Antwort, Community-Wiki-Stil basiert implementiert:

function Start-Emacs ([string]$file) 
{ 
    Start-Job -ArgumentList "$pwd\$file" { emacs $args[0] } 
} 
6

versuchen, diese

Start-Job -inputobject $pwd -scriptblock { emacs "$input/RandomFile.txt" } 

Hier $input ist vordefinierte Variable, die den Wert intern nehmen von -inputobject Parameter

4

Start-Job ist ein Overkill für das, was Sie brauchen (Ausführen eines Befehls im Hintergrund). Verwenden Sie Startprozess statt:

Start-Process -NoNewWindow emacs RandomFile.txt 

Es gibt kein Problem mit dem aktuellen Verzeichnis in diesem Ansatz. Ich habe auch eine Funktion, um diese so einfach wie möglich erstellt:

function bg() {Start-Process -NoNewWindow @args} 

und dann der Aufruf wird:

bg emacs RandomFile.txt 

Dies funktioniert auf Windows 7 (Powershell v2).

+0

Aber Start-Prozess bleibt bestehen, nachdem das Terminal geschlossen wurde? – CMCDragonkai

17

Es gibt eine schöne Lösung von comments section of some dude's post. Commenter schlägt vor, den Parameter Init zu verwenden, um das Arbeitsverzeichnis des Skriptblocks einzurichten.

function start-jobhere([scriptblock]$block) { 
    Start-Job -Init ([ScriptBlock]::Create("Set-Location '$pwd'")) -Script $block 
} 
+0

++ für die allgemeinste Lösung: kein Hilfsskript benötigt, kein Eingabeargument, das der Hintergrundskriptblock kennen und handhaben muss. – mklement0

+0

Dies sollte Anführungszeichen um $ pwd haben, um Leerzeichen im Pfad zu behandeln – ghostbust555

+0

@ ghostbust555 ist korrekt, einfache Anführungszeichen sind erforderlich, da dies keine Variablenreferenz ist, sondern eine variable Erweiterung in einer Zeichenfolge. – Sander

3

das Problem Fassen wir zusammen:

  • Ein Hintergrundjob begann mit Start-Job tut nicht den aktuellen Standort erben (Arbeitsverzeichnis).

    • Es standardmäßig $HOME\Documents in Windows Powershell, und $HOME in Powershell-Core (ab PSv5.1/PSv6 alpha).

    • Wenn Sie Powershell Kern verwenden und Sie eine Datei im aktuellen Verzeichnis-Targeting, können Sie die folgende verwenden, da die neue ... & Syntax standardmäßig den Job in der läuft Strom Verzeichnis:
      emacs RandomFile.txt &

  • Sie können nicht direkt Referenzvariablen aus der aktuellen Sitzung in einem Skriptblock an Start-Job übergeben.

Zur Ergänzung jdmichal's own helpful answer und asavartsov's helpful answer, die auch noch funktionieren:

PSV3 eine einfache Art und Weise eingeführt, um das aktuelle Sitzung Variablen in einem Skriptblock zu verweisen, die (als Hintergrund in einem anderen Kontext ausgeführt wird Job oder auf einem entfernten Rechner) über die $using: -umfang:

Start-Job { Set-Location $using:PWD; emacs RandomFile.txt } 

Alternativ:

Start-Job { emacs $using:PWD/RandomFile.txt } 

Hinweis:

  • This GitHub issue schlägt eine -WorkingDirectory, um das Start-Job Cmdlets hinzufügen.

    • Start-Job -WorkingDirectory $PWD { emacs RandomFile.txt } # WISHFUL THINKING
  • This GitHub issue berichtet die überraschende Unfähigkeit $using: im Skriptblock -InitializationScript weitergegeben zu verwenden, auch wenn es im Hauptskriptblock (die impliziten -ScriptBlock Parameter) arbeitet.

    • Start-Job -Init { Set-Location $using:PWD } { emacs RandomFile.txt } # FAILS