#c# #powershell
Вопрос:
Я создал сценарий powershell, который состоит из:
param($ServerName, $Location)
"Application Name: $ServerName"
"Location: $Location"
когда я нахожусь в powershell и запускаю .Params.ps1 ConsoleApp1 Washington, D.C.
его, он отобразится:
Application Name: ConsoleApp1
Location: Washington D.C.
Так что я знаю, что это работает просто отлично. Теперь я хочу перенести это в c# и выполнить передачу параметров.
В своем консольном приложении я создал следующее:
static void Main(string[] args)
{
string[] scriptParam = { "ConsoleApp1", "Washington, D.C."};
string powerShell = PerformScript(scriptParam);
Console.WriteLine(powerShell);
Console.WriteLine("nPowershell script excuted!!");
Console.ReadLine();
}
static string PerformScript(string scriptParameters)
{
InitialSessionState runspaceConfiguration = InitialSessionState.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddCommand(@"C:UsersuserssourcereposConsoleApp1powershellParams.ps1");
foreach (string scriptParameter in scriptParameters)
{
ps.AddParameter(scriptParameter);
}
Collection<PSObject> psObjects = pipeline.Invoke();
runspace.Close();
StringBuilder stringBuilder = new();
foreach (PSObject item in psObjects)
{
stringBuilder.AppendLine(item.ToString());
}
return stringBuilder.ToString();
}
но когда я запускаю программу, я получаю сообщение Exception Unhandled
на линии
Collection<PSObject> psObjects = pipeline.Invoke();
Система.Управление.Автоматизация.Исключение PSInvalidOperationException: «Конвейер не содержит команды».
Я делаю что-то неправильно при передаче параметров?
Обновленный код:
static string PerformScript(string[] scriptParameters)
{
InitialSessionState runspaceConfiguration = InitialSessionState.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
using (var ps = PowerShell.Create())
{
var result = ps.AddCommand(@"C:UsersuserssourcereposConsoleApp1powershellParams.ps1")
.AddArgument("ConsoleApp1")
.AddArgument("Washington, D.C.")
.Invoke();
foreach (var o in result)
{
Console.WriteLine(o);
}
}
Collection<PSObject> psObjects = pipeline.Invoke();
runspace.Close();
StringBuilder stringBuilder = new();
foreach (PSObject item in psObjects)
{
stringBuilder.AppendLine(item.ToString());
}
return stringBuilder.ToString();
}
Комментарии:
1. Я не очень много пишу на C#, за исключением случаев, когда мне нужно вызвать P/, поэтому я не уверен, что это точно, но может показаться, что вы пытаетесь перебирать строку, а не массив строк: string[]. Посмотрите, как Performscript() объявляет свой параметр (параметры сценария), а также то, что вы передаете ему…. обе строки.
2. Спасибо! Это исправило эту проблему. Однако, когда я запустил программу, она вернула новую ошибку. Система.Управление. Автоматизация. Исключение PSInvalidOperationException: «Конвейер не содержит команды». @thepip3r
Ответ №1:
Воспользуйся .AddArgument()
, не .AddParameter()
.
То, что вы пытаетесь передать, — это позиционные (безымянные) аргументы, т. Е. простые значения параметров, целевой параметр которых подразумевается их положением, для чего .AddArgument()
и предназначен.
Напротив, .AddParameter()
используется для именованных аргументов, где сначала указывается имя параметра, а затем его значение (аргумент).
Вот упрощенный пример:
using (var ps = PowerShell.Create()) {
var result = ps.AddCommand(@"C:UsersuserssourcereposConsoleApp1powershellParams.ps1")
.AddArgument("ConsoleApp1")
.AddArgument("Washington, D.C.")
.Invoke();
foreach (var o in result) {
Console.WriteLine(o);
}
}
Примечание: Выше используется значительно упрощенный API, доступный непосредственно с помощью методов PowerShell
экземпляра (созданного с .Create()
): Если достаточно автоматического создания пространства выполнения с состоянием сеанса по умолчанию , нет необходимости в явном создании пространства выполнения с RunspaceFactory.CreateRunspace()
, состояния сеанса с InitialSessionState.Create()
и конвейера пространства выполнения с .CreatePipeline()
— см. Нижний раздел для применения методов к вашему коду.
Что касается того, что вы пытались:
Если вы ошибочно используете .AddParameter()
только один аргумент метода, пакет SDK PowerShell использует значение по умолчанию true
для пропущенного параметра , что .AddParameter('foo')
эквивалентно передаче -foo: $true
из PowerShell.
Это работает должным образом , только если вы передаете имя параметра, который является параметром переключателя (типа System.Management.Automation.SwitchParameter
, [switch]
в коде PowerShell).
Применяется к вашему коду:
static void Main(string[] args)
{
Console.WriteLine(
PerformScript(
@"C:UsersuserssourcereposConsoleApp1powershellParams.ps1",
new string[] { "ConsoleApp1", "Washington, D.C." }
)
);
}
static string PerformScript(string scriptPath, string[] scriptArguments)
{
StringBuilder stringBuilder = new();
using (var ps = PowerShell.Create())
{
ps.AddCommand(scriptPath);
foreach (var arg in scriptArguments)
{
ps.AddArgument(arg);
}
foreach (var o in ps.Invoke())
{
stringBuilder.AppendLine(o.ToString());
}
}
return stringBuilder.ToString();
}
Комментарии:
1. Спасибо за подробное объяснение! Теперь я это понимаю. Это сработало, как и ожидалось, еще раз спасибо! 🙂
2. Я рад это слышать, @MarkCo; мое удовольствие.