确定PowerShell模块的.NET和CLR要求

问题描述

模块清单,让我们指定对.NET和CLR的要求,来自清单* .psd1

# Minimum version of Microsoft .NET Framework required by this module.
# This prerequisite is valid for the PowerShell Desktop edition only.
DotNetFrameworkVersion = "3.5"

# Minimum version of the common language runtime (CLR) required by this module.
# This prerequisite is valid for the PowerShell Desktop edition only.
CLRVersion = "2.0"

我有几个正在使用的模块,但找不到任何资源来帮助我指定模块所需的最低版本。

解决此问题,我正在考虑编写一个正则表达式脚本,该脚本将扫描模块中使用的.NET类型,例如,该脚本将收集诸如以下的类型:

[System.Net.IPAddress]
[System.Management.Automation.ValidateUserDriveAttribute]

根据使用的类型,我可以检查引入了哪些类型的.NET和CLR。

然后,我也可以使用旧版PowerShell运行测试,但只能使用“ Core”版运行,我不确定是否可以安装旧版Windows PowerShell。

这是很多工作,我什至不确定是否能解决我的问题,您知道更好的方法可以用来学习需求吗?

解决方法

我正在考虑编写一个正则表达式脚本,该脚本将扫描.NET类型的模块

它不会给您完整的图片,但这是一个好的开始!

我要强调的一件事-不要在这种类型的静态分析中使用正则表达式!

PowerShell公开了其语言解析器,因此使用它来生成抽象语法树,然后可以使用它来发现诸如类型文字名称之类的东西:

using namespace System.Management.Automation.Language

Get-ScriptTypeLiteral
{
  param([string]$LiteralPath)

  $filePath = Resolve-Path @PSBoundParameters

  # Step 1,parse the file to produce an AST
  $AST = [Parser]::ParseFile($filePath,[ref]$null,[ref]$null)

  # Step 2,find all type literals
  $TypeLiterals = $AST.FindAll({
    param($SubAST) 
    # Type literals come in two variants - expressions and attributes 
    # Expressions are things like the first half of `[type]::Member`
    # Attributes cover things like [ValidateLength()] as well as type constraints in param blocks
    $SubAST -is [TypeExpressionAst] -or $SubAST -is [AttributeAst]
  },$true)

  # Step 3,return the type names
  return $TypeLiterals.TypeName
}

您可以进一步采用这种方法,并使用它来发现诸如member access expressions之类的事物,以同时考虑各个版本之间的BCL类型差异。

虽然我从未将其用于特定目的,但我怀疑您可以利用PSScriptAnalyzer通过自定义规则简化此过程。

这是很多工作,我什至不确定是否能解决我的问题,您知道更好的方法可以用来学习需求吗?

我不确定我是否会考虑上述任何“最佳实践”,但是可能值得在the PowerShell GitHub repo

中提交问题以寻求指导 ,

在@Mathias答案的帮助下,我进行了一些研究,得出了非常简单且准确率达到90%的解决方案。

第一步是为PSScriptAnalyzer定义规则,该规则应在文件PSScriptAnalyzerSettings.psd1中定义,并将其放入存储库中的根目录中。

文件应包含以下规则:

@{
    IncludeRules = @(
    
    'PSUseCompatibleCmdlets'
    'PSUseCompatibleSyntax'
    
     Rules = @{

        PSUseCompatibleSyntax = @{
            Enable = $true
            TargetVersions = @(
                "7.0","5.1"
            )
        }

        PSUseCompatibleCmdlets = @{
            compatibility = @(
                "core-6.1.0-windows"
                "desktop-5.1.14393.206-windows"
            )
         }
      }
   )
}

然后从存储库的根目录调用分析器:

Invoke-ScriptAnalyzer .\ -Recurse -Settings .\PSScriptAnalyzerSettings.psd1

这将使您知道模块是否调用了任何与Core 6.1或Desktop 5.1不兼容的Commandlet。

如果收到警告,则不支持这些版本,这意味着需要在更高的PowerShell版本上执行测试。

为什么这很重要?这是关于PowerShell版本而不是.NET或CLR ... 如果5.1是最新的Windows PowerShell版本,又如何测试?

上面的规则中还有一个内部版本号14393,可能会报告问题,下一步是确定该内部版本的Windows版本,具体操作请参见:

Windows 10 release information

从这里我们看到内部版本号是针对Windows v1607的。

下一步是查看哪些版本的Windows中包含了.NET版本,请参见:

.NET Framework versions and dependencies

从这里我们看到Windows 10中包含的最低.NET版本是.NET Framework 4.6,具体取决于CLR 4.0

目前,这一切都取决于要在哪个系统上部署模块,如果您从PSScriptAnalyzer得到警告,则最低要求是.NET 4.6和CLR 4.0

下一步是确定模块发生故障的确切操作系统内部版本号,为此,请参见:

Determine which .NET Framework versions are installed

这应该会有所帮助,但是需要进行测试,所以我对大致的结果感到满意。