在ps1中查找函数并调用

时间:2017-03-12 07:13:57

标签: powershell powershell-v3.0

如何找到特定.ps1文件中存在的所有已经点源的函数并在循环中调用这些方法? (不需要参数)

我们知道使用Get-ChildItem函数:\将列出shell中的所有方法。

一种解决方案可能是对.ps1文件中的所有函数使用特定的命名约定,并使用Get-ChildItem函数:\ unique_pattern * search。这确实感觉有点脆弱。

另外,我不知道如何根据Get-ChildItem的返回信息调用该函数。有什么想法吗?

4 个答案:

答案 0 :(得分:3)

使用PowerShell 3.0 + Language namespace解析器列出ps1文件中的所有顶级函数名称::

$code = Get-Content -literal 'R:\source.ps1' -raw
$fns = [Management.Automation.Language.Parser]::ParseInput($code, [ref]$null, [ref]$null).
    EndBlock.Statements.
    FindAll([Func[Management.Automation.Language.Ast,bool]]{
        $args[0] -is [Management.Automation.Language.FunctionDefinitionAst]
    }, $false) |
    Select -expand Name

在点源脚本后,在变量中按名称调用函数:

& $name param1 param2 param3

答案 1 :(得分:1)

另一种可能性(不相信它是最好的一种,但可能会给你另一条跟踪,取决于你的用例):

$before = dir function:\

. .\test.ps1
# test.ps1 contains
# function f1 { Write-Output "f1 called" }
# function f2 { Write-Output "f2 called" }
# function f3 { Write-Output "f3 called" }

$after = dir function:\

$newFunctions = compare-object $before $after | ?{ $_.SideIndicator -eq "=>" } | select -ExpandProperty InputObject

$newFunctions | %{
    . $_
}

答案 2 :(得分:0)

使用 Ronald Rink 创建的功能。 您可以将脚本保存为.ps1,执行后,您将能够看到其中的功能。因此,您可以将它放在脚本中以枚举所有自定义函数。

他使用Abstract Syntax Tree class(AST)来实现它。

以下是相同的参考链接:Enumerate all PS Functions in a Script File

[CmdletBinding(
    SupportsShouldProcess = $true
    ,
    ConfirmImpact = 'Low'
    ,
    DefaultParameterSetName = 'list'
)]
Param
(
    [Parameter(Mandatory = $false, Position = 0, ParameterSetName = 'list')]
    [Switch]
    $ListAvailable = $true
)

BEGIN
{
    function functionInBeginBlock()
    {
        return "functionInBeginBlock";
    }

    function getFunctions($_MyInvocation)
    {
        $OutputParameter = @();
        foreach($BlockName in @("BeginBlock", "ProcessBlock", "EndBlock"))
        {
            $CurrentBlock = $_MyInvocation.MyCommand.ScriptBlock.Ast.$BlockName;
            foreach($Statement in $CurrentBlock.Statements)
            {
                $Extent = $Statement.Extent.ToString();
                if([String]::IsNullOrWhiteSpace($Statement.Name) -Or $Extent -inotmatch ('function\W+(?<name>{0})' -f $Statement.Name))
                {
                    continue;
                }
                $OutputParameter += $Statement.Name;
            }
        }
        return $OutputParameter;
    }
}

PROCESS
{
    function functionInProcessBlock()
    {
        return "functionInProcessBlock";
    }
}

END
{
    function functionInEndBlock()
    {
        return "functionInEndBlock";
    }

    function theAnswer()
    {
        return 42;
    }

    return getFunctions($MyInvocation);
}

希望它有所帮助。

答案 3 :(得分:0)

在Ronald和@ wOxxOm的回答基础上,这是一种单行方法,用于提供当前正在执行的脚本文件的本地定义函数。由于我们使用AST,因此任何angular.module('starter').controller('ComprarCtrl', ComprarCtrl); ComprarCtrl.$inject = ['$scope', 'ProductosService']; function ComprarCtrl($scope, ProductosService) { var vm = this; ProductosService.lista().then(function(productos) { console.log(productos); $scope.productos = productos; vm.productos = productos; }); } 源函数都不会显示在此处。另外需要注意的是,这将处理您没有任何dotBegin块的情况,因为在这种情况下,AST会将整个脚本放入Process块。

End