为什么此脚本仅在直接从Powershell运行而不从其他脚本运行时才起作用

时间:2019-02-12 12:49:20

标签: powershell scoping strict

我正在部署在事件网格上触发的Logic App。部署后,我需要验证API连接。我找到了该脚本https://github.com/logicappsio/LogicAppConnectionAuth,并且运行正常。但是只有当我从Powershell手动运行它时。但是我想在New-AzResourceGroupDeployment命令之后,从另一个脚本(从部署Logic App的脚本)中调用该脚本。

这样做不起作用。我收到错误消息:

The variable '$Scope' cannot be retrieved because it has not been set.
At C:\location\LogicAppConnectionAuth.ps1:16 char:113
+ ... Browser -Property @{Width=580;Height=780;Url=($url -f ($Scope -join " ...
+                                                            ~~~~~~
    + CategoryInfo          : InvalidOperation: (Scope:String) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : VariableIsUndefined

$ scope变量是什么?脚本中未定义它,但单独运行时它仍然存在,但是当我从另一个脚本中运行该脚本时却没有。

2 个答案:

答案 0 :(得分:1)

you've discovered一样,在您的特定情况下,此问题是正常的良性错误,由于 caller 启用严格模式而浮出水面。但是,这个问题是一个根本性的问题,如下所述。


潜在的问题是,从v6.2开始, PowerShell的严格模式是动态范围的,而不是词法上的

这意味着使用 Set-StrictMode不仅会影响调用该函数的功能或脚本,还会影响其他称为 from的功能和脚本驻留在同一作用域内的功能或脚本 ,也就是说,如果调用方和被调用方都在外部定义了或在 same 模块中定义。

换句话说:脚本或函数可能不经意间继承严格模式设置,并且可能 break (如果未设计)该模式。

例如,被调用方可以假定严格模式为默认模式-Off,并依靠(宽松地)使用$var测试变量if (-not $var)的不存在, 例如。如果同一作用域域中的呼叫者设置了Set-StrictMode -Version 1或更高级别,则被呼叫者将中断。

解决方法

  • 如果控制所调用的脚本或函数

    • 在您的脚本或函数开始处明确调用Set-StrictMode ,采用您的代码设计方式。

      • 鉴于所描述的行为,在非模块脚本和功能中作为习惯问题是值得做的
    • 注意:请记住,此模式对于从您手中的脚本或函数内部调用的同一个作用域域中的脚本/函数以及它们的脚本/函数也同样有效。 em>通话。 (相比之下,调用堆栈上的 higher 代码不会受到影响。)

  • 否则

    • 暂时禁用严格模式,以便调用希望关闭严格模式(或较低版本)的脚本或函数:

      # Temporarily turn strict mode off.
      Set-StrictMode -Off
      
      # Call the script or function that breaks with (a higher) strict mode in effect
      ...
      
      # Re-enable strict mode for your code.
      # Note that there's no way to *get* (and save for later restoring)
      # the specific mode in effect.
      Set-StrictMode -Version <n> 
      

未来前景

This RFC建议引入 lexical 范围严格的模式,以避免当前行为出现问题。

答案 1 :(得分:0)

似乎$ scope变量由于某些复制粘贴错误而存在。不会在任何地方声明,设置或读取它。导致错误的原因是在StrictMode 3中运行调用脚本。删除该错误会删除该错误,但这并不是真正的解决方案。

我在github仓库中发布了一个问题,并通过将$ scope变量声明为空字符串来修复了自己的解决方案。