在标记化作业步骤中处理“找不到变量”

jim*_*gee 5 sql-server powershell sql-server-agent

我有一个代理作业,通常由 WMI 事件触发。该作业中有一个令牌,它会自动从 WMI 事件中获取一个值并将其替换为该步骤的 Powershell 代码,例如:

$alert_wmi_state = '$(ESCAPE_SQUOTE(WMI(State)))';
Run Code Online (Sandbox Code Playgroud)

SQL 代理配置为选中所有作业响应警报设置的替换令牌,因此,当 WMI 事件触发时,替换会正常发生,并且运行的代码为:

$alert_wmi_state = '7';
Run Code Online (Sandbox Code Playgroud)

但是,该作业有可能手动运行(即右键单击,在步骤中启动作业...),并且我希望我的步骤代码能够优雅地处理此问题,因此我在步骤中进一步采用了以下逻辑:

if ($alert_wmi_state -eq ('$' + '(ESCAPE_SQUOTE(WMI(State)))')) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

...理论是,$从 中分离(ESCAPE_SQUOTE...将合理地意味着这不被识别为令牌,因此不会被替换,因此测试将按字面意思读取:

if ($alert_wmi_state -eq '$(ESCAPE_SQUOTE(WMI(State)))') {
    ...
}
Run Code Online (Sandbox Code Playgroud)

但是,手动运行作业时,在运行我的任何代码之前,SQL 代理总是会在该步骤中出错(无论它是配置为CmdExec作业步骤类型还是PowerShell作业步骤类型),并显示错误Variable WMI(State) not found

我的猜测是,这是因为替换ESCAPE_SQUOTE发生步骤代码实际解析/加载之前,因此代理永远不会运行该步骤。

我希望我可以有两个步骤,一个带有令牌,一个没有,并且让标记化步骤的失败操作启动非标记化步骤,但是步骤代码的重复是不可取的。

所以,我的问题是,有什么方法可以优雅地处理步骤代码中不存在步骤令牌的情况吗?

Bac*_*its 1

在脚本中使用PowerShell here-string会阻止需要 吗ESCAPE_SQUOTE

$alert_wmi_state = @'
$(WMI(State))
'@
Run Code Online (Sandbox Code Playgroud)

这至少应该让您确定问题是否在于ESCAPE_SQUOTE引发错误,或者是否是 SQL 代理的标记解析器本身在抱怨。

只要 SQL 代理不是真正以'@您开头就应该没问题。如果它确实以 开头'@,您可以轻松修复该问题:

$alert_wmi_state = @'
_$(WMI(State))
'@.Substring(1)
Run Code Online (Sandbox Code Playgroud)

请注意,您通常希望使用@'...'@and not @"..."@,因为后者仍由 PowerShell 计算,就像双引号字符串一样。