te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>c# - How can I output a PSCustomObject from a compiled Cmdlet? - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - How can I output a PSCustomObject from a compiled Cmdlet? - Stack Overflow

programmeradmin2浏览0评论

I have a compiled Cmdlet that works with Hashtables. I would like to write a [pscustomobject] of the hashtable to the pipeline. In a PowerShell script block that would be accomplished using the following cast:

[pscustomobject]$hashtable

I would like to accomplish the same from a compiled Cmdlet. The natural implementation would be

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() {
        WriteObject(new PSCustomObject(Hashtable));
    }
}

however, PSCustomObject has no public constructor.

I thought new PSObject() might be equivalent, but WriteObject(new PSObject(Hashtable)) differs enough from [pscustomobject]$hashtable that they aren't even shown the same in the console:

PS\> Out-PsCustomObject -Hashtable @{ a='aye' }
Name                           Value
----                           -----
a                              aye

PS\> [pscustomobject]@{ a = 'aye' }
a
-
aye

How can I output a PSCustomObject from a compiled Cmdlet?

I have a compiled Cmdlet that works with Hashtables. I would like to write a [pscustomobject] of the hashtable to the pipeline. In a PowerShell script block that would be accomplished using the following cast:

[pscustomobject]$hashtable

I would like to accomplish the same from a compiled Cmdlet. The natural implementation would be

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() {
        WriteObject(new PSCustomObject(Hashtable));
    }
}

however, PSCustomObject has no public constructor.

I thought new PSObject() might be equivalent, but WriteObject(new PSObject(Hashtable)) differs enough from [pscustomobject]$hashtable that they aren't even shown the same in the console:

PS\> Out-PsCustomObject -Hashtable @{ a='aye' }
Name                           Value
----                           -----
a                              aye

PS\> [pscustomobject]@{ a = 'aye' }
a
-
aye

How can I output a PSCustomObject from a compiled Cmdlet?

Share Improve this question asked Feb 17 at 23:22 alx9ralx9r 4,2516 gold badges32 silver badges56 bronze badges 1
  • 1 Just added additional info using a new method to the answer – Santiago Squarzon Commented 2 days ago
Add a comment  | 

1 Answer 1

Reset to default 3

You're kinda close, first you need to create a PSObject and then, for each DictionaryEntry on the hash table, you need to add a new PSNoteProperty to said object and lastly output it.

NOTE: The following does not ensure ordering on the PSCustomObject properties, what [pscustomobject]@{ .... } achieves preserving the order of the hash table key / value pairs is all done via AST parsing at runtime. Cannot be achieved via already created hash table.

If you needed to preserve the order then you could change the parameter to:

public IDictionary IDictionary { get; set; }

And pass-in an OrderedDictionary, like so:

Out-PsCustomObject ([ordered]@{ foo = 'bar'; baz = 'hello' })

Also worth noting, what the [ordered] accelerator does has the same AST parsing used in [pscustomobject] to preserve ordering via hash table literal (@{ ... }) instantiation.

using System.Collections;
using System.Management.Automation;

[Cmdlet(VerbsData.Out, "PsCustomObject")]
public class OutPsCustomObjectCommand : PSCmdlet
{
    [Parameter(Mandatory = true, Position = 0)]
    public Hashtable Hashtable { get; set; }

    protected override void ProcessRecord()
    {
        PSObject output = new();
        foreach (DictionaryEntry kv in Hashtable)
        {
            output.Properties.Add(new PSNoteProperty(
                LanguagePrimitives.ConvertTo<string>(kv.Key), kv.Value));
        }

        WriteObject(output);
    }
}

EDIT

After further inspecting the PowerShell source (see Mshexpression.cs#L353-L371), there is a perhaps shorter way to create a pscustomobject from a hash table or any other IDictionary type using LanguagePrimitives.ConvertPSObjectToType, however, the notes mentioned before still remain, this does not ensure property ordering.

using System.Collections;
using System.Management.Automation;

[Cmdlet(VerbsData.Out, "PsCustomObject")]
public class OutPsCustomObjectCommand : PSCmdlet
{
    [Parameter(Mandatory = true, Position = 0)]
    public IDictionary IDictionary { get; set; }

    protected override void ProcessRecord() =>
        WriteObject(LanguagePrimitives.ConvertPSObjectToType(
            valueToConvert: PSObject.AsPSObject(IDictionary),
            resultType: typeof(PSObject),
            recursion: false,
            formatProvider: null,
            ignoreUnknownMembers: true));
}
发布评论

评论列表(0)

  1. 暂无评论