powershell - 如何使用 System.Manangement.Automation.Language... ast
问题描述
所以我试图为办公室创建一个自定义的 PsAnalyzer 规则,这是我第一次使用$ast
基于命令/变量。结果我有点不知所措。
我一直在使用几个站点来了解[System.Management.Automation.Language]
对象类,即this、this和this。
出于测试目的,我正在使用下面的函数 - 看起来很狡猾的参数。
Function IE {
[cmdletbinding()]
Param(
$Url,
$IEWIDTH = 550,
$IeHeight = 450
)
$IE = new-object -comobject InternetExplorer.Application
$IE.top = 200 ; $IE.width = $IEWIDTH ; $IE.height = $IEHEIGHT
$IE.Left = 100 ; $IE.AddressBar = $FALSE ; $IE.visible = $TRUE
$IE.navigate( "file:///$Url" )
}
然后使用下面的代码,我希望$IEWIDTH
它是唯一失败的参数。
Function Measure-PascalCase {
<#
.SYNOPSIS
The variables names should be in PascalCase.
.DESCRIPTION
Variable names should use a consistent capitalization style, i.e. : PascalCase.
.EXAMPLE
Measure-PascalCase -ScriptBlockAst $ScriptBlockAst
.INPUTS
[System.Management.Automation.Language.ScriptBlockAst]
.OUTPUTS
[Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord[]]
.NOTES
https://msdn.microsoft.com/en-us/library/dd878270(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/ms229043(v=vs.110).aspx
https://mathieubuisson.github.io/create-custom-rule-psscriptanalyzer/
#>
[CmdletBinding()]
[OutputType([Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
Param
(
[Parameter(Mandatory = $True)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.Language.ScriptBlockAst]
$ScriptBlockAst
)
Process {
$Results = @()
try {
#region Define predicates to find ASTs.
[ScriptBlock]$Predicate = {
Param ([System.Management.Automation.Language.Ast]$Ast)
[bool]$ReturnValue = $false
if ( $Ast -is [System.Management.Automation.Language.ParameterAst] ){
[System.Management.Automation.Language.ParameterAst]$VariableAst = $Ast
if ( $VariableAst.Left.VariablePath.UserPath -eq 'i' ){
$ReturnValue = $false
} elseif ( $VariableAst.Left.VariablePath.UserPath.Length -eq 3 ){
$ReturnValue = $false
} elseif ($VariableAst.Left.VariablePath.UserPath -cnotmatch '^([A-Z][a-z]+)+$') {
$ReturnValue = $True
}
}
return $ReturnValue
}
#endregion
#region Finds ASTs that match the predicates.
[System.Management.Automation.Language.Ast[]]$Violations = $ScriptBlockAst.FindAll($Predicate, $True)
If ($Violations.Count -ne 0) {
Foreach ($Violation in $Violations) {
$Result = New-Object `
-Typename "Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord" `
-ArgumentList "$((Get-Help $MyInvocation.MyCommand.Name).Description.Text)",$Violation.Extent,$PSCmdlet.MyInvocation.InvocationName,Information,$Null
$Results += $Result
}
}
return $Results
#endregion
}
catch {
$PSCmdlet.ThrowTerminatingError($_)
}
}
}
Export-ModuleMember -Function Measure-*
相反,我得到:
Line Extent Message
---- ------ -------
6 $Url Variable names should use a consistent capitalization style, i.e. : PascalCase.
7 $IEWIDTH = 550 Variable names should use a consistent capitalization style, i.e. : PascalCase.
8 $IeHeight = 450 Variable names should use a consistent capitalization style, i.e. : PascalCase.
6 $Url Variable names should use a consistent capitalization style, i.e. : PascalCase.
7 $IEWIDTH = 550 Variable names should use a consistent capitalization style, i.e. : PascalCase.
8 $IeHeight = 450 Variable names should use a consistent capitalization style, i.e. : PascalCase.
关于我做错了什么的任何想法?我在这里找到了另一个站点,如果我使用该方法一次测试单个变量,我会得到我期望看到的结果。
为此,请在函数 IE 的末尾添加以下行,
[System.Management.Automation.Language.Parser]::ParseInput($MyInvocation.MyCommand.ScriptContents, [ref]$null, [ref]$null)
然后下面的代码将为您提供长度数字。
$stuffast = .\FunctionIe.ps1
$left = $Stuffast.FindAll({$args[0] -is [System.Management.Automation.Language.AssignmentStatementAst]},$true)
$left[0].Left.Extent.Text.Length
$left[0].Left.VariablePath.UserPath.Length
解决方案
与AssignmentStatementAst
具有Left
和Right
(-hand)值属性的 an 不同,ParameterAst
具有Name
andDefaultValue
属性,因此您需要Name
在谓词块中使用:
$predicate = {
# ...
if ( $Ast -is [System.Management.Automation.Language.ParameterAst] ) {
[System.Management.Automation.Language.ParameterAst]$VariableAst = $Ast
if ( $VariableAst.Name.VariablePath.UserPath -eq 'i' ) {
$ReturnValue = $false
}
elseif ( $VariableAst.Name.VariablePath.UserPath.Length -eq 3 ) {
$ReturnValue = $false
}
elseif ($VariableAst.Name.VariablePath.UserPath -cnotmatch '^([A-Z][a-z]+)+$') {
$ReturnValue = $True
}
}
# ...
}
或者,翻转您的谓词逻辑以搜索VariableExpressionAst
父节点为AssignmentStatementAst
or之一的 's ParameterAst
:
$predicate = {
param($ast)
$ValidParents = @(
[System.Management.Automation.Language.ParameterAst]
[System.Management.Automation.Language.AssignmentStatementAst]
)
if($ast -is [VariableExpressionAst] -and $ValidParents.Where({$ast -is $_}, 'First')){
[System.Management.Automation.Language.VariableExpressionAst]$variableAst = $ast
# inspect $variableAst.VariablePath here
}
return $false
}
推荐阅读
- c - 为什么 pow(10,2) 的结果是 99 而不是 100?
- swift - Xcode 10.1 调试器 - 如何在 Xcode 的调试器中查看整个对象集合?
- leaflet - 从 50% 不透明度的 tilelayer WMS 生成图像
- artificial-intelligence - Fluid-synth 始终确保存在银行编号
- ruby-on-rails - AJAX Ruby on Rails | 部分不重新渲染
- scala - 从 Scala 中的抽象类创建匿名类 - 脱糖代码
- c# - 如何将现有类转换为带有事件的 DDD 聚合?
- c# - 查找与 PID 对应的 HWND
- javascript - ReactJS - TypeError:无法读取未定义的属性'setState' - LocalForage IndexedDB GraphQL
- mysql - 在mysql中的某个时间后获取下一个可用时间段