Установка начального каталога при вызове Powershell из .NET?
Я использую API System.Management.Automation для вызова сценариев PowerShell в С# WPF-приложении. В следующем примере, как бы вы изменили начальный каталог ($ PWD), чтобы он выполнял foo.ps1 из C:\scripts\вместо местоположения .exe, он был вызван из?
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
using (Pipeline pipeline = runspace.CreatePipeline())
{
pipeline.Commands.Add(@"C:\scripts\foo.ps1");
pipeline.Invoke();
}
runspace.Close();
}
Ответы
Ответ 1
Вам не нужно изменять System.Environment.CurrentDirectory
, чтобы изменить рабочий путь для ваших сценариев PowerShell. Это может быть довольно опасно, потому что это может иметь непреднамеренные побочные эффекты, если вы используете другой код, чувствительный к вашему текущему каталогу.
Поскольку вы предоставляете Runspace
, все, что вам нужно сделать, это установить свойства Path
в SessionStateProxy
:
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
runspace.SessionStateProxy.Path.SetLocation(directory);
using (Pipeline pipeline = runspace.CreatePipeline())
{
pipeline.Commands.Add(@"C:\scripts\foo.ps1");
pipeline.Invoke();
}
runspace.Close();
}
Ответ 2
Настройка System.Environment.CurrentDirectory
заблаговременно сделает то, что вы хотите.
Вместо добавления Set-Location
к вашему скрипту вы должны установить System.Environment.CurrentDirectory
в любое время перед, открывая Runspace. Он наследует все, что было в CurrentDirectory при его открытии:
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
System.Environment.CurrentDirectory = "C:\\scripts";
runspace.Open();
using (Pipeline pipeline = runspace.CreatePipeline())
{
pipeline.Commands.Add(@".\foo.ps1");
pipeline.Invoke();
}
runspace.Close();
}
И помните, Set-Location
не устанавливает .net framework CurrentDirectory
, поэтому, если вы вызываете .Net-методы, которые работают с "текущим" местоположением, вам нужно установить его самостоятельно.
Ответ 3
Что-то не так:
pipeline.Commands.AddScript(@"set-location c:\scripts;.\foo.ps1")
?
-Oisin
Ответ 4
Вы можете установить рабочий каталог в powershell с помощью следующей команды
set-location c:\mydirectory
Вы также можете попробовать запустить PowerShell script ($ profile).
C:....\MyDocs\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
Но только если этот каталог исправлен и не меняет
Ответ 5
Вместо того, чтобы позволить приложению обрабатывать его, вы можете включить это в начало вашего скрипта,
Set-Location $PSScriptRoot
Он выполнит оставшуюся часть сценария в своем каталоге установки.
Но будьте осторожны, "текущее местоположение" PowerShell НЕ совпадает с рабочим каталогом вашего приложения, оно просто инициализируется при запуске powershell.
Set-Location может подшутить над вами, если вы запустите исполняемые файлы, которые зависят от текущего каталога, или если ваш скрипт содержит вызовы API-интерфейсов, как в этом примере:
PS C:\Users\luc> Set-Location C:\
PS C:\> [System.IO.Directory]::GetCurrentDirectory()
C:\Users\luc
При этом я бы предпочел ответ майка Бэйли. Я просто хотел дать решение, которое имеет свои достоинства, если сценарий не всегда установлен в одном и том же каталоге (как обычно, на компьютере разработчика отличается от пути к продукту).