我在 电源外壳 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.
这是两个部分帖子的第二部分。
- 第1部分:创建和使用自定义属性
- 第2部分:创建参数og体育器和转换(此帖子)
在开始之前,明白这是一个非常先进的技术,我们即将深入潜入它。
指数
什么是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.