65

According to get-help about_Functions_CmdletBindingAttribute

The CmdletBinding attribute is an attribute of functions that makes them operate like compiled cmdlets

We can use it on the top of our scripts. What is the function in this case? An internal implicit "main" function called by the PowerShell engine for all its inputs?

Regarding this syntax:

[CmdletBinding(ConfirmImpact=<String>,
                     DefaultParameterSetName=<String>,
                     HelpURI=<URI>,
                     SupportsPaging=<Boolean>,
                     SupportsShouldProcess=<Boolean>,
                     PositionalBinding=<Boolean>)]

What are we doing? Instantiating a cmdlbinding object and passing an argument list to its constructor? This syntax can be found in param() - for example: [Parameter(ValueFromPipeline=$true)]. Does this syntax have a particular name, and can it be found elsewhere?

Lastly, are we able, as simple PowerShellers, to mimic this functionality and modify the behavior of scripts by setting an attribute?

phuclv
  • 37,963
  • 15
  • 156
  • 475
Loïc MICHEL
  • 24,935
  • 9
  • 74
  • 103
  • 6
    I guess docs are bit misleading here: all this is related to any type of script block: as Shay mentioned - named by function name, by path (script) but *also* unnamed, e.g. `& { [CmdletBinding()]param() Write-Verbose 'Foo'} -Verbose` works like a champ. – BartekB Feb 03 '13 at 10:02

3 Answers3

23

Generally speaking, CmdletBinding is what makes a function into an Advanced function. Putting it at the top of a script makes the script an "advanced" script. Functions and scripts are much the same, where the script file name is equivalent to the function name and the script content is equivalent to the scriptblock section of a function.

CmdletBinding attributes give you control over function capabilities, such as adding Confirm and WhatIf support (via SupportsShouldProcess), Disable parameters positional binding, and so on.

MarredCheese
  • 17,541
  • 8
  • 92
  • 91
Shay Levy
  • 121,444
  • 32
  • 184
  • 206
  • 1
    "_where the script file name is equivalent to the function name and the script content is equivalent to the scriptblock section of a function_" What does that mean in context? If I have, say, inherited a single file full of `Function`s with `[CmdletBinding()]` before every `param` section, how does that relate to the script file name? Does it? – ruffin Nov 18 '21 at 16:43
  • @ruffin "*Does it relate to the script file name?*" No. Shay's comparison is merely an analogy, as both examples result in the same functionality. The names of the functions defined in your file and the fact that said functions contain `[CmdletBinding( )]` have no relation to the file name of the script in which they are contained. – Bren0man Jan 23 '22 at 03:16
21

CmdletBinding, Parameter etc. are special attribute classes that scripters can use to define PowerShell's behavior, e.g. make a function an Advanced function with Cmdlet capabilites.

When you call them via e.g. [CmdletBinding()] you initialize a new instance of the class.

Read more about the CmdletBindingAttribute class at: MSDN

Read more about the ParameterAttribute class at: MSDN

More about Attribute classes here and here

phuclv
  • 37,963
  • 15
  • 156
  • 475
Frode F.
  • 52,376
  • 9
  • 98
  • 114
  • 1
    OK. So when using the complete syntax we pass an hashtable to the constructor that will be used use to set the public members values ? – Loïc MICHEL Feb 03 '13 at 13:23
  • 1
    in a way. hashtables are separated by `;` . I think this is a special type of class and way of constructing that the PowerShell process can use. You could think of it as e.g. `new Question { Text = "Some question" };` in c# I guess. If you want to know how it Works, you can try to decompile the Library specified in my MSDN link and see if it's readable. – Frode F. Feb 03 '13 at 13:32
  • yeah sort of hashtable :). – Loïc MICHEL Feb 03 '13 at 13:34
  • added some links about attribute classes that explains how to create and use it. special classes that inherits from `System.Attribute` or something. I'm just Learning scripting as a hobby, so I'm far from an expert at this :) – Frode F. Feb 03 '13 at 13:50
  • 1
    `@{}`is of type [`System.Collections.Hashtable`](http://msdn.microsoft.com/en-us/library/system.collections.hashtable.aspx), which implements `System.Collections.IDictionary`. `Hashtable` has been in .NET since 1.1. Equivalent in C#: `new Hashtable { { "key1", "value1" }, { "key2", "value2" }, }` – Zenexer Jul 19 '13 at 11:10
4

Regarding the syntax question, the format closely matches how you apply a .NET attribute class to a member using named parameters in C#.

Compare the (simplified) grammar for attributes from section B.2.4 of The PowerShell Language Specification with that from section C.2.13 of the C# Language Specification:

B.2.4 Attributes   (PowerShell)

attribute:
  [ attribute-name ( attribute-arguments ) ]

attribute-arguments:
  attribute-argument
  attribute-argument
, attribute-arguments

attribute-argument:
  simple-name
= expression


C.2.13 Attributes   (C#)

attribute:
  [ attribute-name ( named-argument-list ) ]

named-argument-list:
  named-argument
  named-argument-list
, named-argument

named-argument:
  identifier
= attribute-argument-expression



I agree it might have been nice from a sense of conceptual brevity to e.g. re-use hashtable initialization syntax for attribute initialization. However, I can imagine supporting all the options from hashtables (like [A(P=v)] and [A('P'=v)] and $n = 'P'; [A($n=v)] and such, or some particular subset of them) just to use ; as the separator character would have been more trouble than it was worth.

On the other hand, if you want to use advanced functions, then maybe it makes sense to learn an advanced syntax :)

Emperor XLII
  • 13,014
  • 11
  • 65
  • 75
  • Attributes don't support hashtable syntax because they aren't dealing with normal keys and values. The keys correspond to well-defined properties in classes that extend `System.Attribute`. – Zenexer Jul 19 '13 at 11:14
  • @Zenexer: That is an argument in support of the C#-like syntax, but that does not place a constraint on the language. Similarly, I can define a hashtable `$h = @{ foo = 2 }` and access the element with `$h.foo` property syntax, even though the hashtable does not actually have a "foo" property. In one case, the language designers chose a flexible syntax, and in the other they chose to support a simpler syntax. – Emperor XLII Jul 19 '13 at 13:42
  • There's certainly a degree of language design involved, but keep in mind that PowerShell sits on top of .NET. PowerShell attributes are .NET attributes, so they have to follow .NET attribute rules. It'd certainly be possible to extend upon .NET attributes and provide a PowerShell-specific version, but there has to be a way to define .NET attributes due to the nature of PowerShell. – Zenexer Jul 20 '13 at 02:08
  • I think we are talking about two different things :) My answer is focused on syntax: what is the form of the text that is used by the language to instantiate Attribute objects (in this case, `name` + '`=`' + `value`), whereas it looks like your focus has been on the features of the Attribute types themselves. I agree that supporting hashtables or arbitrary PSObjects instead of simple Attributes is unnecessary and, regardless of whether you could write `"name"=value` instead of `name=value`, that does not change the fact that `name` has to refer to an assignable property on the Attribute. – Emperor XLII Jul 20 '13 at 14:56