PowerShell 对象 returns 空

PowerShell Object returns null

我有以下命令,它return是我的空对象。当我 运行 在 PowerShell window 中单独执行命令时,我得到了正确的结果。下面是我调用命令的 PowerShell 方法以及我定义的 PowerShell 命令。我基本上是在寻找 return 一个字符串值。请让我知道我做错了什么?

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 cmdlet 定义,上面的代码试图调用它:

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
            } );
        }
    }
}

使用 PowerShell SDK 时,如果您想将参数传递给 单个命令.AddParameter() / .AddParameters() / AddArgument(), 使用 .AddCommand(), 而不是 .AddScript()

.AddScript() 用于传递作为 脚本块 执行的任意 PowerShell 代码 ,其中添加了参数.AddParameters() 通过。

也就是说,您的调用等同于 & { Get-RowAndPartitionKey } <your-parameters>,如您所见,您的 Get-RowAndPartitionKey 命令因此不会接收参数值。

参见 this answer 或更多信息。


注意:作为调用自定义 Get-RowAndPartitionKey cmdlet 的 先决条件,您可能必须显式 导入包含它的模块 (DLL) ,你可以这样做:

  • 或者:在之前执行一个单独的同步Import-Module调用(为简单起见,我在这里使用.AddArgument(), with 传递参数 positionally,它绑定到 -Name 参数(它也接受 paths):

    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 cmdlet 的模块的完整文件系统路径;根据该模块的实现方式,它要么是模块 目录 .psd1 模块清单的路径,要么是 .dll 的路径,如果它是独立程序集。

替代导入方法,使用 PowerShell SDK 的专用 .ImportPSModule() 方法:

此方法无需会话中 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 中的初始会话状态,但在概念上 只读 属性;棘手的部分是它技术上仍然可以修改,因此错误的修改它的尝试会被悄悄忽略而不是导致异常。


排除 这些调用的故障:

  • .Invoke() / .EndInvoke() 之后检查 ps.HadErrors 以查看 PowerShell 命令是否报告任何(非终止)错误。

  • 枚举 ps.Streams.Errors 以检查发生的具体错误。

请参阅 this answer 后续问题,了解演示这些技术的独立示例代码。