Вопрос

Есть ли способ указать рабочий каталог для команды Start-Job?

Вариант использования:

Я нахожусь в каталоге и хочу открыть файл с помощью Emacs для редактирования.Если я сделаю это напрямую, PowerShell заблокируется, пока я не закрою Emacs.Но использование Start-Job пытается запустить Emacs из моего домашнего каталога, в результате чего Emacs открывает новый файл вместо того, который мне нужен.

Я попытался указать полный путь с помощью $pwd, но переменные в блоке сценария не разрешаются, пока они не выполняются в контексте Start-Job.Таким образом, приемлемым ответом на этот вопрос также будет какой-то способ принудительного разрешения переменных в контексте оболочки.

Итак, вот что я попробовал, просто для полноты:

Start-Job { emacs RandomFile.txt }
Start-Job { emacs "$pwd/RandomFile.txt" }
Это было полезно?

Решение

Возможным решением было бы создание «кикер-скрипта»:

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

Ваш скрипт будет выглядеть так:

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

Надеюсь это поможет.

Другие советы

Есть хорошее решение от раздел комментариев к посту какого-то чувака.Комментатор предлагает использовать Init параметр для настройки рабочего каталога блока скрипта.

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

Подводя итог проблеме:

  • Фоновое задание началось с Start-Job делает нет наследовать текущее местоположение (рабочий каталог).

    • По умолчанию это $HOME\Documents в Windows PowerShell и $HOME в PowerShell Core (начиная с PSv5.1/PSv6 альфа).

    • Если вы используете PowerShell Основной и вы нацеливаетесь на файл в текущий каталог, вы можете использовать следующее, потому что новый ... & синтаксис по умолчанию запускает задание в текущий каталог:
      emacs RandomFile.txt &

  • Вы не можете напрямую ссылочные переменные из текущий сеанс в блоке сценария, переданном Start-Job.

Дополнять собственный полезный ответ jdmichal и полезный ответ асаварцова, которые по-прежнему работают хорошо:

PSv3 представил простой способ ссылки на текущий переменные сеанса в блоке сценария, который выполняется в другом контексте (в качестве фонового задания или на удаленном компьютере), через $using: объем:

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

Альтернативно:

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

Примечание:

  • Эта проблема на GitHub предлагает добавить -WorkingDirectory к Start-Job командлет.

    • Start-Job -WorkingDirectory $PWD { emacs RandomFile.txt } # WISHFUL THINKING
  • Эта проблема на GitHub сообщает об удивительной невозможности использования $using: в блоке сценария, переданном -InitializationScript, хотя он работает в основном блоке скрипта (подразумеваемый -ScriptBlock параметр).

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

попробуй это

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

Здесь $input — это предопределенная переменная, которая внутренне принимает значение -inputobject параметр

Start-Job — это излишество для того, что вам нужно (выполнение команды в фоновом режиме).Использовать Старт-Процесс вместо:

Start-Process -NoNewWindow emacs RandomFile.txt

При таком подходе проблем с текущим каталогом нет.Я также создал функцию, чтобы сделать это как можно проще:

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

и тогда вызов становится:

bg emacs RandomFile.txt

Это работает в Windows 7 (Powershell v2).

Для полноты картины приведу окончательный сценарий, который я реализовал на основе ответа Филберта в стиле вики-сообщества:

function Start-Emacs ( [string]$file )
{
    Start-Job -ArgumentList "$pwd\$file" { emacs $args[0] }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top