我在 电源外壳 Slack. 频道和渠道 Joel Bennett. mentioned inheriting from System.Management.Automation.ValidateArgumentsAttribute to create a custom validator. This builds directly on my last post because you are creating a custom attribute to do this.

这是两个部分帖子的第二部分。

在开始之前,明白这是一个非常先进的技术,我们即将深入潜入它。

指数

什么是og体育者?

只是为了确保我们在同一页面上。og体育程序是您可以将参数附加到高级功能中的属性。他们会为您og体育您的论点,所以您不必自己做到这一点。

 function Verb-Noun
 {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [ValidateSet("sun", "moon", "earth")]
        $Param1
        ...

有一个长长的og体育器中内置的,今天我们将介绍如何制作自己的自定义og体育器。

自定义validatePathExistattribute.

One thing that I find myself doing quite often is using a [ValidateScript({Test-Path -Path $_})] on path parameters. This checks they are valid, except the error message is worthless. So instead of just using a script block, we can implement our own validator.

class ValidatePathExistsAttribute : System.Management.Automation.ValidateArgumentsAttribute
{
    [void]  Validate([object]$arguments, [System.Management.Automation.EngineIntrinsics]$engineIntrinsics)
    {
        $path = $arguments
        if([string]::IsNullOrWhiteSpace($path))
        {
            Throw [System.ArgumentNullException]::new()
        }
        if(-not (Test-Path -Path $path))
        {
            Throw [System.IO.FileNotFoundException]::new()
        }        
    }
}

The first thing to point out is that I postfix my name with the 属性 keyword. When we attach that to our property, we can call it [ValidatePathExists()].

I inherit the ValidateArgumentsAttribute and I override the [void] Validate ([object]$arguments, [System.Management.Automation.EngineIntrinsics]$engineIntrinsics) function. I figured this out by looking at the Powershell source for an 例子.

The $Arguments contains the value of the property. I have no idea what the $engineIntrinsics is, so I ignore it for now.

I decided to use standard exceptions in this case so the error message is localized. I could throw a custom message if needed.

使用og体育器

现在我们有一个自定义og体育器,我们可以将它附加到我们的财产,让PowerShell完成其余部分。

function Do-Something
{
    [cmdletbinding()]
    param(
        [ValidatePathExists()]
        $Path
    )
    return $Path
}	 

然后我们运行我们的测试程序以查看结果

PS:> Do-Something -Path 'C:\Windows'
C:\Windows

PS:> Do-Something -Path 'testvalue'
do-something : Cannot validate argument on parameter 'Path'. Unable to find the specified file.

PS:> Do-Something -Path $null
do-something : Cannot validate argument on parameter 'Path'. Value cannot be null.

使用自定义og体育器的其他原因

我经常使用脚本并匹配og体育器,但我不喜欢隐秘的错误消息。如果您真的需要更好的og体育器错误消息,值得考虑此选项。

argumentTransformationAttribute.

A lesser known attribute built into Powershell is the argumentTransformationAttribute.. This is also one that I discovered when looking at the Powershell source. There are only two (that are publicly accessible) instances that I know of.

类型加速器

我需要暂停一二次提一下 类型加速器. These transforms are just like those except with a Type Accelerator, your value becomes that type. A transform can do anything and return any type (as long as it is an [Object]).

[system.management.Automation.Credential()]

I ran across this one a while back. You can attach this attribute to a parameter. If you pass in a string, then you will be prompted for the password. If you give it a [PSCredential], it will use that credential.

function Do-Something
{
    [cmdletbinding()]
    param(
        [system.management.Automation.Credential()]
        $Credential
    )
    return $Credential
}

Do-Something -Credential 'username'

So this attribute transforms a string into something else. Starting with Powershell 5.0, you get this same functionality by specifying the type as [PSCredential].

[ArgugentToconFigurationDatatRansformationAttribute()]

我去寻找另一个例子,我发现了这个 宝石 。如果将此连接到属性,则允许您指定文件路径。如果它发现PSD1文件,它将参数转换为哈希表的PSD1的内容。所以它自动为您导入哈希表。

function Get-HashtableFromFile
{
    [cmdletbinding()]
    param(
        [Microsoft.PowerShell.DesiredStateConfiguration.ArgumentToConfigurationDataTransformation()]
        $Path
    )
    return $Path
}

$path = 'C:\workspace\PSGraph\PSGraph\PSGraph.psd1'
Get-HashtableFromFile -Path $path

我不认为这是为了我们来使用这种方式,但这是一个很好的例子。

自定义路径阵列形式化

我们可以采取我们在这里学到的一切,并建立自己的变革。有关一个简单的示例,允许创建一个转换,该转换为文件提供完整路径。

class PathTransformAttribute : System.Management.Automation.argumentTransformationAttribute.
{
    [object] Transform([System.Management.Automation.EngineIntrinsics]$engineIntrinsics, [object] $inputData)
    {
        if ( $inputData -is [string] )
        {
            if ( -NOT [string]::IsNullOrWhiteSpace( $inputData ) )
            {
                $fullPath = Resolve-Path -Path $inputData -ErrorAction SilentlyContinue
                if ( ( $fullPath.count -gt 0 ) -and ( -Not [string]::IsNullOrWhiteSpace( $fullPath ) ) 
                {
                    return $fullPath.Path
                }                
            }
        }
        $fullName = $inputData.Fullname
        if($fullName.count -gt 0)
        {
            return $fullName
        }

        throw [System.IO.FileNotFoundException]::new()
    }
}

For this attribute, we inherit from System.Management.Automation.argumentTransformationAttribute. and override the [object] Transform([System.Management.Automation.EngineIntrinsics]$engineIntrinsics, [object] $inputData) function.

The inner logic checks for a [string] and does a Resolve-Path on it. Then if it can find a FullName property (assuming a file or directory), then it returns the FullPath. I decided to throw an error if there was no match but I could have returned the original object.

使用变换

现在我们使用它就像我们的Validator属性。

function Get-Path
{
    [cmdletbinding()]
    param(
        [PathTransform()]
        $Path
    )
    return $Path
}

Get-Path -Path '\Windows'
Get-Path -Path (Get-ChildItem $ENV:temp)

大局

这些自定义og体育器和变换真正是高级功能。但如果您发现自己在模块上的某些数据组上进行相同的og体育和转换,则值得考虑此选项。

我可以看到创建一个og体育器,以og体育客户身分的格式(而不是正则表达式匹配)。

Another validator that I am considering building already is one that verifies that a [Hashtable] or a [PSCustomObject] has a specific key (or keys). I often pass in a hashtable that I assume has a set structure to it and this would let be validate those assumptions.