是否可以在 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,或者您可以将它们转换为脚本块并点源。