首页 > 解决方案 > 为什么此脚本仅在直接从 powershell 运行而不是从另一个脚本运行时才有效

问题描述

我正在部署一个在事件网格上触发的逻辑应用程序。部署后,我需要对 API 连接进行身份验证。我找到了这个脚本https://github.com/logicappsio/LogicAppConnectionAuth并且工作正常。但前提是我从 Powershell 手动运行它。但我想在 New-AzResourceGroupDeployment 命令之后从另一个脚本调用该脚本,从部署逻辑应用的脚本。

这样做是行不通的。我得到错误:

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 变量是什么?它没有在脚本中定义,单独运行时仍然存在,但当我从另一个脚本运行脚本时不存在。

标签: powershellscopingstrict

解决方案


正如您所发现的,在您的特定情况下,问题是由于调用者启用严格模式而出现的通常良性错误。然而,这个问题是一个基本问题,如下所述。


根本问题是,从 v6.2 开始,PowerShell 的严格模式是动态作用域的,而不是词法上的

这意味着 usingSet-StrictMode不仅会影响调用它的函数或脚本,还会影响该函数或脚本调用的位于同一作用域域中的其他函数和脚本,也就是说,如果调用者和被调用者都是在模块外部定义或在同一模块中定义。

换句话说:一个脚本或函数可能会在不知不觉中继承严格模式设置并且可能会中断,如果它不是为该模式设计的。

例如,被调用者可能假设严格模式是默认的-Off,并且依赖(松散地)测试变量的不存在$varif (-not $var)例如。如果同一作用域域中的调用者已Set-StrictMode -Version 1设置或更高设置,则被调用者将中断。

解决方法

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

    • Set-StrictMode在脚本或函数的开头以代码设计的模式显式调用。

      • 鉴于所描述的行为,作为非模块脚本和函数中的习惯问题,这样做是值得的。
    • 注意:请记住,此模式也适用于从手头的脚本或函数中调用的同一作用域域中的脚本/函数,以及它们调用的脚本/函数。(相比之下,调用堆栈更高的代码不受影响)。

  • 否则

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

      # 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> 
      

未来展望

这个 RFC建议引入一个词法范围的严格模式来避免当前行为的问题。


推荐阅读