Tôi đang cố gắng viết một số chức năng PowerShell thực hiện một số công cụ và sau đó gọi một cách rõ ràng đến các chức năng tích hợp sẵn có. Tôi muốn vượt qua tất cả các đối số bị ảnh hưởng. Tôi không muốn biết bất kỳ chi tiết nào về các lập luận.Làm cách nào để chuyển 'dòng đối số' của một chức năng PowerShell sang một chức năng khác?
Tôi mệt mỏi khi sử dụng 'splat' để làm điều này với @args
nhưng điều đó không hoạt động như tôi mong đợi.
Trong ví dụ bên dưới, tôi đã viết chức năng đồ chơi có tên là myls
, nghĩa vụ in xin chào! và sau đó gọi cùng một chức năng được tích hợp sẵn, Get-ChildItem
, rằng lệnh gọi ls
bí danh dựng sẵn có phần còn lại của dòng đối số vẫn còn nguyên vẹn. Những gì tôi có cho đến nay hoạt động khá tốt:
function myls
{
Write-Output "hello!"
# $MyInvocation | Format-List # <-- uncomment this line for debug info
Invoke-Expression ("Get-ChildItem " + $MyInvocation.UnboundArguments -join " ")
}
Một phiên bản đúng của myls
nên có thể xử lý được gọi mà không có lý lẽ, với một đối số, với các đối số được đặt tên, từ một dòng chứa nhiều lệnh dấu chấm phẩy phân và với các biến trong các đối số, bao gồm các biến chuỗi chứa dấu cách. Về cơ bản, nó phải là một lựa chọn thay thế cho ls
.
Các thử nghiệm dưới đây so sánh myls
và được xây dựng trong ls
:
[Chú ý: sản lượng elided và/hoặc đầm để tiết kiệm không gian]
PS> md C:\p\d\x, C:\p\d\y, C:\p\d\"jay z"
PS> cd C:\p\d
PS> ls # no args
PS> myls # pass
PS> cd ..
PS> ls d # one arg
PS> myls d # pass
PS> $a="A"; $z="Z"; $y="y"; $jz="jay z"
PS> $a; ls d; $z # multiple statements
PS> $a; myls d; $z # pass
PS> $a; ls d -Exclude x; $z # named args
PS> $a; myls d -Exclude x; $z # pass
PS> $a; ls d -Exclude $y; $z # variables in arg-line
PS> $a; myls d -Exclude $y; $z # pass
PS> $a; ls d -Exclude $jz; $z # variables containing spaces in arg-line
PS> $a; myls d -Exclude $jz; $z # FAIL!
Có cách nào tôi có thể viết lại myls
để có được hành vi tôi muốn?
Câu trả lời ngắn: Có, có thể. Tin xấu: nó yêu cầu mã biết chi tiết về các tham số và siêu dữ liệu khác về hàm mà người dùng muốn gọi đến. Tin tốt: người ta không cần phải viết tất cả những người này. Siêu dữ liệu này có sẵn theo chương trình và tồn tại các mô-đun có sẵn mà người dùng có thể sử dụng để tự động tạo mã proxy của bộ xương (xem câu trả lời của @ Jaykul bên dưới). Tôi chọn sử dụng the module named "MetaProgramming". Khi nhập khẩu, tạo ra một thả trong myls
kịch bản là chết đơn giản:
New-ProxyCommand ls > .\myls.ps1
Sau đó, người ta có thể bắt đầu tùy chỉnh mới được tạo myls.ps1
kịch bản, như thế này:
...
begin
{
Write-Output "hello!" # <-- add this line
try {
$outBuffer = $null
...
Voila! Phiên bản mới này vượt qua tất cả các bài kiểm tra.
bạn đúng, đây là những gì tôi thực sự cần. Cảm ơn! – jwfearn
Nói cách khác: sao chép tự động. Chỉ đáng kinh ngạc. – alecov
Nếu bạn có thể sao chép-dán, bạn sẽ không cần tạo mã. Những gì OP đang làm là cố gắng phân lớp lệnh: viết một lệnh mới dựa trên bản gốc, nhưng với các sửa đổi tùy chỉnh ... và trong tập lệnh. Nếu bạn đã làm nó trong C#, bạn chỉ cần kế thừa.Nhưng bạn đang ở trong PowerShell, vì vậy bạn phải viết một hàm bắt đầu bằng cách sao chép tập hợp các tham số từ lệnh ghép ngắn ban đầu (trong PowerShell, chúng tôi gọi các hàm proxy đó). Nếu có bất cứ điều gì mà khóc cho thế hệ mã, đây là nó. – Jaykul