Pet*_*ete 4 arrays powershell expression
我有很多这样的字符串,我希望 powershell 重新评估\转换为数组(就像如果您在 ISE 中编写不带单引号的相同代码会发生什么)。
$String = '@("a value","b value","c value")'
有没有比从字符串中删除“@”和“()”并使用 -split 更简单的方法?
我在这里先向您的帮助表示感谢。
只要字符串包含有效的表达式,就可以使用以下[scriptblock]::Create(..)方法:
$String = '@("a value","b value","c value")'
& ([scriptblock]::Create($String))
Run Code Online (Sandbox Code Playgroud)
Invoke-Expression也会起作用,在这种情况下基本上是相同的事情。
然而,正如zett42 在评论中指出的那样,脚本块的一个很好的功能是,使用它们我们可以验证其CheckRestrictedLanguage方法是否禁止任意代码执行。
在下面的示例中,Write-Host是一个允许的命令,并且包含 only 的字符串'Write-Host "Hello world!"'不会引发异常,但是,赋值语句或未列出的任何其他命令$allowedCommands将引发异常,并且脚本块将不会被执行。
$String = @'
Write-Host "Hello world!"
$stream = [System.Net.Sockets.TcpClient]::new('google.com', 80).GetStream()
'@
[string[]] $allowedCommands = 'Write-Host'
[string[]] $allowedVaribales = ''
try {
$scriptblock = [scriptblock]::Create($String)
$scriptblock.CheckRestrictedLanguage(
$allowedCommands,
$allowedVaribales,
$false # Argument to allow Environmental Variables
)
& $scriptblock
}
catch {
Write-Warning $_.Exception.Message
}
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用Mode在运行空间中运行表达式。这个功能可以让事情变得非常简单。ConstrainedLanguage
using namespace System.Management.Automation.Language
using namespace System.Collections.Generic
using namespace System.Management.Automation.Runspaces
function Invoke-ConstrainedExpression {
[CmdletBinding(DefaultParameterSetName = 'ScriptBlock')]
param(
[Parameter(ParameterSetName = 'Command', Mandatory, ValueFromPipeline, Position = 0)]
[string] $Command,
[Parameter(ParameterSetName = 'ScriptBlock', Mandatory, Position = 0)]
[scriptblock] $ScriptBlock,
[Parameter()]
[Management.Automation.PSLanguageMode] $LanguageMode = 'ConstrainedLanguage',
# When using this switch, the function inspects the AST to find any variable
# not being an assigned one in the expression, queries the local state to find
# it's value and injects that variable to the Initial Session State of the Runspace.
[Parameter()]
[switch] $InjectLocalVariables
)
process {
try {
$Expression = $ScriptBlock
if($PSBoundParameters.ContainsKey('Command')) {
$Expression = [scriptblock]::Create($Command)
}
# bare minimum for the session state
$iss = [initialsessionstate]::CreateDefault2()
# set `ContrainedLanguage` for this session
$iss.LanguageMode = $LanguageMode
if($InjectLocalVariables.IsPresent) {
$ast = $Expression.Ast
$map = [HashSet[string]]::new([StringComparer]::InvariantCultureIgnoreCase)
$ast.FindAll({ $args[0] -is [AssignmentStatementAst] }, $true).Left.Extent.Text |
ForEach-Object { $null = $map.Add($_) }
$variablesToInject = $ast.FindAll({
$args[0] -is [VariableExpressionAst] -and
-not $map.Contains($args[0].Extent.Text)
}, $true).VariablePath.UserPath
foreach($var in $variablesToInject) {
$value = $ExecutionContext.SessionState.PSVariable.GetValue($var)
$entry = [SessionStateVariableEntry]::new($var, $value, '')
$iss.Variables.Add($entry)
}
}
# create the PS Instance and add the expression to invoke
$ps = [powershell]::Create($iss).AddScript($Expression)
# invoke the expression
[Collections.Generic.List[object]] $stdout = $ps.Invoke()
$streams = $ps.Streams
$streams.PSObject.Properties.Add([psnoteproperty]::new('Success', $stdout))
$streams
}
finally {
if($ps) { $ps.Dispose() }
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以使用约束语言测试表达式:
Invoke-ConstrainedExpression {
Write-Host 'Starting script'
[System.Net.WebClient]::new().DownloadString($uri) | iex
'Hello world!'
}
Run Code Online (Sandbox Code Playgroud)
输出如下所示:
Success : {Hello world!}
Error : {Cannot create type. Only core types are supported in this language mode.}
Progress : {}
Verbose : {}
Debug : {}
Warning : {}
Information : {Starting script}
Run Code Online (Sandbox Code Playgroud)
开发博客文章:PowerShell 约束语言模式有一些不错的信息,绝对值得一读。