Объект PowerShell возвращает значение null

У меня есть команда ниже, и она возвращает мне нулевой объект. Когда я запускаю команду отдельно в окне PowerShell, я получаю правильный результат. Ниже приведен мой метод PowerShell, который вызывает команду, а также команду PowerShell, которую я определил. Я в основном хочу вернуть строковое значение. Пожалуйста, дайте мне знать, что я делаю не так?

C # метод:

     public string RunScript( string contentScript, Dictionary<string, EntityProperty> parameters)
            {
                List<string> parameterList = new List<string>();
                foreach( var item in parameters )
                {
                    parameterList.Add( item.Value.ToString() );
                }
               
                using( PowerShell ps = PowerShell.Create() )
                {
                    ps.AddScript( contentScript );
// in ContentScript I get "Get-RowAndPartitionKey" on debugging
                    ps.AddParameters( parameterList );//I get list of strings
                   
                    IAsyncResult async = ps.BeginInvoke();
                    StringBuilder stringBuilder = new StringBuilder();
                    foreach( PSObject result in ps.EndInvoke( async ) )
// here i get result empty in ps.EndInvoke(async)
                    {
                        stringBuilder.AppendLine( result.ToString() );
                    }
                    return stringBuilder.ToString();
                }
            }
        }

Мое определение командлета Powershell GetRowAndPartitionKey, которое пытается вызвать приведенный выше код:

public abstract class GetRowAndPartitionKey : PSCmdlet
    {
        [Parameter]
        public List<string> Properties { get; set; } = new List<string>();
    }

    [Cmdlet( VerbsCommon.Get, "RowAndPartitionKey" )]
    public class GetRowAndPartitionKeyCmd : GetRowAndPartitionKey

    {
        protected override void ProcessRecord()
        {
            string rowKey = string.Join( "_", Properties );
            string pKey = string.Empty;
            
            WriteObject( new
            {
                RowKey = rowKey,
                PartitionKey = pKey
            } );
        }
    }
}

person ZZZSharePoint    schedule 19.02.2021    source источник
comment
Что такое EntityProperty и _2 _ = _ 3_ после Invoke()?   -  person Mathias R. Jessen    schedule 19.02.2021
comment
EntityProperty - это Microsoft.Azure.Cosmos.Table.EntityProperty. Я не проверял ps.HadErrors.   -  person ZZZSharePoint    schedule 19.02.2021
comment
только что проверил его false после BeginInvoke ()   -  person ZZZSharePoint    schedule 19.02.2021


Ответы (1)


При использовании PowerShell SDK если вы хотите передать параметры отдельной команде с .AddParameter() / .AddParameters() / AddArgument(), используйте _ 4_, а не .AddScript()

.AddScript() предназначен для передачи произвольных фрагментов. кода PowerShell, который выполняется как блок сценария, которому передаются параметры, добавленные с помощью .AddParameters().

То есть ваш вызов эквивалентен & { Get-RowAndPartitionKey } <your-parameters>, и, как вы можете видеть, ваша команда Get-RowAndPartitionKey поэтому не получает значения параметров.

См. этот ответ или дополнительную информацию.


Примечание. В качестве предварительного условия для вызова пользовательского командлета Get-RowAndPartitionKey вам, возможно, придется явно импортировать модуль (DLL), который его содержит, что вы можете сделать:

  • либо: с отдельным синхронным Import-Module вызовом, выполняемым заранее (для простоты, я использую здесь .AddArgument(), с передачей аргумента позиционно, который привязывается к параметру -Name (который также принимает пути)):

    ps.AddCommand("Import-Module").AddArgument(@"<your-module-path-here>").Invoke();
    
  • или: как часть одного (в данном случае асинхронного) вызова - обратите внимание на обязательный вызов .AddStatement() для разделения двух команд:

    IAsyncResult async = 
      ps.AddCommand("Import-Module").AddArgument(@"<your-module-path-here>")
        .AddStatement()
          .AddCommand("GetRowAndPartitionKey").AddParameter("Properties", parameterList)
              .BeginInvoke();
    

"<your-module-path-here>" относится к полному пути в файловой системе модуля, содержащего командлет Get-RowAndPartitionKey; в зависимости от того, как этот модуль реализован, это либо путь к каталогу модуля, его .psd1 манифесту модуля, либо к его .dll, если это автономная сборка.

Альтернативный метод импорта с использованием выделенного пакета SDK PowerShell _ 21_ метод:

Этот метод устраняет необходимость в сеансе Import-Module вызова, но требует дополнительной настройки:

  • Создайте состояние сеанса по умолчанию.
  • Вызовите .ImportPSModule(), чтобы импортировать модуль.
  • Передать это состояние сеанса PowerShell.Create()
var iss = InitialSessionState.CreateDefault();
iss.ImportPSModule(new string[] { @"<your-module-path-here>" });
var ps = PowerShell.Create(iss);

// Now the PowerShell commands submitted to the `ps` instance
// will see the module's exported commands.

Предостережение: экземпляр PowerShell отражает начальное состояние сеанса в .Runspace.InitialSessionState, но как свойство концептуально только для чтения; сложность заключается в том, что он технически по-прежнему модифицируется, поэтому ошибочные попытки изменить его незаметно игнорируются, а не приводят к исключениям.


Чтобы устранить эти вызовы:

  • Проверьте ps.HadErrors после .Invoke() / .EndInvoke(), чтобы узнать, сообщают ли команды PowerShell о каких-либо (непрекращающихся) ошибках.

  • Перечислите ps.Streams.Errors, чтобы проверить конкретные возникшие ошибки.

См. этот ответ на следующий вопрос для автономного примера кода, демонстрирующего эти методы.

person mklement0    schedule 19.02.2021