是否可以在 PowerShell 中点源字符串变量?
Is it possible to dot source a string variable in PowerShell?
我知道我可以dot source一个文件:
. .\MyFunctions.ps1
但是,我想在字符串变量中点源命令:
. $myFuctions
我知道这是可能的:
.{$x=2}
并且脚本块获取后$x等于2。
但是....{$myFunctions}
不起作用。
我试过 $myFunctions | Invoke-Expression
,但它没有将源函数保留在当前范围内。我能想到的最接近的方法是将变量写入临时文件,点源文件,然后删除文件。
难免会有人问:“你想干什么?”所以这是我的用例:
我想混淆一些我打算从另一个脚本调用的函数。我不想混淆主脚本,只是我的附加功能。我有一个用户群需要根据他们的网络、目录结构和其他本地因素调整主脚本,但我不想修改某些功能。我也想保护源代码。因此,另一个问题是:保护 PowerShell 脚本代码的好方法有哪些?
我的想法是 PowerShell 将执行 Base64 编码的字符串,但仅当使用 -EncodedCommand 在命令行上传递时。
我首先想点源编码命令,但我无法弄清楚。然后我决定,如果我将 Base64 文件转换为解码字符串并点源字符串变量的值,那么它就足以满足我的目的。但是,如果不将解码后的源代码写入文件,我不知道如何对其进行点源。
能满足我的需求Import-Module -EncodedCommand .\MyEncodedFile.dat
目前无法点源字符串变量。
我的立场是正确的! . { Invoke-Expression $MyFunctions } 绝对有效!
实际上,有一种方法可以做到这一点,而您几乎已经做到了。
首先,正如您已经说过的,源或点运算符通过提供路径(作为字符串)或 script block. See also: . (source or dot operator).
来工作
因此,当尝试对字符串变量进行点源时,PowerShell 认为它是一条路径。但是,由于点源脚本块的可能性,您可以执行以下操作:
# Make sure everything is properly escaped.
$MyFunctions = "function Test-DotSourcing { Write-Host `"Worked`" }"
. { Invoke-Expression $MyFunctions }
Test-DotSourcing
并且您成功地从字符串变量点源了您的函数!
解释:
- 使用
Invoke-Expression
评估字符串并在子作用域(脚本块)中 运行。
- 然后使用
.
将评估的表达式添加到当前范围。
另请参阅:
虽然 是使用 Invoke-Expression
处理函数存储为字符串这一事实的可行方法,但下面还有其他方法似乎可以达到相同的结果。
我不crystal 清楚的一件事是作用域本身,Invoke-Expression
不会创建新的作用域,因此此时并不完全需要点源。 ..
#Define your function as a string
PS> $MyUselessFunction = "function Test-WriteSomething { 'It works!' }"
#Invoke-Expression would let you use the function
PS> Invoke-Expression $MyUselessFunction
PS> Test-WriteSomething
It works!
#Dot sourcing works fine if you use a script block
PS> $ScriptBlock = [ScriptBlock]::Create($MyUselessFunction)
PS> . $ScriptBlock
PS> Test-WriteSomething
It works!
#Or just create the function as a script block initially
PS> $MyUselessFunction = {function Test-WriteSomething { 'It works!' }}
PS> . $MyUselessFunction
PS> Test-WriteSomething
It works!
换句话说,可能有无数种方法可以得到与您想要的类似的东西 - 其中一些已记录在案,而另一些则从现有文档中推断出来。如果您的函数定义为字符串,则可能需要 Invoke-Expression
,或者您可以将它们转换为脚本块并点源。
我知道我可以dot source一个文件:
. .\MyFunctions.ps1
但是,我想在字符串变量中点源命令:
. $myFuctions
我知道这是可能的:
.{$x=2}
并且脚本块获取后$x等于2。
但是....{$myFunctions}
不起作用。
我试过 $myFunctions | Invoke-Expression
,但它没有将源函数保留在当前范围内。我能想到的最接近的方法是将变量写入临时文件,点源文件,然后删除文件。
难免会有人问:“你想干什么?”所以这是我的用例:
我想混淆一些我打算从另一个脚本调用的函数。我不想混淆主脚本,只是我的附加功能。我有一个用户群需要根据他们的网络、目录结构和其他本地因素调整主脚本,但我不想修改某些功能。我也想保护源代码。因此,另一个问题是:保护 PowerShell 脚本代码的好方法有哪些?
我的想法是 PowerShell 将执行 Base64 编码的字符串,但仅当使用 -EncodedCommand 在命令行上传递时。 我首先想点源编码命令,但我无法弄清楚。然后我决定,如果我将 Base64 文件转换为解码字符串并点源字符串变量的值,那么它就足以满足我的目的。但是,如果不将解码后的源代码写入文件,我不知道如何对其进行点源。
能满足我的需求Import-Module -EncodedCommand .\MyEncodedFile.dat
目前无法点源字符串变量。 我的立场是正确的! . { Invoke-Expression $MyFunctions } 绝对有效!
实际上,有一种方法可以做到这一点,而您几乎已经做到了。
首先,正如您已经说过的,源或点运算符通过提供路径(作为字符串)或 script block. See also: . (source or dot operator).
来工作因此,当尝试对字符串变量进行点源时,PowerShell 认为它是一条路径。但是,由于点源脚本块的可能性,您可以执行以下操作:
# Make sure everything is properly escaped.
$MyFunctions = "function Test-DotSourcing { Write-Host `"Worked`" }"
. { Invoke-Expression $MyFunctions }
Test-DotSourcing
并且您成功地从字符串变量点源了您的函数!
解释:
- 使用
Invoke-Expression
评估字符串并在子作用域(脚本块)中 运行。 - 然后使用
.
将评估的表达式添加到当前范围。
另请参阅:
虽然 Invoke-Expression
处理函数存储为字符串这一事实的可行方法,但下面还有其他方法似乎可以达到相同的结果。
我不crystal 清楚的一件事是作用域本身,Invoke-Expression
不会创建新的作用域,因此此时并不完全需要点源。 ..
#Define your function as a string
PS> $MyUselessFunction = "function Test-WriteSomething { 'It works!' }"
#Invoke-Expression would let you use the function
PS> Invoke-Expression $MyUselessFunction
PS> Test-WriteSomething
It works!
#Dot sourcing works fine if you use a script block
PS> $ScriptBlock = [ScriptBlock]::Create($MyUselessFunction)
PS> . $ScriptBlock
PS> Test-WriteSomething
It works!
#Or just create the function as a script block initially
PS> $MyUselessFunction = {function Test-WriteSomething { 'It works!' }}
PS> . $MyUselessFunction
PS> Test-WriteSomething
It works!
换句话说,可能有无数种方法可以得到与您想要的类似的东西 - 其中一些已记录在案,而另一些则从现有文档中推断出来。如果您的函数定义为字符串,则可能需要 Invoke-Expression
,或者您可以将它们转换为脚本块并点源。