Передача параметров из c# в скрипт powershell

#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; мое удовольствие.