2012-07-06 19 views
21

Tôi cảm thấy như tôi đang thiếu một cái gì đó mà nên được rõ ràng, nhưng tôi chỉ không thể tìm ra cách để làm điều này.Làm cách nào để đưa chức năng được xác định cục bộ khi sử dụng Lệnh gọi của PowerShell để truy cập từ xa?

Tôi có tập lệnh ps1 có chức năng được xác định trong đó. Nó gọi hàm này và sau đó thử sử dụng nó từ xa:

function foo 
{ 
    Param([string]$x) 

    Write-Output $x 
} 

foo "Hi!" 

Invoke-Command -ScriptBlock { foo "Bye!" } -ComputerName someserver.example.com -Credential [email protected] 

Tập lệnh mẫu ngắn này in "Xin chào!" và sau đó đổ vỡ cho biết "Thuật ngữ 'foo' không được nhận dạng là tên của lệnh ghép ngắn, hàm, tệp kịch bản hoặc chương trình có thể hoạt động."

Tôi hiểu rằng chức năng không được xác định trên máy chủ từ xa vì nó không có trong ScriptBlock. Tôi có thể xác định lại nó ở đó, nhưng tôi không muốn. Tôi muốn xác định chức năng một lần và sử dụng nó một cách cục bộ hoặc từ xa. Có cách nào tốt để làm điều này?

Trả lời

25

Bạn cần phải tự vượt qua chức năng (không phải cuộc gọi đến hàm trong ScriptBlock).

Tôi có nhu cầu tương tự chỉ vào tuần trước và tìm thấy this SO discussion

Vì vậy, mã của bạn sẽ trở thành:

Invoke-Command -ScriptBlock ${function:foo} -argumentlist "Bye!" -ComputerName someserver.example.com -Credential [email protected] 

Lưu ý rằng bằng cách sử dụng phương pháp này, bạn chỉ có thể vượt qua các thông số vào chức năng của bạn theo vị trí; bạn không thể sử dụng các tham số được đặt tên như bạn có thể khi chạy hàm cục bộ.

+0

Được rồi, âm thanh đó tương tự với nội dung tôi đã đọc. Vì vậy, lấy một bước xa hơn: có cách nào tốt để bao gồm hàm và một số dòng lệnh bổ sung sử dụng hàm này không? –

+0

Tôi chưa thử nghiệm điều này, nhưng nếu bạn muốn định dạng đầu ra của hàm (ví dụ), điều này sẽ hoạt động: '-ScriptBlock {$ function: foo | format-table -auto}'. Về cơ bản, bất kỳ 'ScriptBlock' nào cũng có thể là bất kỳ" đoạn mã "nào của mã PowerShell hợp lệ, miễn là bạn định dạng nó đúng (hoặc sử dụng dấu chấm phẩy ở cuối mỗi" dòng "), bạn nên làm tốt. Trước đó hôm nay tôi đã mucking xung quanh với 'measure-command {$ x = [xml] (get-content file.xml); ví dụ $ x.selectsinglenode (" // thing ");}. – alroc

20

Bạn có thể vượt qua định nghĩa của hàm như một tham số, và sau đó xác định lại chức năng trên máy chủ từ xa bằng cách tạo ra một scriptblock và sau đó dot-sourcing nó:

$fooDef = "function foo { ${function:foo} }" 

Invoke-Command -ArgumentList $fooDef -ComputerName someserver.example.com -ScriptBlock { 
    Param($fooDef) 

    . ([ScriptBlock]::Create($fooDef)) 

    Write-Host "You can call the function as often as you like:" 
    foo "Bye" 
    foo "Adieu!" 
} 

này giúp loại bỏ sự cần thiết phải có một bản sao của hàm của bạn. Bạn cũng có thể chuyển nhiều chức năng theo cách này, nếu bạn nghiêng như vậy:

$allFunctionDefs = "function foo { ${function:foo} }; function bar { ${function:bar} }" 
+0

Chính xác những gì tôi đang tìm kiếm! Giải pháp của bạn kết hợp với '$ Sử dụng: Var' đã làm các trick :) Cảm ơn bạn rất nhiều! – DarkLite1

+0

Rất hay, chính xác những gì tôi đang tìm kiếm. Cảm ơn bạn đã chia sẻ – vdubgeek

4

Bạn cũng có thể đặt (các) hàm cũng như tập lệnh trong tệp (foo.ps1) và chuyển để Gọi-Lệnh sử dụng tham số FilePath:

Invoke-Command –ComputerName server –FilePath .\foo.ps1 

Tệp sẽ được sao chép vào máy tính từ xa và được thi hành.

+0

Đây là tùy chọn tốt nhất. Giảm sự lộn xộn và dễ dàng. Viết kịch bản giống như bạn muốn nó được thực hiện và thì đấy! –

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