powershell - कस्टम cmdlet में-verbose और-debug पैरामीटर का सही तरीके से उपयोग कैसे करें




parameters cmdlets (6)

आप अपनी स्क्रिप्ट शुरू करने पर VerbosePreference को वैश्विक चर के रूप में सेट कर सकते हैं और फिर अपने कस्टम cmdlet में वैश्विक चर की जांच कर सकते हैं।

स्क्रिप्ट:

$global:VerbosePreference = $VerbosePreference
Your-CmdLet

आपका-cmdlet:

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

'जारी रखें' के लिए स्पष्ट रूप से जांचना स्क्रिप्ट को -verbose:$false बराबर होने की अनुमति देता है -verbose:$false जब आप CmdLet को उस स्क्रिप्ट से कॉल करते हैं जो वैश्विक चर सेट नहीं करता है (जिस स्थिति में यह $null )

डिफ़ॉल्ट रूप से, किसी भी नामित फ़ंक्शन जिसमें [सीएमडीलेट बाइंडिंग ()] विशेषता है -debug और -verbose (और कुछ अन्य) पैरामीटर स्वीकार करता है और $ डीबग और $ verbose चर को पूर्वनिर्धारित करता है। जो मैं समझने की कोशिश कर रहा हूं वह यह है कि उन्हें अन्य cmdlet पर कैसे पास किया जाए, जिसे फ़ंक्शन के भीतर बुलाया जाता है।

मान लें कि मेरे पास एक cmdlet है:

function DoStuff() {
   [CmdletBinding()]

   PROCESS {
      new-item Test -type Directory 
   }
}

अगर -debug या -verbose मेरे समारोह में पारित किया गया था, मैं उस ध्वज को new-item cmdlet में पास करना चाहता हूं। ऐसा करने के लिए सही पैटर्न क्या है?


आप बाध्य डीबग या वर्बोज़ पैरामीटर के आधार पर एक नई हैश तालिका बना सकते हैं और फिर इसे आंतरिक कमांड में विभाजित कर सकते हैं। यदि आप केवल स्विच निर्दिष्ट कर रहे हैं (और एक झूठी स्विच नहीं दे रहे हैं, जैसे $ डीबग: $ झूठी) आप केवल डीबग या वर्बोज़ के अस्तित्व की जांच कर सकते हैं:

function DoStuff() { 
   [CmdletBinding()] 

   PROCESS { 
        [email protected]{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}
   [email protected]{Verbose=$v;Debug=$d} 
   new-item Test -type Directory @HT 
   }  
}  

कोई जरूरत नहीं है। 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

यह अगली cmdlet को पास होने के रूप में सीधे के रूप में नहीं किया जाता है। यह $ DebugPreference और $ VerbrosePreference चर के माध्यम से किया जाता है। लिखित-डीबग और लिखें-वर्बोज़ अधिनियम जैसा आप उम्मीद करेंगे, लेकिन यदि आप डीबग या वर्बोज़ के साथ कुछ अलग करना चाहते हैं तो आप here पढ़ सकते हैं कि स्वयं को कैसे जांचें।


पुनर्जीवित करने और पुराने धागे के जोखिम के साथ। मेरा समाधान यहाँ है।

function DoStuff {
    [CmdletBinding()]
    param ()

    BEGIN
    {
    [email protected]{
        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 / -Debug को सत्य पर सेट करेगा:

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

शायद यह अजीब लगता है लेकिन 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 स्तर मान) तो $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 माध्यम से बाध्य पैरामीटर तक पहुंच सकते हैं। यहां एक ऐसा फ़ंक्शन है जो सीएमडीलेट बाइंडिंग का उपयोग करता है और फ़ंक्शन स्कोप के अंदर उपलब्ध चरों की जांच करने के लिए तुरंत एक नेस्टेड प्रॉम्प्ट में प्रवेश करता है।

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)
    }
}

यह कवर-वेर्बोस, -वर्बोस: $ झूठा, -वर्बोस: $ सच, और वह मामला जहां स्विच बिल्कुल मौजूद नहीं है।





cmdlet