【发布时间】:2021-03-22 02:23:55
【问题描述】:
我正在尝试用 C# 编写一个简单的 PowerShell cmdlet,它接受一个 ArrayList 实例并向其中添加一个项目。我遇到的问题是数组列表的副本被传递给 cmdlet,而不是我期望的实际对象。有没有办法通过引用传递参数?以下代码仅输出 ArrayList $B 的“Count is 0”。
注意:要在 PowerShell 7.1 中运行程序,您需要以 .NET 5 为目标并安装 Microsoft.PowerShell.SDK 和 System.Management.Automation Nuget 包。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
namespace CustomPowerShellCmdlet
{
class Program
{
static void Main(string[] args)
{
string powerShellScript = @"
$B = New-Object System.Collections.ArrayList
Add-CollectionItem -Collection $B -Item '1'
Add-CollectionItem -Collection $B -Item '2'
Write-Output ('Count is ' + $B.Count)
";
var output = RunPowerShellScript(powerShellScript);
foreach (PSObject psObject in output)
{
Console.WriteLine(psObject.BaseObject.ToString());
}
}
private static Collection<PSObject> RunPowerShellScript(string powerShellScript)
{
InitialSessionState initialSessionState = InitialSessionState.CreateDefault();
initialSessionState.Commands.Add(new SessionStateCmdletEntry("Add-CollectionItem", typeof(AddCollectionItemCmdlet), null));
using (var runspace = RunspaceFactory.CreateRunspace(initialSessionState))
{
runspace.Open();
using (var ps = PowerShell.Create())
{
ps.Streams.Error.DataAdding += Output_DataAdding;
ps.Streams.Debug.DataAdding += Output_DataAdding;
ps.Runspace = runspace;
ps.AddScript(powerShellScript);
return ps.Invoke();
}
}
}
private static void Output_DataAdding(object sender, DataAddingEventArgs e)
{
Console.WriteLine(e.ItemAdded.ToString());
}
[Cmdlet(VerbsCommon.Add, "CollectionItem")]
public class AddCollectionItemCmdlet : Cmdlet
{
[Parameter(Mandatory = true)]
[AllowEmptyCollection]
public ArrayList Collection { get; set; }
[Parameter(Mandatory = true)]
public object Item { get; set; }
/// <summary>
/// This static field is needed for demo purposes only.
/// </summary>
public static List<object> AddedItems = new List<object>();
protected override void BeginProcessing()
{
Console.WriteLine("A new collection is passed to the cmdlet: {0}", !AddedItems.Any(x => ReferenceEquals(x, Collection)));
AddedItems.Add(Collection);
Collection.Add(Item);
}
}
}
}
UPD1. 看来此行为是由 New-Object cmdlet 引起的。如果我用 [System.Collections.ArrayList] @() 替换它,那么我得到了我需要的东西。我仍然不明白为什么它会这样工作。
【问题讨论】:
-
什么版本的 PowerShell?我无法在 PowerShell 5.1、7.0.3 和 7.1.0 中重现此行为。也许您正在使用加载了先前版本的模块的会话中进行测试?
-
@MathiasR.Jessen 我可以在 5.1 和 7.1 中重现它。我更新了问题中的代码以阐明如何使用 cmdlet。它在运行空间中注册为命令,我没有在模块中使用它。
标签: c# powershell cmdlets