2010-12-28 27 views
10

Chức năng PowerShell có thể xác định xem nó có đang chạy như một phần của đường ống không? Tôi có một chức năng populates một mảng với các trường hợp của FileInfo mà tôi muốn "mang lại" cho các đường ống nếu chức năng đang được chạy theo cách này hoặc sản xuất một số đầu ra khá nếu chức năng đang được gọi của chính nó từ dòng lệnh.Tôi có thể xác định xem chức năng PowerShell có đang chạy như một phần của đường ống không?

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

Về cơ bản, tôi đang cố gắng tìm hiểu cách triển khai INVOKED_IN_PIPELINE. Nếu nó chạy trong một đường ống (ví dụ: Do-Something | format-table fullname), tôi sẽ chỉ đơn giản là tạo mảng, nhưng nếu chạy trực tiếp (ví dụ: Do-Something), nó sẽ in các nội dung của mảng đó lên bảng điều khiển.

Có cách nào để thực hiện việc này không? Nếu có một cách "thành ngữ" hơn để đạt được loại điều này, tôi cũng sẽ muốn biết.

+1

Tại sao này downvoted? –

Trả lời

14

Thông tin này có sẵn như là một phần của $ PSCmdlet.MyInvocation. Đây là một lệnh ghép ngắn mà bạn có thể sử dụng để thử nghiệm với điều này. Những gì nó làm nó để viết ra các nội dung của tài sản đó một lần cho bất kỳ lệnh thực hiện và sau đó đi vào đối tượng (để bạn có thể thao tác các đối tượng một số chi tiết với đường ống lớn hơn). Những gì bạn sẽ thấy là có một thuộc tính được gọi là PipelineLength bằng 1 khi bạn tự chạy lệnh này và tăng cho mỗi mục trong đường ống. Cũng thông báo PipelinePosition. Nó cho bạn biết vị trí nào lệnh này đang ở trong đường dẫn.

LƯU Ý:$PSCmdlet chỉ có sẵn khi bạn viết một chức năng tiên tiến (ví dụ có thuộc tính [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 $_ 
    } 
} 

Dưới đây là một số ví dụ:.

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

Có bất kỳ tùy chọn nào khi lệnh là một phần của nhiệm vụ thay vì sau đó được gọi là riêng của nó, chẳng hạn như '$ x = Do-Something ...'. Trong trường hợp đó, vị trí đường ống sẽ không giúp ích gì. Giải pháp cho việc này là 'Do-Something | đặt x' nhưng dễ quên điều đó ... – majkinetor

6

Cách "thành ngữ" để thực hiện việc này là tạo ra một loại đối tượng cụ thể và sau đó xác định dữ liệu định dạng cho đối tượng đó. Đối tượng có thể là một đối tượng tùy chỉnh (đối tượng dựa trên C#/VB) hoặc một PSObject có tên. Ưu điểm của phương pháp này là bạn chỉ có thể xuất các đối tượng này và nếu không có định dạng đầu ra đường ống nữa (tức là sử dụng lệnh Format) thì bạn đã xác định định dạng đầu ra mặc định sẽ được sử dụng. Nếu không, một trong các lệnh Format có thể ghi đè định dạng mặc định đó. Dưới đây là ví dụ:

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 

Lưu ý cách đầu ra mặc định khác với lần thứ hai chúng tôi gửi $obj xuống ống. Đó là vì nó đã sử dụng các hướng dẫn định dạng tùy chỉnh được cung cấp vì không có lệnh định dạng rõ ràng nào được sử dụng.

BTW luôn có đường ống ngay cả đối với $obj vì đường ống đó được ngầm hoàn toàn đến Out-Default.

Dưới đây là định nghĩa định dạng tùy chỉnh được định nghĩa trong một file .ps1xml mà tôi đặt tên MyCustomFormatData.xml:

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

Để biết thêm ví dụ về cách định dạng đối tượng tùy chỉnh nhìn vào sản lượng tập tin bằng lệnh này:

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

Đó là OK nhưng nó ghép cặp tập lệnh với dữ liệu XML có thể không được chấp nhận (đặc biệt là vì $ pshome thay đổi có thể yêu cầu nâng cao) – majkinetor

+2

Bạn không cần sửa đổi $ PSHome để cài đặt tệp .ps1xml định dạng. Tệp .ps1xml có thể được đặt ngay bên cạnh tập lệnh. Xem trợ giúp về Update-FormatData. –

Các vấn đề liên quan