如何从已编译的Cmdlet中输出PSCustomObject?
我太懂你的困扰了——在PowerShell脚本里用[pscustomobject]$hashtable能轻松把哈希表转成自定义对象输出,但到了编译的Cmdlet里直接用PSCustomObject构造函数却行不通,而且用new PSObject(Hashtable)输出的格式和预期完全不一样。
其实问题出在:PowerShell里的[pscustomobject]$hashtable本质是把哈希表的键值对映射成对象的属性,而new PSObject(Hashtable)只是把整个哈希表包装成了PSObject,所以控制台显示的是哈希表的键值列表,不是我们想要的自定义对象样式。
这里有两种靠谱的解决方法,都能让你输出和脚本里一样的PSCustomObject风格对象:
方法一:使用PSObject.AsPSObject(推荐)
这是PowerShell SDK提供的内置方法,专门用来把哈希表这类键值结构转成属性化的PSObject,用法非常简洁:
using System.Collections; using System.Management.Automation; [Cmdlet(VerbsData.Out, "PsCustomObject")] public class OutPsCustomObjectCommand : PSCmdlet { [Parameter(Mandatory = true)] public Hashtable Hashtable { get; set; } protected override void ProcessRecord() { // 调用AsPSObject将哈希表转换为属性化的自定义对象 var customObject = PSObject.AsPSObject(Hashtable); WriteObject(customObject); } }
编译后运行,输出就和你在脚本里用[pscustomobject]$hashtable的结果完全一致了:
PS> Out-PsCustomObject -Hashtable @{ a='aye' } a - aye
方法二:手动添加属性(更灵活)
如果你需要更精细地控制属性的添加过程,可以手动创建PSObject,然后逐个添加PSNoteProperty:
protected override void ProcessRecord() { var psObj = new PSObject(); foreach (DictionaryEntry entry in Hashtable) { // 把哈希表的每个键值对转为对象的NoteProperty psObj.Properties.Add(new PSNoteProperty(entry.Key.ToString(), entry.Value)); } WriteObject(psObj); }
这种方式的效果和方法一完全相同,适合需要对属性做额外处理(比如类型转换、过滤)的场景。
为什么之前的方法不行?
再补充解释一下:new PSObject(Hashtable)的构造逻辑是包装传入的对象,它把整个Hashtable当作PSObject的底层实例,所以输出时PowerShell会按照Hashtable的默认格式显示键值对;而我们需要的是把Hashtable的键值对映射为对象的属性,这正是AsPSObject和手动添加NoteProperty实现的逻辑。
备注:内容来源于stack exchange,提问作者alx9r

