Get all the features in PowerShell Script

I have a problem similar to this question . I want to get all the functions in a given PowerShell script, but the difference is that I do not want to execute the contents of the script, and I do not want to execute the functions.

The goal is to be able to load all functions into the execution space in order to be able to extract comment help from each function for documentation purposes.

Does anyone have magic tricks to just load functions from .ps1 without executing all the other code inside this file?

I was thinking of using [System.Management.Automation.PSParser]::Tokenize()a script to parse the file, but this is much more than I would like to do. If someone has something easier, I would be glad.

# 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
}
+4
2

AST - () . ,

$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()
}

$tokens , . AST, .

. - , - , - , . , - , . .

GetHelpContent FunctionDefinitionAst

$helpContent = $functionDefinitions | ForEach-Object { $_.GetHelpContent() }

CommentHelpInfo . , , Get-Help. , , . , , 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
    }
}
+5

( script), . "" script , , , .

, , PowerShell, , :

Get-Command -Module Example -CommandType Function

CommandType, .

( /) , , , .

, script , function. , , , , .


, , , :

functions.ps1

# 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"
}

, .

execute.ps1

. .\path\functions.ps1

# But I don't want to execute any of this
$Items = Get-ChildItem
$Items | ForEach-Object {
    Invoke-Stuff
}
+1

Source: https://habr.com/ru/post/1684638/


All Articles