2009-04-30 38 views
7

Tôi đang tạo tập lệnh Powershell để triển khai một số mã và một phần của quy trình là gọi một công cụ nén dòng lệnh gọi là RAR.EXE để sao lưu một số thư mục.Xử lý lệnh Powershell (Chuyển các biến)

Tôi đang cố gắng tự động xây dựng các tham số và sau đó có PowerShell gọi lệnh bằng các biến nhưng tôi đang gặp sự cố. Nó không hoạt động ...

Chạy tập lệnh sau và bạn sẽ thấy những gì tôi đang nói đến. Các thông số được truyền vào dưới dạng biến sẽ bị xáo trộn. Nếu tôi vượt qua toàn bộ lệnh + tham số trong tôi nhận được các "khét tiếng" không được công nhận là một cmdlet ... "tin nhắn.

Cảm ơn bạn đã trợ giúp!

echo "this should succeed" 
& cmd /c echo foo 

echo "why does this echo out an additional double quote?" 
$param = "/c echo foo" 
& cmd "$param" 

echo "this does the same" 
$param = "/c echo foo" 
& cmd $param 

echo "escaping the slash doesn't work either..." 
$param = "`/c echo foo" 
& cmd $param 

echo "this fails, but why?" 
$cmd = "cmd /c echo foo" 
&$cmd 

Trả lời

9

Toán tử gọi '&' là không cần thiết trong trường hợp này. Nó được sử dụng để gọi một lệnh trong một phạm vi mới. Điều này thường được sử dụng để gọi một lệnh được chỉ định bởi một chuỗi hoặc scriptblock. Nó cũng có lợi ích phụ mà bất kỳ biến được tạo ra trong nói rằng một kịch bản PowerShell được bỏ đi sau khi lệnh kết thúc và phạm vi biến mất.

Tuy nhiên vì cmd là một EXE, nó thực hiện trong một quá trình hoàn toàn khác. FWIW, bạn sẽ nhận được kết quả tương tự trực tiếp từ cmd.exe:

> cmd "/c echo foo" 
foo" 

Vì vậy, báo giá bổ sung ở cuối là vấn đề cmd.exe. Thông thường, bạn cần phải giữ lệnh tách biệt với các tham số khi PowerShell đang thực hiện phân tích cú pháp để gọi lệnh, ví dụ:

45> & { $foo = "foo" } 
46> $foo # Note that $foo wasn't found - it went away with the scope 
47> . { $foo = "foo" } # dotting executes in the current scope 
48> $foo 
foo 

Ngoại lệ đáng chú ý ở đây là Invoke-Expression hoạt động giống như chức năng "đánh giá chuỗi này". Sử dụng cẩn thận, đặc biệt là nếu người dùng cung cấp chuỗi. Ngày của bạn có thể hút nếu họ cung cấp "ri C: \ -r".

Trong trường hợp này, như những người khác đã đề nghị tôi sẽ kéo/c ra khỏi param chuỗi string $ và xác định nó ví dụ .:

cmd /c $param 

Hoặc sử dụng Invoke-Biểu hiện nhưng sử dụng một cách cẩn thận. BTW khi bạn đang cố gắng gỡ lỗi các vấn đề với việc gửi các đối số tới EXE từ PowerShell, hãy kiểm tra tiện ích echoargs trong Tiện ích Cộng đồng PowerShell (http://pscx.codeplex.com). Nó rất tiện dụng:

49> $param = "/c echo foo" 
50> echoargs $param 
Arg 0 is </c echo foo> 

Điều này cho thấy cmd.exe nhận "/ c vang foo" như một đơn tranh cãi. "/ c" phải là một đối số riêng biệt từ "echo foo" (lệnh thực hiện).

+5

Mảng cũng hoạt động tốt để xây dựng các đối số dòng lệnh; ví dụ: $ cmdArgs = @ ('/ c', 'echo foo'); cmd $ cmdArgs –

0

đó là một tạo phẩm sử dụng cmd/c, tôi nghĩ vậy. chạy

$param = "echo foo" 
cmd /c $param 

hoạt động tốt. Trừ khi bạn có một ví dụ mã thực sự, đó là một chút khó khăn để bắn rắc rối.

6

Tôi đã gặp sự cố với toán tử gọi & trong quá khứ khi cố gọi các lệnh loại thực thi như bạn đang cố gắng. Không chắc tôi hiểu tại sao. Gọi-Biểu Tuy nhiên, luôn luôn có vẻ để làm việc trong bối cảnh này:

PS C:\> $cmd = "cmd /c echo foo" 
PS C:\> Invoke-expression $cmd 
foo 
3

ví dụ cuối cùng của bạn nếu không vì "&" xử lý các chuỗi như một đối số, vì vậy nó đang tìm kiếm một chương trình có tên là "cmd/c vang foo .exe ". :)

này hoạt động:

& $cmd $params 

Đối với các vấn đề báo giá gấp đôi, nó có vẻ rằng cmd không thích các dấu ngoặc kép quanh lập luận rằng PowerShell đặt. Nó được điều này:

cmd "/c echo foo" 

Vì vậy, tôi nghĩ rằng nó đối xử với tất cả mọi thứ sau/c như lệnh chính xác, do đó, như vậy:

echo foo" 

Một số chương trình dòng lệnh và phân tích sôi nổi của dòng lệnh (có nghĩa là tại sao PowerShell tiếp quản công việc này cho các hàm và các lệnh ghép ngắn). Trong trường hợp cmd, tôi sẽ đề xuất điều này:

$param = "echo foo" 
& cmd /c $param 
8

Một cách khác mà tôi tìm thấy để thực hiện việc này là tạo một mảng đối số cho dòng lệnh và sử dụng toán tử đó với toán tử gọi apersand &. Một cái gì đó như thế này:

$exe = "cmd"; 
[Array]$params = "/c", "echo", "foo"; 

& $exe $params; 

Nó hoạt động tốt cho tôi.

tôi ban đầu được tìm thấy kỹ thuật này ở đây: http://techstumbler.blogspot.com/2009/12/windows-commands-with-arguments-in.html

0

args được đối xử khác biệt khi chúng được chứa trong một String:

PS D:\> echo "1 2 3" 
1 2 3 
PS D:\> echo 1 2 3 
1 
2 
3 

Các kết quả tương tự xảy ra khi bạn sử dụng một biến cho args:

PS D:\> $param = "1 2 3" 
PS D:\> echo $param 
1 2 3 

GIẢI PHÁP sử dụng Mảng:

PS D:\> $param = @(1,2,3) 
PS D:\> echo $param 
1 
2 
3 
Các vấn đề liên quan