2010-02-08 22 views
21

Czy istnieje sposób określenia katalogu roboczego do polecenia Uruchomienie pracy?Katalog roboczy PowerShell Start-Job

Use-case:

jestem w katalogu i chcę otworzyć plik za pomocą Emacsa do edycji. Jeśli zrobię to bezpośrednio, to zablokuje PowerShell, dopóki nie zamknę Emacs. Ale używając Start-Job próbuje uruchomić Emacs z mojego katalogu domowego, dzięki czemu Emacs otworzy nowy plik zamiast tego, który chciałem.

Próbowałem podać pełną ścieżkę, używając $ pwd, ale zmienne w bloku skryptu nie zostaną rozwiązane, dopóki nie zostaną wykonane w kontekście Start-Praca. Więc jakiś sposób na wymuszenie rozwiązania zmiennych w kontekście powłoki byłby również akceptowalną odpowiedzią na to.

Więc oto co próbowałem, tylko dla kompletności:

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

Odpowiedz

13

Możliwym rozwiązaniem byłoby stworzenie „kicker skrypt”:

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

Skrypt będzie wyglądać to:

Set-Location $args[0] 
emacs $args[1] 

Mam nadzieję, że to pomoże.

+1

to działało bardzo dobrze. Lista -ArgumentList jest dokładnie tym, czego szukałem. – jdmichal

+0

Należy pamiętać, że działa to tylko wtedy, gdy '$ workingdir' nie zawiera spacji ani innych znaków specjalnych. – DiscoInfiltrator

+0

@DiscoInfiltrator: Przejście tylko '$ workingdir' działa dobrze w PowerShellu, nawet z osadzonymi spacjami i innymi metaznakami powłoki (prawdopodobnie myślisz o powłokach podobnych do POSIX-a); zweryfikuj za pomocą '$ dir = 'C: \ Program Files \'; function foo() {set-location $ args [0]}; foo $ dir'. – mklement0

2

Tylko dla kompletności, oto ostateczny scenariusz I wdrożone na podstawie Filburt w stylu odpowiedzią społeczności Wiki:

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

spróbować tej

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

Tutaj $input jest predefiniowaną zmienną, która wewnętrznie podjęcia wartości parametru -inputobject parametr

4

Start-Job jest przesadą dla tego, czego potrzebujesz (uruchomienie polecenia w tle). Użyj Start-Process Zamiast:

Start-Process -NoNewWindow emacs RandomFile.txt 

Nie ma problemu z bieżącego katalogu w tym podejściu. Mam też stworzyliśmy funkcję, aby to tak proste, jak to możliwe:

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

a następnie wywołanie ma postać:

bg emacs RandomFile.txt 

To działa na Windows 7 (PowerShell v2).

+0

Ale proces początkowy nie ustępuje po zamknięciu terminala? – CMCDragonkai

17

Istnieje dobre rozwiązanie z comments section of some dude's post. Komentator sugeruje użycie parametru Init do ustawienia katalogu roboczego bloku skryptu.

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

++ dla najbardziej ogólnego rozwiązania: bez potrzeby użycia skryptu pomocniczego, bez argumentu wejściowego, o którym blok skryptu tła musi się znać i nim zarządzać. – mklement0

+0

powinno to mieć wartości około $ pwd do obsługi spacji na ścieżce – ghostbust555

+0

@ ghostbust555 jest poprawne, potrzebne są pojedyncze cudzysłowy, ponieważ nie jest to zmienna referencja, ale zmienna ekspansja w ciągu znaków. – Sander

3

Podsumowując problem:

  • Zadanie tło rozpoczął Start-Job robi nie odziedziczyć aktualną lokalizację (katalog roboczy).

    • Domyślnie jest $HOME\Documents w PowerShell i $HOME PowerShell rdzeniowego (od PSv5.1/PSv6 alfa).

    • Jeśli używasz PowerShell rdzenia a ty kierowania pliku w bieżącym katalogu , można użyć następujących, ponieważ nowy ... & składnia domyślnie uruchamia pracę w prąd katalog:
      emacs RandomFile.txt &

  • nie możesz bezpośrednio zmiennych referencyjnych z bieżącej sesji przekazanych do Start-Job.

celu uzupełnienia jdmichal's own helpful answer i asavartsov's helpful answer, które nadal działają dobrze:

PSv3 wprowadził prosty sposób odwoływać się do aktualnych zmiennych sesji w bloku skryptu, który jest wykonywany w innym kontekście (w tle pracy lub na komputerze zdalnym), poprzez zakres $using::

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

Alternatywnie:

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

Uwaga:

  • This GitHub issue proponuje dodanie -WorkingDirectory na ten Start-Job cmdlet.

    • Start-Job -WorkingDirectory $PWD { emacs RandomFile.txt } # WISHFUL THINKING
  • This GitHub issue donosi zaskakującą niezdolność do korzystania $using: w bloku skryptu przekazanego -InitializationScript, chociaż działa w głównym bloku skryptu (implikowana -ScriptBlock parametr).

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