自动检索受限语言模式的允许类型
Automatically retrieve Allowed Types for Constrained Language mode
为了我的爱好项目ConvertTo-Expression
, I would like the output expression of my cmdlet (by default) compliant with the Constrained Language mode。为此,我可能会包含一个硬编码的 列表,其中包含 Allowed Types:
$AllowedTypes = # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_language_modes?view=powershell-7
[Array],
[Bool],
[byte],
[char],
[DateTime],
[decimal],
...
但我宁愿从 PowerShell 本身自动检索 允许类型列表 ,因为我知道那将是最新版本(例如 [Ordered]
类型是'在网站上列出,但在受限语言模式下似乎是允许的。
有办法吗?
或:
我如何检查(在 full 语言模式 中)特定类型是否符合 constrained 语言模式?
How can I check (in full language mode) if a specific type is compliant with constrained language mode?
您可以根据下面进一步定义的 Test-TypePermitted
函数使用如下内容:
PS> [System.IO.FileInfo], [int] | Test-TypePermitted -Mode Constrained
TypeName Permitted Message
-------- --------- -------
System.IO.FileInfo False Cannot create type. Only core types are supported in this language mode.
System.Int32 True
关于 PowerShell 语言模式的官方 docs(您也 link 提出问题):about_Language_Modes
Test-TypePermitted
函数:
function Test-TypePermitted {
[CmdletBinding(PositionalBinding = $false)]
param(
[Parameter(ValueFromPipeline, Position = 0)]
[Type[]] $Type
,
[Parameter(Position = 1)]
[Alias('Mode')]
[ValidateSet('Restricted', 'Constrained', 'FullLanguage')]
$LanguageMode = 'Constrained'
)
begin {
try {
$ps = [powershell]::Create()
$ps.Runspace.SessionStateProxy.LanguageMode = $LanguageMode
} catch { Throw }
}
process {
foreach ($t in $type) {
$expression = switch -Wildcard ($LanguageMode) {
'Restricted*' {
# In 'RestrictedLanguage' mode, seemingly just referencing the *type*
# of a non-permitted type causes an error.
'[{0}]' -f $t.FullName
}
Default {
# In 'ConstrainedLanguage' mode, whether a type is permitted or not
# only surfaces when you try to *construct an instance*.
# Note: New-Object can construct value types even without argument.
# For reference types, it succeeds only if there is a (public)
# parameterless constructor.
# However, fortunately, construction isn't even attempted if
# the type isn't permitted.
'New-Object ''{0}''' -f $t.FullName
}
}
$message = $null
$permitted = try {
if ($ps.AddScript($expression).Invoke().Count -ne 0) {
$true
} elseif ($ps.Streams.Error[0].FullyQualifiedErrorId -Match 'CannotFindAppropriateCtor') {
# Type is permitted in principle, but couldn't be constructed due to not having a parameterless constructor.
$true
} else {
# Type is not permitted.
$message = $ps.Streams.Error[0].ToString()
$false
}
} catch { # Happens in RestrictedLanguage mode.
# Type is not permitted.
$message = ($_.ToString() -split '\r?\n')[-1].TrimEnd('"')
$false
}
}
[pscustomobject] @{
TypeName = $t.FullName
Permitted = $permitted
Message = $message
}
# Prepare for next iteration.
$ps.Commands.Clear(); $ps.Streams.ClearStreams()
}
end {
$ps.Dispose()
}
}
为了我的爱好项目ConvertTo-Expression
, I would like the output expression of my cmdlet (by default) compliant with the Constrained Language mode。为此,我可能会包含一个硬编码的 列表,其中包含 Allowed Types:
$AllowedTypes = # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_language_modes?view=powershell-7
[Array],
[Bool],
[byte],
[char],
[DateTime],
[decimal],
...
但我宁愿从 PowerShell 本身自动检索 允许类型列表 ,因为我知道那将是最新版本(例如 [Ordered]
类型是'在网站上列出,但在受限语言模式下似乎是允许的。
有办法吗?
或:
我如何检查(在 full 语言模式 中)特定类型是否符合 constrained 语言模式?
How can I check (in full language mode) if a specific type is compliant with constrained language mode?
您可以根据下面进一步定义的 Test-TypePermitted
函数使用如下内容:
PS> [System.IO.FileInfo], [int] | Test-TypePermitted -Mode Constrained
TypeName Permitted Message
-------- --------- -------
System.IO.FileInfo False Cannot create type. Only core types are supported in this language mode.
System.Int32 True
关于 PowerShell 语言模式的官方 docs(您也 link 提出问题):about_Language_Modes
Test-TypePermitted
函数:
function Test-TypePermitted {
[CmdletBinding(PositionalBinding = $false)]
param(
[Parameter(ValueFromPipeline, Position = 0)]
[Type[]] $Type
,
[Parameter(Position = 1)]
[Alias('Mode')]
[ValidateSet('Restricted', 'Constrained', 'FullLanguage')]
$LanguageMode = 'Constrained'
)
begin {
try {
$ps = [powershell]::Create()
$ps.Runspace.SessionStateProxy.LanguageMode = $LanguageMode
} catch { Throw }
}
process {
foreach ($t in $type) {
$expression = switch -Wildcard ($LanguageMode) {
'Restricted*' {
# In 'RestrictedLanguage' mode, seemingly just referencing the *type*
# of a non-permitted type causes an error.
'[{0}]' -f $t.FullName
}
Default {
# In 'ConstrainedLanguage' mode, whether a type is permitted or not
# only surfaces when you try to *construct an instance*.
# Note: New-Object can construct value types even without argument.
# For reference types, it succeeds only if there is a (public)
# parameterless constructor.
# However, fortunately, construction isn't even attempted if
# the type isn't permitted.
'New-Object ''{0}''' -f $t.FullName
}
}
$message = $null
$permitted = try {
if ($ps.AddScript($expression).Invoke().Count -ne 0) {
$true
} elseif ($ps.Streams.Error[0].FullyQualifiedErrorId -Match 'CannotFindAppropriateCtor') {
# Type is permitted in principle, but couldn't be constructed due to not having a parameterless constructor.
$true
} else {
# Type is not permitted.
$message = $ps.Streams.Error[0].ToString()
$false
}
} catch { # Happens in RestrictedLanguage mode.
# Type is not permitted.
$message = ($_.ToString() -split '\r?\n')[-1].TrimEnd('"')
$false
}
}
[pscustomobject] @{
TypeName = $t.FullName
Permitted = $permitted
Message = $message
}
# Prepare for next iteration.
$ps.Commands.Clear(); $ps.Streams.ClearStreams()
}
end {
$ps.Dispose()
}
}