【问题标题】:Automatically retrieve Allowed Types for Constrained Language mode自动检索受限语言模式的允许类型
【发布时间】:2021-05-20 23:37:58
【问题描述】:

对于我的爱好项目ConvertTo-Expression,我希望我的cmdlet 的输出表达式(默认情况下)符合Constrained Language mode。为此,我可能会包含一个硬编码的允许类型列表

$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] 类型未在网站上列出,但似乎在受限语言模式下是允许的)。

有没有办法做到这一点?
或者:
我如何检查(在完整语言模式)特定类型是否符合受限语言模式

【问题讨论】:

  • 好问题。快速抛开[ordered],让其他人知道:它不是类型(字面量)本身,只能用作 syntactic sugar 构造 [ordered] @{ ... } 的一部分,它允许您创建有序哈希表(字典),即其条目以定义顺序维护的哈希表。底层 .NET 类型是 [System.Collections.Specialized.OrderedDictionary]
  • @mklement0,我创建了一个文档问题,但我认为这里实际上存在错误(或严重不一致),请参阅:Incomplete Allowed Types list

标签: powershell expression


【解决方案1】:

如何检查(在完整语言模式下)特定类型是否符合受限语言模式?

您可以根据下面进一步定义的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 

官方 docs re PowerShell 语言模式(您也可以从问题链接到):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()
  }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-16
    • 2018-10-13
    • 2022-10-19
    • 2014-03-18
    • 2020-10-02
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    相关资源
    最近更新 更多