如何向 PowerShell PSDrive“function:”上的函数对象添加属性?

riv*_*ivy 3 powershell properties

我尝试使用 $function:foo 值和 get-item function:foo。所有尝试都成功修改了临时函数对象,但在重新分配给存储函数时(通过 $function:foo = ... 或 set-item function:foo ...),附加属性丢失。

以下是我尝试的结果(全部失败):

设置

$=>函数 foo { "foo" }
$=>$f = $函数:foo
$=>$f = $f | 添加成员注释属性栏 BARvalue -pass
$=>$f | 通用汽车*

   类型名称:System.Management.Automation.ScriptBlock

名称 成员类型 定义
---- ---------- ----------
bar NoteProperty System.String bar=BARvalue

#1

$=>设置项函数:f $f -force
$=>$函数:foo | 通用汽车*
>

#2

$=>$函数:f = $f
$=>$函数:foo | 通用汽车*
>

#3

$=>$f = 获取项目函数:foo
$=>$f | 通用汽车

   类型名称:System.Management.Automation.FunctionInfo

名称 成员类型 定义
---- ---------- ----------
等于方法 System.Boolean Equals(Object obj)
GetHashCode 方法 System.Int32 GetHashCode()
GetType 方法 System.Type GetType()
ToString 方法 System.String ToString()
PSDrive NoteProperty System.Management.Automation.PSDriveInfo PSDrive=函数
PSIContainer NoteProperty System.Boolean PSIContainer=False
PSPath NoteProperty System.String PSPath=Microsoft.PowerShell.Core\Function::foo
PSProvider NoteProperty System.Management.Automation.ProviderInfo PSProvider=Microsoft....
CmdletBinding 属性 System.Boolean CmdletBinding {get;}
CommandType 属性 System.Management.Automation.CommandTypes CommandType {get;}
DefaultParameterSet 属性 System.String DefaultParameterSet {get;}
定义属性 System.String 定义 {get;}
描述 属性 System.String 描述 {get;set;}
模块属性 System.Management.Automation.PSModuleInfo 模块 {get;}
ModuleName 属性 System.String ModuleName {get;}
名称属性 System.String 名称 {get;}
选项属性 System.Management.Automation.ScopedItemOptions 选项 {get;set;}
参数属性 System.Collections.Generic.Dictionary`2[[System.String, mscorli...
ParameterSets 属性 System.Collections.ObjectModel.ReadOnlyCollection`1[[System.Man...
ScriptBlock 属性 System.Management.Automation.ScriptBlock ScriptBlock {get;}
可见性属性 System.Management.Automation.SessionStateEntryVisibility 可见性...

$=>$f = $f | 添加成员注释属性栏 barValue -pass
$=>$f | 通用汽车*

   类型名称:System.Management.Automation.FunctionInfo

名称 成员类型 定义
---- ---------- ----------
bar NoteProperty System.String bar=barValue

$=>设置项函数:foo $f
$=>$函数:foo | 通用汽车*
>

不确定我做错了什么。重新分配时,这些属性似乎被删除了。那是对的吗?定义的行为?我还没有看到任何文档说 FunctionInfo 对象或 ScriptBlocks 被异常对待。这是语言中某些深奥的角落吗?

Ste*_*ski 5

我的第一个想法是,当您将此属性附加到对象时,您是将其附加到该对象的特定实例。当您的变量丢失对该对象的引用时,该新属性的任何知识都会丢失。

我的猜测是,下次您获取该项目时,您将使用 foo 的属性(存储在函数提供程序中)创建一个新的 FunctionInfo 对象。

当您调用 Get-Item 或 Get-ChildItem 时,它会返回对表示基础项的 .NET 类型的对象引用。这些项目不会无限期地存在于内存中(想象一下每个本地驱动器上的每个文件以及内存中的每个映射驱动器都有一个 FileInfo 对象......哎哟)。由于每次调用 Get-Item 时 PowerShell 都会创建一个新实例,因此您将获得基本的 FunctionInfo 对象。

如果要向特定类型的所有项目添加属性,可以使用 PowerShell 的可扩展类型系统。您可以创建自定义 .ps1xml 文件并将其加载到 PowerShell 会话中,该会话可以向类型的每个实例添加属性。PowerShell 团队博客上的一些很棒的示例位于此处 -> Hate Add-MemberLeveraging the PowerShell Type Extensions to Get Documentation

编辑(解决评论):我理解您想要做什么,但失败是由于新属性被“嫁接”到允许即时添加属性的 PSObject 包装器上。新属性从来都不是您从 PSDrive 检索的 FunctionInfo 对象的真正一部分。

此外,函数提供者(函数:psdrive)没有存储该附加属性的机制。它知道并使用 FunctionInfo 对象。当您从 Function: PSDrive 请求某个项目时,Function 提供程序将返回 FunctionInfo 对象。当您将函数保存到 Function: PSDrive 时,提供程序只能存储它知道如何处理的属性值。人们可以编写一个自定义提供程序来处理来自 PSObject 包装器的新属性,但这不是该提供程序中默认功能的一部分。

编辑#2:好吧,这一直困扰着我。 我在博客中介绍了一种解决方法