Powershell 从脚本中获取函数列表
如果我有一个带有以下函数的.ps1文件Powershell 从脚本中获取函数列表,powershell,Powershell,如果我有一个带有以下函数的.ps1文件 function SomeFunction {} function AnotherFunction {} get-command -module scriptfile function SomeFunction function AnotherFunction 如何获取所有这些函数的列表并调用它们 我想这样做: $functionsFromFile = Get-ListOfFunctions -Path 'C:\someScript.ps1' fo
function SomeFunction {}
function AnotherFunction {}
get-command -module scriptfile
function SomeFunction
function AnotherFunction
如何获取所有这些函数的列表并调用它们
我想这样做:
$functionsFromFile = Get-ListOfFunctions -Path 'C:\someScript.ps1'
foreach($function in $functionsFromFile)
{
$function.Run() #SomeFunction and AnotherFunction execute
}
您可以使用
getchilditem
检索所有函数并将它们存储到变量中。然后将脚本加载到to运行空间并再次检索所有函数,然后使用Where-Object
cmdlet通过排除以前检索到的所有函数来过滤所有新函数。最后迭代所有新函数并调用它们:
$currentFunctions = Get-ChildItem function:
# dot source your script to load it to the current runspace
. "C:\someScript.ps1"
$scriptFunctions = Get-ChildItem function: | Where-Object { $currentFunctions -notcontains $_ }
$scriptFunctions | ForEach-Object {
& $_.ScriptBlock
}
我需要从多功能脚本中获取函数的名称。这就是我想到的。基于此,也许有人可以提供一个较短的版本
# Get text lines from file that contain 'function'
$functionList = Select-String -Path $scriptName -Pattern "function"
# Iterate through all of the returned lines
foreach ($functionDef in $functionList)
{
# Get index into string where function definition is and skip the space
$funcIndex = ([string]$functionDef).LastIndexOf(" ") + 1
# Get the function name from the end of the string
$FunctionExport = ([string]$functionDef).Substring($funcIndex)
Write-Output $FunctionExport
}
我提出了一个较短的版本来查找和列出脚本列表中的函数。它不是完美的,并且会有问题,因为模式只是单词“Function”,如果这个方法假设它在任何地方找到了一个函数,那么它就会找到关键字 为了遍历文件并获取列表,我使用了“get ChildItem”函数,并使用递归选项传递了路径和文件过滤器规范 它通过管道传递到“Select String”中,并查找“Function”关键字。它不区分大小写,将接受“Function”或“Function”。如果需要,可以添加“-区分大小写”选项 然后迭代输出以获得实际的函数名。“Line”成员是一种字符串类型,我使用了从位置9开始的“Substring”选项,它是刚刚通过“function”标识符的长度
$scriptPath = "c:\\Project"
$scriptFilter = "*.ps1"
( Get-ChildItem -Path $scriptPath -Filter $scriptFilter -Recurse | Select-String -Pattern "function" ) | %{ $_.Line.Substring(9) }
解决方案1. 如果需要使用另一个脚本文件中的函数,可以使用cmdlet导入该函数 函数。ps1包含完整的函数。此脚本需要由主脚本导入
function Write-TextColor
{
Param(
[parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[Object]
$Info,
[parameter(Position=1, ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[System.ConsoleColor]
$ForegroundColor = [System.ConsoleColor]::White,
[parameter(Position=2, ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[Switch]
$NoNewLine
)
Process{
foreach ($value in $Info)
{
if($NoNewLine)
{
Write-Host $value -ForegroundColor $ForegroundColor -NoNewline
}
else {
Write-Host $value -ForegroundColor $ForegroundColor
}
}
}
}
function Write-InfoBlue
{
Param(
[parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[Object]
$Information,
[parameter(Position=1, ValueFromPipeline=$true)]
[Switch]
$NoNewLine
)
Process{
Write-TextColor $Information Blue $NoNewLine
}
}
Main.ps1
Import-Module -Name "$($PSCommandPath | Split-Path)/Functions.ps1" -Force
Write-InfoBlue "Printed from imported function."
$FX_ALL_DEFS = Get-AmalgamatedScriptFunctionDefinitions -Path "$($PSCommandPath | Split-Path)/Functions.ps1"
$R_HOST = "192.168.211.1"
$R_USERNAME = "root"
$R_PORT = "2222"
$R_SESSION = New-PSSession -HostName $R_USERNAME@$($R_HOST):$R_PORT #//Connected by OpenSSL, private key added to OpenSSH Session Agent. If you need login by password, remove the private key from OpenSSH Session Agent and write as follows user:pass@host:port $($R_USERNAME):$R_PASS@$($R_HOST):$R_PORT
Invoke-Command -ArgumentList $FX_ALL_DEFS,"Joma" -Session $R_SESSION -ScriptBlock{ #// -ArgumentList function definitions and a name.
Param($fxs, $name) #// Param received by remote context.
. ([System.Management.Automation.ScriptBlock]::Create($fxs)) #//Creating function definitions in remote script context.
Clear-Host
Write-Host "Running commands in my remote Linux Server" -ForegroundColor Green #//Powershell Core cmdlet
#//We can use Write-InfoBlue on this script context.
Write-InfoBlue ($(Get-Content /etc/*-release | Select-String -Pattern "^PRETTY_NAME=.*" ).ToString().Split("=")[1]) #//Created function + cmdlets combo
Write-InfoBlue $(uname -a) #//Created function + Native remote command
Write-InfoBlue $(whoami) #//Cmdlet + Native remote command
printf "Hello! $name" #//Native remote command
Write-InfoBlue "Local function executed in remote context"
}
Remove-PSSession -Session $R_SESSION
控制台输出
解决方案2. 函数。ps1包含完整的函数。此脚本需要由主脚本导入。与Solution1的脚本相同 Main.ps1
此脚本包含3个函数。
1. 获取脚本函数名。它返回一个字符串数组,每个元素都是函数名。
2. 获取脚本函数定义。它返回一个字符串数组,每个元素都是完整的函数。
3. 获取合并脚本函数定义。它只返回一个字符串,即连接函数Get-ScriptFunctionDefinitions返回的所有元素的结果。 所有3个都需要相同的参数,即Powershell脚本文件的路径 我们将在此文件上测试这3个函数 此脚本未使用导入模块cmdlet
function Get-ScriptFunctionNames {
param (
[parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[AllowEmptyString()]
[AllowNull()]
[System.String]
$Path
)
Process{
[System.Collections.Generic.List[String]]$FX_NAMES = New-Object System.Collections.Generic.List[String]
if(!([System.String]::IsNullOrWhiteSpace($Path)))
{
Select-String -Path "$Path" -Pattern "function" |
ForEach-Object {
[System.Text.RegularExpressions.Regex] $regexp = New-Object Regex("(function)( +)([\w-]+)")
[System.Text.RegularExpressions.Match] $match = $regexp.Match("$_")
if($match.Success)
{
$FX_NAMES.Add("$($match.Groups[3])")
}
}
}
return ,$FX_NAMES.ToArray()
}
}
function Get-ScriptFunctionDefinitions {
param (
[parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[AllowEmptyString()]
[AllowNull()]
[System.String]
$Path
)
Process{
[System.Collections.Generic.List[String]]$FX_DEFS = New-Object System.Collections.Generic.List[String]
if(!([System.String]::IsNullOrWhiteSpace($Path)))
{
Import-Module -Name "$Path" -Force
}
$names = Get-ScriptFunctionNames -Path $Path
Get-ChildItem "function:" | Where-Object { $_ -in $names } | ForEach-Object{
$FX_DEFS.Add("function $($_.Name) { $($_.Definition) };")
}
return ,$FX_DEFS.ToArray()
}
}
function Get-AmalgamatedScriptFunctionDefinitions {
param (
[parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[AllowEmptyString()]
[AllowNull()]
[System.String]
$Path
)
Process{
[System.String]$FX_DEFS = ""
Get-ScriptFunctionDefinitions -Path $Path |
ForEach-Object {
$FX_DEFS += "$_$([System.Environment]::NewLine)$([System.Environment]::NewLine)"
}
return $FX_DEFS
}
}
Write-Host
[System.String[]]$FX_NAMES = Get-ScriptFunctionNames -Path "$($PSCommandPath | Split-Path)/Functions.ps1"
[System.String[]]$FX_DEFS = Get-ScriptFunctionDefinitions -Path "$($PSCommandPath | Split-Path)/Functions.ps1"
[System.String] $FX_ALL_DEFS = Get-AmalgamatedScriptFunctionDefinitions -Path "$($PSCommandPath | Split-Path)/Functions.ps1"
. ([System.Management.Automation.ScriptBlock]::Create($FX_ALL_DEFS)) #The functions in Functions.ps1 are created in the current script.
Write-InfoBlue "Printed from imported function."
检查:。阶级 控制台输出 将以下内容添加到Main.ps1中,我们可以测试这3个函数
Write-Host "• TEST 1" -ForegroundColor Magenta
$FX_NAMES |
ForEach-Object {
Write-Host $_
}
Write-Host
Write-Host "• TEST 2" -ForegroundColor Magenta
foreach($value in $FX_DEFS)
{
Write-Host $value
Write-Host "███" -ForegroundColor DarkGray
}
Write-Host
Write-Host "• TEST 3" -ForegroundColor Magenta
Write-Host $FX_ALL_DEFS
控制台输出
3。额外解决方案-特殊情况 在获取函数定义时,使用它们调用不包含本地函数定义的远程计算机上的命令非常有用,我们只需获取定义并通过如下参数传递它们 如果需要在远程计算机中运行powershell命令,请安装 在远程计算机上 本地文件
PrintColorFunctions.ps1
与解决方案1的脚本内容相同 本地文件 Main.ps1
Import-Module -Name "$($PSCommandPath | Split-Path)/Functions.ps1" -Force
Write-InfoBlue "Printed from imported function."
$FX_ALL_DEFS = Get-AmalgamatedScriptFunctionDefinitions -Path "$($PSCommandPath | Split-Path)/Functions.ps1"
$R_HOST = "192.168.211.1"
$R_USERNAME = "root"
$R_PORT = "2222"
$R_SESSION = New-PSSession -HostName $R_USERNAME@$($R_HOST):$R_PORT #//Connected by OpenSSL, private key added to OpenSSH Session Agent. If you need login by password, remove the private key from OpenSSH Session Agent and write as follows user:pass@host:port $($R_USERNAME):$R_PASS@$($R_HOST):$R_PORT
Invoke-Command -ArgumentList $FX_ALL_DEFS,"Joma" -Session $R_SESSION -ScriptBlock{ #// -ArgumentList function definitions and a name.
Param($fxs, $name) #// Param received by remote context.
. ([System.Management.Automation.ScriptBlock]::Create($fxs)) #//Creating function definitions in remote script context.
Clear-Host
Write-Host "Running commands in my remote Linux Server" -ForegroundColor Green #//Powershell Core cmdlet
#//We can use Write-InfoBlue on this script context.
Write-InfoBlue ($(Get-Content /etc/*-release | Select-String -Pattern "^PRETTY_NAME=.*" ).ToString().Split("=")[1]) #//Created function + cmdlets combo
Write-InfoBlue $(uname -a) #//Created function + Native remote command
Write-InfoBlue $(whoami) #//Cmdlet + Native remote command
printf "Hello! $name" #//Native remote command
Write-InfoBlue "Local function executed in remote context"
}
Remove-PSSession -Session $R_SESSION
控制台输出
事实上,当Powershell有办法做到这一点时,为什么要重新发明轮子?我们只需将其制作成一个模块即可:
cp .\scriptFile.ps1 .\scriptfile.psm1
然后导入模块
import-module .\scriptfile.psm1
现在,获取所有函数
function SomeFunction {}
function AnotherFunction {}
get-command -module scriptfile
function SomeFunction
function AnotherFunction
如果您的
.ps1
是一个.psm1
,那么它将是一个模块,获取函数列表将与一样简单(导入模块C:\someScript.psm1-Passthru)。ExportedFunctions.Values
。(根据Martin的回答,用和$\ScriptBlock
调用。)@Jeroenmoster为什么会这样?(我们能把它的名字转换成一个临时文件并运行它吗?)。很好的技巧:-)如果您只想使用特定的函数进行简单的复制/粘贴,请使用:getchilditem函数:SomeFunction | ForEach对象{“function${”,“$..ScriptBlock,}`n}
。哇!这是一个很好的答案。不知道为什么这不是投票结果。它确实可以打印每个函数的内容,而不需要其他“积垢”。我唯一的愿望是它要短得多,而且更容易使用。我一直在寻找与Bash中的typeset-f
命令等价的东西。似乎pwsh现在正在进行一些内部字母排序。