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

时间:2009-02-13 05:10:37

标签: powershell properties

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

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

设置

$=>function foo { "foo" }
$=>$f = $function:foo
$=>$f = $f | add-member noteproperty bar BARvalue -pass
$=>$f | gm b*

   TypeName: System.Management.Automation.ScriptBlock

Name                 MemberType   Definition
----                 ----------   ----------
bar                  NoteProperty System.String bar=BARvalue

#1

$=>set-item function:f  $f -force
$=>$function:foo | gm b*
>

#2

$=>$function:f = $f
$=>$function:foo | gm b*
>

#3

$=>$f = get-item function:foo
$=>$f | gm

   TypeName: System.Management.Automation.FunctionInfo

Name                MemberType   Definition
----                ----------   ----------
Equals              Method       System.Boolean Equals(Object obj)
GetHashCode         Method       System.Int32 GetHashCode()
GetType             Method       System.Type GetType()
ToString            Method       System.String ToString()
PSDrive             NoteProperty System.Management.Automation.PSDriveInfo PSDrive=Function
PSIsContainer       NoteProperty System.Boolean PSIsContainer=False
PSPath              NoteProperty System.String PSPath=Microsoft.PowerShell.Core\Function::foo
PSProvider          NoteProperty System.Management.Automation.ProviderInfo PSProvider=Microsoft....
CmdletBinding       Property     System.Boolean CmdletBinding {get;}
CommandType         Property     System.Management.Automation.CommandTypes CommandType {get;}
DefaultParameterSet Property     System.String DefaultParameterSet {get;}
Definition          Property     System.String Definition {get;}
Description         Property     System.String Description {get;set;}
Module              Property     System.Management.Automation.PSModuleInfo Module {get;}
ModuleName          Property     System.String ModuleName {get;}
Name                Property     System.String Name {get;}
Options             Property     System.Management.Automation.ScopedItemOptions Options {get;set;}
Parameters          Property     System.Collections.Generic.Dictionary`2[[System.String, mscorli...
ParameterSets       Property     System.Collections.ObjectModel.ReadOnlyCollection`1[[System.Man...
ScriptBlock         Property     System.Management.Automation.ScriptBlock ScriptBlock {get;}
Visibility          Property     System.Management.Automation.SessionStateEntryVisibility Visibi...

$=>$f = $f | add-member noteproperty bar barValue -pass
$=>$f | gm b*

   TypeName: System.Management.Automation.FunctionInfo

Name                MemberType   Definition
----                ----------   ----------
bar                 NoteProperty System.String bar=barValue

$=>set-item function:foo $f
$=>$function:foo | gm b*
>

不确定我做错了什么。看来这些属性在重新分配时被剥离了。那是对的吗?定义的行为?我没有看到任何文档说FunctionInfo对象或ScriptBlocks被异常处理。这是语言的一些深奥的角落吗?

1 个答案:

答案 0 :(得分:4)

我首先想到的是,当您将此属性附加到对象时,您将它附加到该对象的特定实例。当您的变量丢失对该对象的引用时,对该新属性的任何知识都将丢失。

我的猜测是下次你得到那个项目时,你正在用foo的属性创建一个新的FunctionInfo对象(存储在函数提供者中)。

当您调用Get-Item或Get-ChildItem时,它会返回对表示基础项的.NET类型的对象引用。这些项目无限期地存在于内存中(想象一下每个本地驱动器上的每个文件的FileInfo对象以及存储在内存中的每个映射驱动器。ouch)。由于PowerShell每次调用Get-Item时都会创建一个新实例,因此您将获得基本的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:好的,这一直困扰着我。 I blogged about a workaround