• 解决方案 1.
如果您需要使用另一个脚本文件中的函数,可以使用 Import-Module cmdlet 导入该函数
Functions.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."
控制台输出
• 解决方案 2。
Functions.ps1 包含完整的函数。此脚本需要由主脚本导入。与 Solution1 的脚本相同。
Main.ps1
该脚本包含 3 个函数。
1. 获取-ScriptFunctionNames。它返回一个字符串数组,每个元素都是函数的名称。
2. Get-ScriptFunctionDefinitions。它返回一个String数组,每个元素都是完整的函数。
3. 获取-AmalgamatedScriptFunctionDefinitions。它只返回一个字符串,即连接函数 Get-ScriptFunctionDefinitions 返回的所有元素的结果。
所有 3 个都需要相同的参数,即 Powershell 脚本文件的路径。
我们将测试这个文件的 3 个函数。
此脚本不使用 Import-Module 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."
检查:Dot Sourcing operator.
Dot Source
ScriptBlock类
控制台输出
在 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 命令,请安装
Powershell Core 在远程计算机上。
本地文件
PrintColorFunctions.ps1
与解决方案 1 的脚本内容相同。
本地文件
Main.ps1
$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
控制台输出