Cách chuyển đối số dòng lệnh vào tệp ps1 PowerShell


90

Trong nhiều năm, tôi đã sử dụng cmd/DOS/Windowsshell và truyền các đối số dòng lệnh cho các tệp hàng loạt. Ví dụ, tôi có một tập tin, zuzu.batvà trong đó, truy cập tôi %1, %2vv Bây giờ, tôi muốn làm điều tương tự khi tôi gọi một PowerShellkịch bản when I am in a Cmd.exe shell. Tôi có một tập lệnh xuxu.ps1(và tôi đã thêm PS1 vào biến PATHEXT của mình và các tệp PS1 được liên kết với PowerShell). Nhưng bất kể tôi làm gì, tôi dường như không thể nhận được bất cứ điều gì từ $argsbiến. Nó luôn có độ dài 0.

Nếu tôi ở trong một trình PowerShellbao, thay vì cmd.exe, nó hoạt động (tất nhiên). Nhưng tôi vẫn chưa đủ thoải mái để sống trong môi trường PowerShell toàn thời gian. Tôi không muốn gõ powershell.exe -command xuxu.ps1 p1 p2 p3 p4. Tôi muốn gõ xuxu p1 p2 p3 p4.

Điều này có khả thi không, và nếu có thì làm thế nào?

Mẫu mà tôi không thể làm việc là tầm thường, foo.ps1:

Write-Host "Num Args:" $args.Length;
foreach ($arg in $args) {
    Write-Host "Arg: $arg";
}

Kết quả luôn như thế này:

C:\temp> foo
Num Args: 0
C:\temp> foo a b c d
Num Args: 0
c:\temp>

Câu trả lời:


34

Bài viết này giúp ích. Đặc biệt, phần này:

-Tập tin

Chạy tập lệnh được chỉ định trong phạm vi cục bộ ("dot-nguồn gốc"), để các hàm và biến mà tập lệnh tạo sẵn có trong phiên hiện tại. Nhập đường dẫn tệp script và bất kỳ thông số nào. Tệp phải là tham số cuối cùng trong lệnh, vì tất cả các ký tự được nhập sau tên tham số Tệp được hiểu là đường dẫn tệp tập lệnh theo sau là các tham số tập lệnh.

I E

powershell.exe -File "C:\myfile.ps1" arg1 arg2 arg3

nghĩa là chạy tệp myfile.ps1 và arg1 arg2 & arg3 là các tham số cho tập lệnh PowerShell.


1
Điều này vẫn không giúp được gì với những gì op muốn ("Tôi muốn nhập xuxu p1 p2 p3 p4").
thdoan

19

Sau khi tìm hiểu tài liệu PowerShell, tôi đã phát hiện ra một số thông tin hữu ích về vấn đề này. Bạn không thể sử dụng $argsif bạn đã sử dụng param(...)ở đầu tệp của mình; thay vào đó bạn sẽ cần phải sử dụng $PSBoundParameters. Tôi sao chép / dán mã của bạn vào tập lệnh PowerShell và nó hoạt động như bạn mong đợi trong PowerShell phiên bản 2 (Tôi không chắc bạn đang sử dụng phiên bản nào khi gặp sự cố này).

Nếu bạn đang sử dụng $PSBoundParameters(và điều này CHỈ hoạt động nếu bạn đang sử dụng param(...)ở đầu tập lệnh của mình), thì nó không phải là một mảng, nó là một bảng băm, vì vậy bạn sẽ cần tham chiếu nó bằng cách sử dụng cặp khóa / giá trị.

param($p1, $p2, $p3, $p4)
$Script:args=""
write-host "Num Args: " $PSBoundParameters.Keys.Count
foreach ($key in $PSBoundParameters.keys) {
    $Script:args+= "`$$key=" + $PSBoundParameters["$key"] + "  "
}
write-host $Script:args

Và khi được gọi bằng ...

PS> ./foo.ps1 a b c d

Kết quả là...

Num Args:  4
$p1=a  $p2=b  $p3=c  $p4=d

Điều này không giải thích cho việc OP bắt đầu dòng lệnh của mình bằng powershell.exe hoặc pwsh. Hành vi thay đổi khi OP thực hiện điều đó.
Eric Hansen

