代码之家  ›  专栏  ›  技术社区  ›  Roman Kuzmin

cmdlet如何知道何时真正应该调用WriteVerbose()?

  •  6
  • Roman Kuzmin  · 技术社区  · 14 年前

    cmdlet如何知道 真正地 应该打电话 WriteVerbose() WriteDebug() 等等。?

    到目前为止我看到的实现只是调用 犹豫。我知道是的 .

    的数据 WriteVerbose() 打电话,也就是说,白费。

    换句话说,在cmdlet中,我希望能够:

    if (<VerboseMode>)
    {
        .... data preparation, sometimes expensive ...
        WriteVerbose(...);
    }
    

    但我不知道怎么弄到这个 if (<VerboseMode>) . 有什么想法吗?


    结论: @stejs答案说明了如何从理论上获得所需的信息。在实践中,这是老套的,不太合适。因此,如果cmdlet产生非常昂贵的详细或调试输出,那么引入一个指定详细级别的附加参数似乎是合理的。

    3 回复  |  直到 14 年前
        1
  •  7
  •   stej    14 年前

    这是我们的方法 System.Management.Automation.MshCommandRuntime

    internal void WriteVerbose(VerboseRecord record)
    {
        if ((this.Host == null) || (this.Host.UI == null))
        {
            tracer.TraceError("No host in CommandBase.WriteVerbose()", new object[0]);
            throw tracer.NewInvalidOperationException();
        }
        ActionPreference verbosePreference = this.VerbosePreference;
        if (this.WriteHelper_ShouldWrite(verbosePreference, this.lastVerboseContinueStatus))
        {
            if (record.InvocationInfo == null)
            {
                record.SetInvocationInfo(this.MyInvocation);
            }
            this.CBhost.InternalUI.WriteVerboseRecord(record);
        }
        this.lastVerboseContinueStatus = this.WriteHelper(null, null, verbosePreference, this.lastVerboseContinueStatus, "VerbosePreference");
    }
    

    MshCommandRuntime 实现接口 ICommandRuntime 它不知道任何细节:|(通过反射器找到)。实例 MshCommandRuntime命令 应提供 Cmdlet ( public ICommandRuntime CommandRuntime { get; set; }

    所以应该可以铸造属性 CommandRuntime MshCommandRuntime命令


    我完全同意应该有一个简单的方法来找到它。除此之外,编译器应该足够聪明,不会在这样的情况下计算某些字符串:

    $DebugPreference = 'SilentlyContinue'
    $array = 1..1000
    Write-Debug "my array is $array"
    

    输入到 Write-Debug 不会被使用,所以 $array 不应在传递的字符串中计算(可以测试它是否真的是这样评估的: Write-Debug "my array is $($array|%{write-host $_; $_})"

        2
  •  5
  •   serialhobbyist    11 年前

    怎么样:

    BEGIN {
        if ($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent) {
            $HasDebugFlag = $true
        }
    
        if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
            $HasVerboseFlag = $true
        }
    }
    PROCESS {
        if ($HasVerboseFlag) {
            expensive_processing
        }
    }
    

        3
  •  5
  •   Community Alex Howansky    7 年前

    因此,我们不仅要考虑cmdlet的公共参数-Debug和-Verbose,还要考虑全局$DebugPreference和$VerbosePreference标志,以及从另一个cmdlet调用cmdlet时继承这些公共参数的事实。

    它可以在不破坏内部结构的情况下完成。

    This answer 向您展示了它可以在PowerShell cmdlet中轻松完成。

    function f { [cmdletbinding()]Param() 
        $debug = $DebugPreference -ne 'SilentlyContinue'
        $verbose = $VerbosePreference -ne 'SilentlyContinue'
        "f is called"
        "    `$debug = $debug"
        "    `$verbose = $verbose"
    }
    function g { [cmdletbinding()]Param() 
        "g is called"
        f 
    }
    f
    f -Debug -Verbose
    g
    g -Debug -Verbose
    

    从C#我们必须检查这两个全局标志,而且还要检查公共参数。确保从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;