PowerShell" ="不是可识别的cmdlet错误

时间:2017-09-05 13:54:26

标签: powershell invoke-command scriptblock

除了这里给出的回复: PowerShell Enter Session find path bug 之外,我还在我的剧本中找到了另一面我无法解决的问题。以下脚本返回错误:

  

术语' ='不被识别为cmdlet,函数,脚本文件或可操作程序的名称。检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试。

$sb = [ScriptBlock]::Create(@"
$Acl = (Get-Item -path D:\Websites\$Sitename).GetAccessControl('Access')
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule('BUILTIN\IIS_IUSRS', 'Modify', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
$Acl.SetAccessRule($Ar)
Set-Acl -path $Path -AclObject $Acl
"@)

Invoke-Command -Session $Session -ScriptBlock $sb

我可以创建脚本块变量($ sb),但是当我调用它时,我得到了错误。我已将其缩小到$Acl变量的设置,并尝试重写各种方法,没有运气。我错过了什么?

1 个答案:

答案 0 :(得分:2)

当你使用双引号here-string时,它的行为就像一个普通的双引号字符串 - 解析器将评估和扩展引号之间的任何变量或子表达式。

由于scriptblock定义中的变量在定义上下文中不存在,因此您最终会得到一个带有以下定义的scriptblock:

 = (Get-Item -path D:\Websites\).GetAccessControl('Access')
 = New-Object System.Security.AccessControl.FileSystemAccessRule('BUILTIN\IIS_IUSRS', 'Modify', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
.SetAccessRule()
Set-Acl -path  -AclObject 

正如您所看到的,前两个语句的开头只有一个裸=作为第一个非空格字符,这就是您看到错误的原因。

切换到单引号here-string:

$sb = [ScriptBlock]::Create(@'
$Acl = (Get-Item -path D:\Websites\$Sitename).GetAccessControl('Access')
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule('BUILTIN\IIS_IUSRS', 'Modify', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
$Acl.SetAccessRule($Ar)
Set-Acl -path $Path -AclObject $Acl
'@)

如果您需要从定义范围传递变量值,我建议在scriptblock中定义param块:

$sb = [ScriptBlock]::Create(@'
param($Sitename)
$Acl = (Get-Item -path D:\Websites\$Sitename).GetAccessControl('Access')
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule('BUILTIN\IIS_IUSRS', 'Modify', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
$Acl.SetAccessRule($Ar)
Set-Acl -path $Path -AclObject $Acl
'@)
 Invoke-Command -Session $Session -ScriptBlock $sb -ArgumentList $Sitename

或使用-f字符串格式运算符在创建scriptblock之前将其替换为字符串:

$sb = [ScriptBlock]::Create(@'
$Acl = (Get-Item -path D:\Websites\{0}).GetAccessControl('Access')
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule('BUILTIN\IIS_IUSRS', 'Modify', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
$Acl.SetAccessRule($Ar)
Set-Acl -path $Path -AclObject $Acl
'@ -f $Sitename)

有关引用和变量扩展的详细信息,请参阅about_Quoting_Rules help topic