在Cmdlet中,我如何检测是否设置了调试标志(Debug flag)?

5
我正在编写一个PowerShell Cmdlet,并使用WriteDebug,但我想写一个需要额外API调用的对象,当关闭调试时,我不想进行那个调用。如何检测是否设置了Debug标志,以便我可以完全跳过对WriteDebug的调用呢?
例如,我的WriteDebug调用将类似于这样:
WriteDebug(string.Format("Name : {0}", api.GetName(myobj)));

在这个例子中,我希望除非调试被打开,否则避免调用 api.GetName

根据stej对类似问题的回答,我猜测没有直接的方法从cmdlet中获取$DebugPreference的当前值。 - Emperor XLII
4个回答

5

只检查是否设置了-Debug标志可以使用以下代码,但这还不够。

bool debug = false;
bool containsDebug = MyInvocation.BoundParameters.ContainsKey("Debug");
if (containsDebug)
    debug = ((SwitchParameter)MyInvocation.BoundParameters["Debug"]).ToBool();

PowerShell还允许您设置一个名为$DebugPreference的全局标志,上面的代码没有检查。调用另一个cmdlet的cmdlet会继承这些常见参数,而不是通过上面的Debug标志继承。下面的代码将检查$DebugPreference并解决这些问题。
debug = (ActionPreference)GetVariableValue("DebugPreference") != ActionPreference.SilentlyContinue;

不幸的是,与PowerShell中的cmdlet相反,您必须同时检查两者。因此,最终的C#代码如下所示。我还添加了Verbose常见参数的代码作为奖励。请确保继承自PSCmdlet而不是Cmdlet以使用GetVariableValue方法。

bool debug = false;
bool containsDebug = MyInvocation.BoundParameters.ContainsKey("Debug");
if (containsDebug)
    debug = ((SwitchParameter)MyInvocation.BoundParameters["Debug"]).ToBool();
else
    debug = (ActionPreference)GetVariableValue("DebugPreference") != ActionPreference.SilentlyContinue;

bool verbose = false;
bool containsVerbose = MyInvocation.BoundParameters.ContainsKey("Verbose");
if (containsVerbose)
    verbose = ((SwitchParameter)MyInvocation.BoundParameters["Verbose"]).ToBool();
else
    verbose = (ActionPreference)GetVariableValue("VerbosePreference") != ActionPreference.SilentlyContinue; 

4

试试这个:

$Debug = $psboundparameters.debug.ispresent


if ($Debug){
  Write-Debug(string.Format("Name : {0}", api.GetName(myobj))
  }

+1 - 你有没有一个好的链接可以解释一下 $psboundparameters 的这种神奇用法?谢谢! - CB.
谢谢!不幸的是,不行。我只是运行了一些测试函数,并检查了-debug开关在绑定中如何显示。 - mjolinor
我该如何从C#中访问它?我正在编写一个扩展PSCmdlet的C#类,而不是脚本cmdlet。 - Ricket
1
$psboundparameters的用法在about_Automatic_Variables中有描述。 - JPBlanc
3
这种方法存在的问题是Debug设置会被继承,但其在psboundparameters中的存在并不会被继承。(很抱歉,我没有任何有建设性的贡献可以提供。) - OldFart
显示剩余2条评论

3

实验表明,您可能需要查看$DebugPreference变量。我已经尝试在高级函数中使用它,但在cmdlet中同样适用。

请尝试以下命令序列:

function f { [cmdletbinding()]Param() $DebugPreference }
function g { [cmdletbinding()]Param() f }
f
f -Debug
g
g -Debug

2
从C#中访问Debug标志,您应该能够基本上像mjolinor建议的那样做:
if (this.MyInvocation.BoundParameters.ContainsKey("Debug"))
{
    ... do something ...
}

然而,请注意您可以将debug参数指定为false的值:
MyCmdlet -Debug:$false

处理此案例,您可能希望在 PSCmdlet 中添加类似以下内容的代码:
bool debug = MyInvocation.BoundParameters.ContainsKey("Debug") &&
             ((SwitchParameter)MyInvocation.BoundParameters["Debug"]).ToBool();

在C#中,BoundParameters是一个字典,因此您也可以使用TryGetValue()方法,但请注意,像Debug这样的开关的值是SwitchParameter而不是bool。
有关更多信息,请参见以下内容:

如果从另一个 cmdlet 调用 cmdlet 并且不考虑 $DebugPreference,则此方法无效。 - Lars Truijens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接