获取PowerShell脚本中的所有函数

Som*_*ica 5 powershell

我有类似这个问题的问题.我想获取给定PowerShell脚本中的所有函数,但区别在于我不想执行脚本的内容而我不想执行这些函数.

目的是能够将所有函数加载到运行空间中,以便能够从每个函数中提取基于注释的帮助以用于文档目的.

有没有人有任何神奇的技巧来加载.ps1中的函数而不执行该文件中的所有其他代码?

我想过要[System.Management.Automation.PSParser]::Tokenize()用来解析脚本文件,但这比我想做的要多得多.如果某人有更轻松的事情,我会很高兴.

# I want to load this to get the comment-based help
Function Invoke-Stuff {
    <#
    .SYNOPSIS
       Stuff doer
    .DESCRIPTION
       It does lots of stuff
    .EXAMPLE
       Invoke-Stuff
    #>
    Write-Host "Stuff was done"
}

# But I don't want to execute any of this
$Items = Get-ChildItem
$Items | ForEach-Object {
    Invoke-Stuff
}
Run Code Online (Sandbox Code Playgroud)

Pat*_*cke 8

AST是进行静态(ish)分析的方法.这就是我如何做你所描述的

$rs = [runspacefactory]::CreateRunspace()
$rs.Open()

# Get the AST of the file
$tokens = $errors = $null
$ast = [System.Management.Automation.Language.Parser]::ParseFile(
    'MyScript.ps1',
    [ref]$tokens,
    [ref]$errors)

# Get only function definition ASTs
$functionDefinitions = $ast.FindAll({
    param([System.Management.Automation.Language.Ast] $Ast)

    $Ast -is [System.Management.Automation.Language.FunctionDefinitionAst] -and
    # Class methods have a FunctionDefinitionAst under them as well, but we don't want them.
    ($PSVersionTable.PSVersion.Major -lt 5 -or
    $Ast.Parent -isnot [System.Management.Automation.Language.FunctionMemberAst])

}, $true)

# Add the functions into the runspace
$functionDefinitions | ForEach-Object {
    $rs.SessionStateProxy.InvokeProvider.Item.Set(
        'function:\{0}' -f $_.Name,
        $_.Body.GetScriptBlock()) 
}

# Get help within the runspace.
$ps = [powershell]::Create().AddScript('Get-Help MyFunction')
try {
    $ps.Runspace = $rs
    $ps.Invoke()
} finally {
    $ps.Dispose()
}
Run Code Online (Sandbox Code Playgroud)

$tokens如果你想要一个纯粹的静态路线,你也可以使用从顶部附近的.评论不会出现在AST中,但它们会出现在令牌中.

编辑上面的方法实际上在进程中的某处丢失了注释帮助,不是因为运行空间而是因为函数的分配方式.可能由于评论并不真正成为AST的一部分.无论如何,有一种更直接,更静态的方式来获得帮助.

您可以使用该GetHelpContent方法,而不是定义函数FunctionDefinitionAst

$helpContent = $functionDefinitions | ForEach-Object { $_.GetHelpContent() }
Run Code Online (Sandbox Code Playgroud)

这将为每个函数返回CommentHelpInfo对象.需要注意的是,这是很重要的不是由返回相同的对象Get-Helpcmdlet的.最值得注意的是,它不区分示例块中的代码和描述之类的内容.但是,如果您需要正常解析CBH,您可以获取注释块文本并定义您自己的假版本.

$helpContent = $functionDefinitions | ForEach-Object {

    # Get the plain string comment block from the AST.
    $commentBlock = $_.GetHelpContent().GetCommentBlock()

    # Create a scriptblock that defines a blank version of the
    # function with the CBH. You may lose some parameter info
    # here, if you need that replace param() with
    # $_.Body.ParamBlock.Extent.Text
    $scriptBlock = [scriptblock]::Create(('
    function {0} {{
        {1}
        param()
    }}' -f $_.Name, $commentBlock))

    # Dot source the scriptblock in a different scope so we can
    # get the help content but still not pollute the session.
    & {
        . $scriptBlock

        Get-Help $_.Name
    }
}
Run Code Online (Sandbox Code Playgroud)