2010-12-28 6 views
10

क्या पावरशेल फ़ंक्शन निर्धारित कर सकता है कि यह पाइपलाइन के हिस्से के रूप में चलाया जा रहा है या नहीं? मेरे पास एक ऐसा फ़ंक्शन है जो FileInfo के उदाहरणों के साथ एक सरणी को पॉप्युलेट करता है जिसे मैं पाइपलाइन पर "उपज" करना चाहता हूं यदि फ़ंक्शन इस तरह से चल रहा है या कुछ सुंदर आउटपुट उत्पन्न करता है यदि फ़ंक्शन को कमांड लाइन से स्वयं ही बुलाया जा रहा है।क्या मैं निर्धारित कर सकता हूं कि पाइपलाइन के हिस्से के रूप में PowerShell फ़ंक्शन चल रहा है या नहीं?

function Do-Something { 
    $file_infos = @() 
    # Populate $file_infos with FileInfo instances... 

    if (INVOKED_IN_PIPELINE) { 
     return $file_infos 
    } 
    else { 
     foreach ($file_info in $file_infos) { 
      write-host -foregroundcolor yellow $file_info.fullname 
     } 
    } 
} 

असल में, मैं यह पता लगाने INVOKED_IN_PIPELINE लागू करने के लिए कैसे करने के लिए कोशिश कर रहा हूँ। यदि यह एक पाइपलाइन में चलाया जाता है (उदा। Do-Something | format-table fullname), तो मैं केवल सरणी उत्पन्न करूंगा, लेकिन यदि सीधे चलाया जाता है (उदा। Do-Something), तो यह कंसोल में सरणी की सामग्री को बहुत प्रिंट करेगा।

क्या ऐसा करने का कोई तरीका है? यदि इस तरह की चीज़ों को हासिल करने के लिए एक और "मूर्ख" तरीका है, तो मुझे भी जानना होगा।

+1

ऐसा क्यों downvoted किया गया था।? –

उत्तर

14

यह जानकारी $ PSCmdlet.MyInvocation के हिस्से के रूप में उपलब्ध है। यहां एक cmdlet है जिसका उपयोग आप इसके साथ प्रयोग करने के लिए कर सकते हैं। किसी भी कमांड निष्पादन के लिए उस संपत्ति की सामग्री को लिखने के लिए यह क्या होता है और फिर ऑब्जेक्ट पर गुजरता है (ताकि आप बड़ी पाइपलाइनों के साथ ऑब्जेक्ट्स को और अधिक कुशल बना सकें)। आप देखेंगे कि PipelineLength नामक एक संपत्ति है जो 1 के बराबर होती है जब आप यह आदेश स्वयं चलाते हैं और पाइपलाइन में प्रत्येक आइटम के लिए बढ़ते हैं। PipelinePosition भी ध्यान दें। यह आपको बताता है कि यह स्थिति कमांड पाइपलाइन में है।

