默认情况下,任何具有[cmdletBinding()]属性的任何命名函数接受-debug和-verbose(以及其他一些)参数,并且具有预定义的$ debug和$ debug和$ verbose变量。我要弄清楚的是如何将它们传递到在功能中被调用的其他CMDLET。

假设我有这样的cmdlet:

function DoStuff() {
   [CmdletBinding()]

   PROCESS {
      new-item Test -type Directory 
   }
}

如果 -debug 或者 -verbose 被传递到我的功能中,我想传递该标志 new-item cmdlet。正确执行此操作的模式是什么?

有帮助吗?

解决方案

也许听起来很奇怪,但是CMDLET没有简单的方法知道其冗长或调试模式。看一个相关的问题:

cmdlet如何知道何时应该调用writeverbose()?

一个不是完美的,但实际上合理的选择是引入您自己的CMDLET参数(例如 $MyVerbose, $MyDebug)并明确使用它们。

function DoStuff {
    [CmdletBinding()]
    param
    (
        # unfortunately, we cannot use Verbose name with CmdletBinding
        [switch]$MyVerbose
    )

    process {

        if ($MyVerbose) {
            # do verbose stuff
        }

        # pass $MyVerbose in the cmdlet explicitly
        New-Item Test -Type Directory -Verbose:$MyVerbose
    }
}

DoStuff -MyVerbose 

更新

当我们只需要一个开关(不像词曲级值)时, $PSBoundParameters 也许比提议的额外参数更好:

function DoStuff {
    [CmdletBinding()]
    param()

    process {
        if ($PSBoundParameters['Verbose']) {
            # do verbose stuff
        }

        New-Item Test -Type Directory -Verbose:($PSBoundParameters['Verbose'] -eq $true)
    }
}

DoStuff -Verbose

无论如何,一切都不是完美的。如果有更好的解决方案,那么我真的很想自己认识他们。

其他提示

$PSBoundParameters 不是您想要的。使用 [CmdletBinding()] 属性允许使用 $PSCmdlet 在您的脚本中,除了提供详细标志。实际上,您应该使用的是相同的详细信息。

通过 [CmdletBinding()], ,您可以通过 $PSCmdlet.MyInvocation.BoundParameters. 。这是一个使用cmdletbinding的函数,并简单地立即输入嵌套的提示符,以便检查功能范围内的可用变量。

PS D:\> function hi { [CmdletBinding()]param([string] $Salutation) $host.EnterNestedPrompt() }; hi -Salutation Yo -Verbose

PS D:\>>> $PSBoundParameters

____________________________________________________________________________________________________
PS D:\>>> $PSCmdlet.MyInvocation.BoundParameters

Key Value                                                                                                                                                                                                           
--- -----                                                                                                                                                                                                           
Salutation Yo                                                                                                                                                                                                              
Verbose   True                                                                                       

因此,在您的示例中,您需要以下内容:

function DoStuff `
{
    [CmdletBinding()]
    param ()
    process
    {
      new-item Test -type Directory `
        -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true)
    }
}

这涵盖了-verbose,-verbose:$ false,-verbose:$ true,以及完全不存在开关的情况。

没有必要。 PowerShell已经这样做,如下所示。

function f { [cmdletbinding()]Param()    
    "f is called"
    Write-Debug Debug
    Write-Verbose Verbose
}
function g { [cmdletbinding()]Param() 
    "g is called"
    f 
}
g -Debug -Verbose

输出是

g is called
f is called
DEBUG: Debug
VERBOSE: Verbose

它并不像传递-Debug到下一个CMDLET那样直接。它是通过$ debugpreference和$ derbrosepreference变量完成的。写入和写作的动作就像您期望的那样,但是如果您想对调试或冗长做一些不同的事情,您可以阅读 这里 如何检查自己。

有恢复和旧线程的风险。这是我的解决方案。

function DoStuff {
    [CmdletBinding()]
    param ()

    BEGIN
    {
    $CMDOUT=@{
        Verbose=If ($PSBoundParameters.Verbose -eq $true) { $true } else { $false };
        Debug=If ($PSBoundParameters.Debug -eq $true) { $true } else { $false }
    }
    } # BEGIN ENDS

    PROCESS
    {
    New-Item Example -ItemType Directory @CMDOUT
    } # PROCESS ENDS

    END
    {
    } #END ENDS
}

与其他示例不同的是,它将重复“ -verbose:$ false”或“ -debug:$ false”。如果您使用以下内容,它将仅将-verbose/-debug设置为$ true:

DoStuff -Verbose
DoStuff -Verbose:$true
DoStuff -Debug
DoStuff -Debug:$true

您可以根据界限或详细参数构建新的哈希表,然后将其插入内部命令。如果您只是指定开关(并且不传递错误的开关,例如$ debug:$ false),您只需检查debug或冗长的存在:

function DoStuff() { 
   [CmdletBinding()] 

   PROCESS { 
        $HT=@{Verbose=$PSBoundParameters.ContainsKey'Verbose');Debug=$PSBoundParameters.ContainsKey('Debug')}
      new-item Test -type Directory @HT
   } 
} 

如果要传递参数值,则更复杂,但可以完成:

function DoStuff {  
   [CmdletBinding()]  
   param()
   PROCESS {  
   $v,$d = $null
   if(!$PSBoundParameters.TryGetValue('Verbose',[ref]$v)){$v=$false}
   if(!$PSBoundParameters.TryGetValue('Debug',[ref]$d)){$d=$false}
   $HT=@{Verbose=$v;Debug=$d} 
   new-item Test -type Directory @HT 
   }  
}  

最好的方法是设置 $VerbosePreference. 。这将使整个脚本启用详细级别。不要忘记在脚本末尾禁用它。

Function test
{
  [CmdletBinding()]
   param( $param1)


  if($psBoundParameters['verbose'])
  {
     $VerbosePreference = "Continue"
     Write-verbose " Verbose mode is on"
   }
  else
   {
     $VerbosePreference = "SilentlyContinue"
     Write-verbose " Verbose mode is Off"
    }
   <<your code>>
   }

您可以在启动脚本时将VerbosePreference设置为全局变量,然后检查自定义CMDLET中的全局变量。

脚本:

$global:VerbosePreference = $VerbosePreference
Your-CmdLet

您的CMDLET:

if ($global:VerbosePreference -eq 'Continue') {
   # verbose code
}

明确检查“继续”允许脚本等于 -verbose:$false 当您从未设置全局变量的脚本调用cmdlet时(在这种情况下是 $null)

我认为这是最简单的方法:

Function Test {
    [CmdletBinding()]
    Param (
        [parameter(Mandatory=$False)]
        [String]$Message
    )

    Write-Host "This is INFO message"

    if ($PSBoundParameters.debug) {
        Write-Host -fore cyan "This is DEBUG message"
    }

    if ($PSBoundParameters.verbose) {
        Write-Host -fore green "This is VERBOSE message"
    }

    ""
}
Test -Verbose -Debug
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top