1
@EricHansen Tôi không biết ý bạn là gì, tôi cũng nhận được kết quả tương tự: `Powershell> powershell.exe. \ ParamTest.ps1 val1 val2 val3 val4 Num Args: 4 $ p1 = val1 $ p2 = val2 $ p3 = val3 $ p4 = val4 '
Randall Borck

@RandallBrock Hành vi của các đối số thay đổi đối với tôi. Nếu tôi đang ở trong CMD / batch, và tôi làm điều gì đó như thế pwsh .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4, nó thực sự không thích điều đó. Mặt khác, nếu tôi đang sử dụng PowerShell và làm như vậy .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4, điều đó sẽ hoạt động như tôi mong đợi. Tôi nghe nói rằng đây là cách nó dự định hoạt động vì "lý do bảo mật".
Eric Hansen

@EricHansen Tôi tự hỏi liệu nó có phải là phiên bản không. Đối với tôi, ra mắt pwsh 6.2.0, nhưng ra mắt powershell.exe 5.1.17134.858, cả hai đều tạo ra kết quả tương tự được liệt kê: Powershell>pwsh .\ParamTest.ps1 val1 val2 val3 val4sản lượng:Num Args: 4 $p1=val1 $p2=val2 $p3=val3 $p4=val4
Randall Borck

1
@Timo Tôi không biết chính xác bạn đang làm gì, nhưng paramlà một cấu trúc ngôn ngữ, tuy nhiên nó phải là thứ đầu tiên trong tệp. Bạn đã khai báo một biến hoặc một cái gì đó khác trước nó? Thông tin thêm tại đây: docs.microsoft.com/en-us/powershell/module/…
Randall Borck

18

OK, vì vậy trước tiên, điều này đang phá vỡ một tính năng bảo mật cơ bản trong PowerShell. Với sự hiểu biết đó, đây là cách bạn có thể làm điều đó:

  1. Mở cửa sổ Windows Explorer
  2. Menu Tools -> Folder Options -> tab Type File
  3. Tìm loại tệp PS1 và nhấp vào nút nâng cao
  4. Nhấp vào nút Mới
  5. Đối với hành động đặt: Mở
  6. Đối với Ứng dụng đặt: "C: \ WINNT \ system32 \ WindowsPowerShell \ v1.0 \ powershell.exe" "-tệp" "% 1"% *

Bạn cũng có thể muốn đưa một -NoProfileđối số vào đó tùy thuộc vào những gì hồ sơ của bạn làm.


4
Tôi nghĩ rằng chìa khóa là ở bước 6 của bạn, nơi bạn chuyển các tham số vào powershell.exe. Daniel cho biết anh đã liên kết các tệp PS1 với PowerShell nhưng điều đó không vượt qua đối số mà không có thông số kỹ thuật% 1% * bổ sung. Cũng lưu ý rằng tham số -File không có sẵn trong V1. Nó là mới với V2.
Keith Hill

Nắm bắt tốt về tham số -tệp, tôi đã quên điều đó.
EBGreen

Tôi sẽ phải cài đặt V2 trước khi tôi có thể thử đề xuất của bạn. Cảm ơn. Khi bạn nói điều này đang phá vỡ một tính năng bảo mật cơ bản, thì "điều này" có nghĩa là gì? Gọi một tập lệnh PowerShell từ Cmd.exe như thể nó là một tệp .com / .bat / .exe? Truyền tham số cho tập lệnh?
Daniel 'Dang' Griffith

1
Xin lỗi, tôi nên nói rõ hơn. Việc gọi tập lệnh mà không gọi rõ ràng powershell.exe. Tôi không nói rằng đó là một tính năng bảo mật quan trọng đối với cá nhân bạn và đó là tính năng bảo mật thông qua sự che giấu mà tôi không phải lúc nào cũng là người yêu thích.
EBGreen

6
Thêm vào nhận xét của EBGreen, vấn đề bảo mật cơ bản mà PowerShell cố gắng tránh là mọi người nhấp đúp vào tệp PS1 được đính kèm trong email và chạy tập lệnh. Đó là lý do tại sao các tệp PS1 chỉ được liên kết với một trình chỉnh sửa theo mặc định. Microsoft thực sự không muốn có một phiên bản PowerShell của virus ILoveYou ví dụ: "LOVE-LETTER-FOR-YOU.TXT.ps1"
Keith Hill

11

Bạn có thể khai báo các tham số của mình trong tệp, như param:

[string]$para1
[string]$param2

Và sau đó gọi tệp PowerShell như vậy .\temp.ps1 para1 para2....para10, v.v.


6

Có thể bạn có thể gói lời gọi PowerShell trong một .battệp như vậy:

rem ps.bat
@echo off
powershell.exe -command "%*"

Nếu sau đó bạn đặt tệp này trong một thư mục trong thư mục của mình PATH, bạn có thể gọi các tập lệnh PowerShell như sau:

ps foo 1 2 3

Tuy nhiên, việc trích dẫn có thể hơi lộn xộn:

ps write-host """hello from cmd!""" -foregroundcolor green

+1 để hiển thị dấu ngoặc kép. điều đó đã khiến tôi bị mắc kẹt trong một thời gian.
DeanOC

1

Bạn có thể không nhận được "xuxu p1 p2 p3 p4" như có vẻ. Nhưng khi bạn ở trong PowerShell và bạn đặt

PS > set-executionpolicy Unrestricted -scope currentuser

Bạn có thể chạy các tập lệnh đó như sau:

./xuxu p1 p2 p3 p4

hoặc là

.\xuxu p1 p2 p3 p4

hoặc là

./xuxu.ps1 p1 p2 p3 p4

Tôi hy vọng điều đó giúp bạn thoải mái hơn một chút với PowerShell.


0

nếu bạn muốn gọi các tập lệnh ps1 từ cmd và chuyển các đối số mà không cần gọi tập lệnh như

powershell.exe script.ps1 -c test
script -c test ( wont work )

bạn có thể làm như sau

setx PATHEXT "%PATHEXT%;.PS1;" /m
assoc .ps1=Microsoft.PowerShellScript.1
ftype Microsoft.PowerShellScript.1=powershell.exe "%1" %*

Điều này giả sử powershell.exe nằm trong đường dẫn của bạn

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ftype


Cần lưu ý rằng điều này yêu cầu chạy dấu nhắc cmd với tư cách Quản trị viên. Ngoài ra, tôi đang đấu tranh để thực sự làm cho nó hoạt động trên Windows 10 phiên bản 1903 (18362.778) - tất cả các lệnh chạy thành công nhưng các đối số vẫn không được chuyển vào. Tôi nghĩ rằng gói bằng tệp .bat là giải pháp di động nhất.
David Airapetyan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.