नोट: जब आप एक उन्नत समारोह लिखने$PSCmdlet ही उपलब्ध है (उदाहरण के लिए [CmdletBinding()] विशेषता यहाँ कुछ उदाहरण हैं

function test-PSCmdlet 
{ 
[CmdletBinding()] 
param(
[Parameter(ValueFromPipeline=$true)] 
$test 
) 
Begin{ 
    $once = $false 
    } 
process 
    { 
     if (!$once) 
     { 
      write-host ($PSCmdlet.MyInvocation |out-string) 
      $once = $true 
     } 
     Write-Output $_ 
    } 
} 

:

PS C:\Users\jsnover.NTDEV> test-PSCmdlet 

MyCommand  : test-PSCmdlet 
BoundParameters : {} 
UnboundArguments : {} 
ScriptLineNumber : 1 
OffsetInLine  : 14 
HistoryId  : 61 
ScriptName  : 
Line    : test-PSCmdlet 
PositionMessage : 
        At line:1 char:14 
        + test-PSCmdlet <<<< 
InvocationName : test-PSCmdlet 
PipelineLength : 1 
PipelinePosition : 1 
ExpectingInput : False 
CommandOrigin : Runspace 


PS C:\Users\jsnover.NTDEV> gps lsass | test-PSCmdlet |Format-table Name,Id -auto 

MyCommand  : test-PSCmdlet 
BoundParameters : {[test, System.Diagnostics.Process (lsass)]} 
UnboundArguments : {} 
ScriptLineNumber : 1 
OffsetInLine  : 26 
HistoryId  : 62 
ScriptName  : 
Line    : gps lsass | test-PSCmdlet |Format-table Name,Id -auto 
PositionMessage : 
        At line:1 char:26 
        + gps lsass | test-PSCmdlet <<<< |Format-table Name,Id -aut 
        o 
InvocationName : test-PSCmdlet 
PipelineLength : 3 
PipelinePosition : 2 
ExpectingInput : True 
CommandOrigin : Runspace 


Name Id 
---- -- 
lsass 620 
+1

क्या कोई विकल्प है जब कमांड असाइनमेंट का हिस्सा होता है, फिर उसे अपने आप पर कॉल किया जाता है, जैसे '$ x = Do-Something ...'। उस मामले में पाइपलाइन स्थिति मदद नहीं करेगा। इसके लिए वर्कअराउंड 'डू-समथिंग' है एक्स सेट करें लेकिन इसे भूलना आसान है ... – majkinetor

6

ऐसा करने के लिए "मूर्खतापूर्ण" तरीका एक विशिष्ट ऑब्जेक्ट प्रकार आउटपुट करना है और फिर उस ऑब्जेक्ट के लिए स्वरूपण डेटा को परिभाषित करना है। ऑब्जेक्ट एक कस्टम (सी #/वीबी-आधारित ऑब्जेक्ट) या नामित पीएसओब्जेक्ट हो सकता है। इस दृष्टिकोण का लाभ यह है कि आप इन ऑब्जेक्ट्स को आउटपुट कर सकते हैं और यदि कोई और पाइपलाइन आउटपुट स्वरूपण नहीं है (यानी Format कमांड का उपयोग करें) तो आपको परिभाषित किया गया है कि डिफ़ॉल्ट आउटपुट स्वरूपण का उपयोग किया जाएगा। अन्यथा, Format आदेशों में से एक डिफ़ॉल्ट स्वरूपण को ओवरराइड कर सकता है।

PS> $obj = new-object psobject -Property @{FName = 'John'; LName = 'Doe'; ` 
              BirthDate = [DateTime]"5/7/1965"} 
PS> $obj.psobject.TypeNames.Insert(0, "MyNamespace.MyCustomTypeName") 
PS> $obj 

BirthDate        FName       LName 
---------        -----       ----- 
5/7/1965 12:00:00 AM     John        Doe 


PS> Update-FormatData .\MyCustomFormatData.ps1xml 
PS> $obj 

FName      LName      BirthDate 
-----      -----      --------- 
John      Doe      5/7/1965 12:00:00 AM 

सूचना कैसे डिफ़ॉल्ट उत्पादन दूसरी बार हम पाइप नीचे $obj भेजा अलग है: यहाँ एक उदाहरण है। ऐसा इसलिए है क्योंकि यह कस्टम स्वरूपण निर्देशों का उपयोग करता है क्योंकि प्रदत्त कोई स्पष्ट स्वरूपण आदेश नहीं थे।

बीटीडब्ल्यू $obj के लिए भी हमेशा एक पाइपलाइन है क्योंकि यह स्पष्ट रूप से Out-Default पर पाइप किया गया है।

<Configuration> 
    <ViewDefinitions> 
    <View> 
     <Name>MyNamespace.MyCustomTypeName</Name> 
     <ViewSelectedBy> 
     <TypeName>MyNamespace.MyCustomTypeName</TypeName> 
     </ViewSelectedBy> 
     <TableControl> 
     <TableHeaders> 
      <TableColumnHeader> 
      <Label>FName</Label> 
      <Width>25</Width> 
      <Alignment>left</Alignment> 
      </TableColumnHeader> 
      <TableColumnHeader> 
      <Label>LName</Label> 
      <Width>25</Width> 
      <Alignment>left</Alignment> 
      </TableColumnHeader> 
      <TableColumnHeader> 
      <Label>BirthDate</Label> 
      <Width>25</Width> 
      <Alignment>left</Alignment> 
      </TableColumnHeader> 
     </TableHeaders> 
     <TableRowEntries> 
      <TableRowEntry> 
      <TableColumnItems> 
       <TableColumnItem> 
       <PropertyName>FName</PropertyName> 
       </TableColumnItem> 
       <TableColumnItem> 
       <PropertyName>LName</PropertyName> 
       </TableColumnItem> 
       <TableColumnItem> 
       <PropertyName>BirthDate</PropertyName> 
       </TableColumnItem> 
      </TableColumnItems> 
      </TableRowEntry> 
     </TableRowEntries> 
     </TableControl> 
    </View> 
    </ViewDefinitions> 
</Configuration> 

कैसे कस्टम वस्तुओं को स्वरूपित करने के अधिक उदाहरणों के लिए इस आदेश से फ़ाइलें उत्पादन को देखो:

यहां कस्टम प्रारूप परिभाषा है कि एक .ps1xml फ़ाइल है कि मैं MyCustomFormatData.xml नामित में परिभाषित किया गया है है

Get-ChildItem $pshome\*.format.ps1xml 
+0

यह ठीक है लेकिन यह एक्सएमएल डेटा के साथ स्क्रिप्ट जोड़ता है जो स्वीकार्य नहीं हो सकता है (विशेष रूप से क्योंकि $ pshome परिवर्तनों को उन्नत निजी की आवश्यकता हो सकती है) – majkinetor

+2

स्वरूपण .ps1xml फ़ाइल को स्थापित करने के लिए आपको $ PSHome को संशोधित करने की आवश्यकता नहीं है। .ps1xml फ़ाइल स्क्रिप्ट के बगल में स्थित हो सकती है। अद्यतन-स्वरूप डेटा पर सहायता देखें। –

संबंधित मुद्दे

 संबंधित मुद्दे