Cách sử dụng tệp hàng loạt để chạy tập lệnh PowerShell dễ dàng hơn
Vì nhiều lý do, chủ yếu liên quan đến bảo mật, các tập lệnh PowerShell không dễ mang theo và có thể sử dụng được như các tập lệnh bó. Tuy nhiên, chúng tôi có thể gói một tập lệnh bó với tập lệnh PowerShell để giải quyết các vấn đề này. Tại đây, chúng tôi sẽ chỉ cho bạn một vài trong số các khu vực có vấn đề đó và cách xây dựng tập lệnh bó để khắc phục chúng.
Tại sao tôi không thể sao chép tệp .PS1 của mình sang máy tính khác và chạy nó?
Trừ khi hệ thống đích đã được cấu hình sẵn để cho phép chạy các tập lệnh tùy ý, với các đặc quyền bắt buộc và sử dụng đúng cài đặt, rất có thể bạn sẽ gặp phải một số vấn đề khi bạn cố gắng làm điều này.
- PowerShell không được liên kết với phần mở rộng tệp .PS1 theo mặc định.
Chúng tôi đã đưa ra điều này ban đầu trong loạt trường PowerShell Geek của chúng tôi. Windows liên kết các tệp .PS1 với Notepad theo mặc định, thay vì gửi chúng đến trình thông dịch lệnh PowerShell. Điều này là để ngăn chặn việc thực thi các tập lệnh độc hại bằng cách nhấp đúp vào chúng. Có nhiều cách bạn có thể thay đổi hành vi này, nhưng có lẽ đó không phải là điều bạn muốn làm trên mọi máy tính mà bạn mang theo tập lệnh của mình - đặc biệt là nếu một số máy tính đó không phải là của riêng bạn. - PowerShell không cho phép thực thi tập lệnh bên ngoài theo mặc định.
Cài đặt ExecutPolicy trong PowerShell ngăn chặn việc thực thi các tập lệnh bên ngoài theo mặc định trong tất cả các phiên bản Windows. Trong một số phiên bản Windows, mặc định không cho phép thực thi tập lệnh. Chúng tôi đã chỉ cho bạn cách thay đổi cài đặt này trong Cách cho phép thực thi tập lệnh PowerShell trên Windows 7. Tuy nhiên, đây cũng là điều bạn không muốn làm trên bất kỳ máy tính nào. - Một số tập lệnh PowerShell sẽ không hoạt động nếu không có quyền của Quản trị viên.
Ngay cả khi chạy với tài khoản cấp Quản trị viên, bạn vẫn cần thông qua Kiểm soát tài khoản người dùng (UAC) để thực hiện một số hành động nhất định. Chúng tôi không muốn vô hiệu hóa điều này, nhưng vẫn tốt khi chúng tôi có thể giải quyết dễ dàng hơn một chút. - Một số người dùng có thể có môi trường PowerShell tùy chỉnh.
Bạn có thể sẽ không gặp phải vấn đề này thường xuyên, nhưng khi bạn làm điều đó có thể khiến việc chạy và xử lý sự cố các tập lệnh của bạn hơi khó chịu. May mắn thay, chúng ta có thể khắc phục điều này mà không thực hiện bất kỳ thay đổi vĩnh viễn nào.
Bước 1: Nhấp đúp chuột để chạy.
Hãy bắt đầu bằng cách giải quyết vấn đề đầu tiên - liên kết tệp .PS1. Bạn không thể nhấp đúp để chạy tệp .PS1, nhưng bạn có thể thực thi tệp .BAT theo cách đó. Vì vậy, chúng tôi sẽ viết một tệp bó để gọi tập lệnh PowerShell từ dòng lệnh cho chúng tôi.
Vì vậy, chúng tôi không phải viết lại tệp bó cho mỗi tập lệnh hoặc mỗi khi chúng tôi di chuyển tập lệnh xung quanh, nó sẽ sử dụng biến tự tham chiếu để xây dựng đường dẫn tệp cho tập lệnh PowerShell. Để thực hiện công việc này, tệp bó sẽ cần được đặt trong cùng thư mục với tập lệnh PowerShell của bạn và có cùng tên tệp. Vì vậy, nếu tập lệnh PowerShell của bạn được gọi là My My.s1.ps1, bạn sẽ muốn đặt tên cho tập tin hàng loạt của mình là My My..biết và đảm bảo rằng nó nằm trong cùng một thư mục. Sau đó, đặt các dòng này trong tập lệnh bó:
@ECHO TẮT PowerShell.exe -Command "& '% ~ dpn0.ps1'" PAUSE
Nếu không có các hạn chế bảo mật khác, đó thực sự là tất cả những gì cần thiết để chạy tập lệnh PowerShell từ một tệp bó. Trên thực tế, dòng đầu tiên và dòng cuối cùng chủ yếu chỉ là vấn đề ưu tiên - đó là dòng thứ hai thực sự làm việc. Đây là sự cố:
@ECHO TẮT tắt lệnh vang vọng. Điều này chỉ giữ cho các lệnh khác của bạn hiển thị trên màn hình khi tệp bó chạy. Dòng này được ẩn bằng cách sử dụng biểu tượng at (@) phía trước nó.
PowerShell.exe -Command & & %% dpn0.ps1 ' thực sự chạy tập lệnh PowerShell. Tất nhiên, PowerShell.exe có thể được gọi từ bất kỳ cửa sổ hoặc tệp bó nào của CMD để khởi chạy PowerShell lên bàn điều khiển trống như bình thường. Bạn cũng có thể sử dụng nó để chạy các lệnh trực tiếp từ một tệp bó, bằng cách bao gồm tham số -Command và các đối số thích hợp. Cách thức này được sử dụng để nhắm mục tiêu tệp .PS1 của chúng tôi với biến% ~ dpn0 đặc biệt. Chạy từ một tệp bó,% ~ dpn0 ước tính cho ký tự ổ đĩa, đường dẫn thư mục và tên tệp (không có phần mở rộng) của tệp bó. Vì tệp bó và tập lệnh PowerShell sẽ nằm trong cùng một thư mục và có cùng tên,% ~ dpn0.ps1 sẽ dịch sang đường dẫn tệp đầy đủ của tập lệnh PowerShell.
TẠM NGỪNG chỉ tạm dừng thực hiện hàng loạt và chờ đợi đầu vào của người dùng. Điều này thường hữu ích khi có ở cuối các tệp bó của bạn, để bạn có cơ hội xem lại bất kỳ đầu ra lệnh nào trước khi cửa sổ biến mất. Khi chúng ta trải qua thử nghiệm từng bước, tính hữu ích của việc này sẽ trở nên rõ ràng hơn.
Vì vậy, tập tin lô cơ bản được thiết lập. Đối với mục đích trình diễn, tệp này được lưu dưới dạng Khăn D: \ Script Lab \ MyScript.bat và có một MyScript.ps1 tựa trong cùng một thư mục. Hãy xem điều gì xảy ra khi chúng ta bấm đúp vào MyScript.bat.
Rõ ràng là tập lệnh PowerShell không chạy, nhưng đó là điều được mong đợi - sau tất cả, chúng tôi chỉ giải quyết vấn đề đầu tiên trong bốn vấn đề của chúng tôi. Tuy nhiên, có một số bit quan trọng được trình bày ở đây:
- Tiêu đề cửa sổ cho thấy tập lệnh bó đã khởi chạy thành công PowerShell.
- Dòng đầu ra đầu tiên cho thấy cấu hình PowerShell tùy chỉnh đang được sử dụng. Đây là vấn đề tiềm năng # 4, được liệt kê ở trên.
- Thông báo lỗi thể hiện các hạn chế ExecutPolicy có hiệu lực. Đó là vấn đề của chúng tôi # 2.
- Phần được gạch chân của thông báo lỗi (được thực hiện nguyên bản bởi đầu ra lỗi của PowerShell) cho thấy tập lệnh bó đã nhắm mục tiêu chính xác vào tập lệnh PowerShell dự định (D: \ Script Lab \ MyScript.ps1). Vì vậy, ít nhất chúng ta biết rằng nhiều thứ đang hoạt động đúng.
Hồ sơ, trong trường hợp này, là một tập lệnh một dòng đơn giản được sử dụng cho trình diễn này để tạo đầu ra bất cứ khi nào hồ sơ được kích hoạt. Bạn có thể tùy chỉnh hồ sơ PowerShell của riêng mình để thực hiện điều này, nếu bạn muốn tự kiểm tra các tập lệnh này. Chỉ cần thêm dòng sau vào tập lệnh hồ sơ của bạn:
Đầu ra ghi 'Cấu hình PowerShell tùy chỉnh có hiệu lực!'
ExecutPolicy trên hệ thống kiểm tra ở đây được đặt thành RemoteSign. Điều này cho phép thực thi các tập lệnh được tạo cục bộ (như tập lệnh hồ sơ), đồng thời chặn tập lệnh từ các nguồn bên ngoài trừ khi chúng được ký bởi cơ quan đáng tin cậy. Đối với mục đích trình diễn, lệnh sau đã được sử dụng để gắn cờ MyScript.ps1 là từ nguồn bên ngoài:
Thêm nội dung -Path 'D: \ Script Lab \ MyScript.ps1' -Value "[ZoneTransfer] 'nZoneId = 3" -Stream' Zone.Identifier '
Điều đó đặt luồng dữ liệu thay thế Zone.Identifier trên MyScript.ps1 để Windows sẽ nghĩ rằng tệp đến từ Internet. Nó có thể dễ dàng đảo ngược với lệnh sau:
Xóa nội dung -Path 'D: \ Script Lab \ MyScript.ps1' -Stream 'Zone.Identifier'
Bước 2: Di chuyển xung quanh ExecutPolicy.
Di chuyển xung quanh cài đặt ExecutPolicy, từ CMD hoặc tập lệnh bó, thực sự khá dễ dàng. Chúng tôi chỉ sửa đổi dòng thứ hai của tập lệnh để thêm một tham số vào lệnh PowerShell.exe.
PowerShell.exe -ExecutPolicy Bypass -Command "& '% ~ dpn0.ps1'"
Tham số -ExecutPolicy có thể được sử dụng để sửa đổi ExecutPolicy được sử dụng khi bạn sinh ra một phiên PowerShell mới. Điều này sẽ không tồn tại sau phiên đó, vì vậy chúng tôi có thể chạy PowerShell như thế này bất cứ khi nào chúng tôi cần mà không làm suy yếu tư thế bảo mật chung của hệ thống. Bây giờ chúng tôi đã sửa nó, chúng ta hãy thực hiện nó:
Bây giờ kịch bản đã được thực thi đúng, chúng ta có thể thấy những gì nó thực sự làm. Nó cho chúng tôi biết rằng chúng tôi đang chạy tập lệnh với tư cách là người dùng có giới hạn. Tập lệnh trên thực tế đang được điều hành bởi một tài khoản có quyền Quản trị viên, nhưng Kiểm soát Tài khoản Người dùng đang cản trở. Mặc dù chi tiết về cách tập lệnh đang kiểm tra quyền truy cập của Quản trị viên nằm ngoài phạm vi của bài viết này, đây là đoạn mã được sử dụng để trình diễn:
if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity] :: GetCản ()). IsInRole ([Security.Principal.WindowsBuiltInRole] "Quản trị viên") Đầu ra ghi 'Chạy giới hạn!' Tạm dừng
Bạn cũng sẽ nhận thấy rằng bây giờ có hai hoạt động Tạm dừng của mối quan hệ trong đầu ra tập lệnh - một từ tập lệnh PowerShell và một từ tập tin bó. Lý do cho điều này sẽ rõ ràng hơn trong bước tiếp theo.
Bước 3: Truy cập quản trị viên.
Nếu tập lệnh của bạn không chạy bất kỳ lệnh nào yêu cầu độ cao và bạn chắc chắn rằng bạn sẽ không phải lo lắng về cấu hình tùy chỉnh của bất kỳ ai cản trở bạn, bạn có thể bỏ qua phần còn lại của điều này. Nếu bạn đang chạy một số lệnh ghép ngắn cấp Quản trị viên, bạn sẽ cần phần này.
Thật không may, không có cách nào để kích hoạt UAC cho độ cao từ trong một tệp bó hoặc phiên CMD. Tuy nhiên, PowerShell cho phép chúng tôi thực hiện điều này với Quá trình bắt đầu. Khi được sử dụng với các phiên bản của Run -Verb RunAs, các đối số của nó, Start-Process sẽ cố gắng khởi chạy một ứng dụng có quyền của Quản trị viên. Nếu phiên PowerShell chưa được nâng lên, điều này sẽ kích hoạt lời nhắc UAC. Để sử dụng tệp này từ tệp bó để khởi chạy tập lệnh của chúng tôi, chúng tôi sẽ kết thúc việc tạo ra hai quy trình PowerShell - một để khởi động Quá trình khởi động và một quy trình khác, do Start-Process khởi chạy, để chạy tập lệnh. Dòng thứ hai của tệp bó cần được thay đổi thành:
PowerShell.exe -Command "& Bắt đầu xử lý PowerShell.exe -ArgumentList '-ExecutPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs"
Khi tệp bó được chạy, dòng đầu ra đầu tiên chúng ta sẽ thấy là từ tập lệnh cấu hình PowerShell. Sau đó, sẽ có một dấu nhắc UAC khi Start-Process cố gắng khởi chạy MyScript.ps1.
Sau khi nhấp qua lời nhắc UAC, một phiên bản PowerShell mới sẽ xuất hiện. Bởi vì đây là một ví dụ mới, tất nhiên, chúng ta sẽ lại thấy thông báo về kịch bản hồ sơ. Sau đó, MyScript.ps1 chạy và chúng tôi thấy rằng chúng tôi thực sự đang ở trong một phiên nâng cao.
Và có lý do chúng tôi cũng có hai lần tạm dừng ở đây. Nếu không phải là một trong tập lệnh PowerShell, chúng ta sẽ không bao giờ thấy đầu ra của tập lệnh - cửa sổ PowerShell sẽ bật lên và biến mất ngay khi tập lệnh được chạy xong. Và không có tạm dừng trong tệp bó, chúng tôi sẽ không thể biết liệu có lỗi nào khởi chạy PowerShell ở vị trí đầu tiên không.
Bước 4: Di chuyển xung quanh các cấu hình PowerShell tùy chỉnh.
Bây giờ chúng ta hãy loại bỏ thông báo hồ sơ tùy chỉnh khó chịu đó, phải không? Ở đây, điều đó thậm chí không gây phiền toái, nhưng nếu cấu hình PowerShell của người dùng thay đổi cài đặt, biến hoặc chức năng mặc định theo cách bạn có thể không lường trước được với tập lệnh của mình, thì chúng có thể thực sự gây rắc rối. Việc chạy tập lệnh của bạn mà không có hồ sơ hoàn toàn đơn giản hơn nhiều nên bạn không phải lo lắng về điều này. Để làm điều đó, chúng ta chỉ cần thay đổi dòng thứ hai của tệp bó một lần nữa:
PowerShell.exe -NoProfile -Command "& Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs"
Thêm tham số -NoProfile vào cả hai phiên bản PowerShell được khởi chạy bởi tập lệnh có nghĩa là tập lệnh hồ sơ của người dùng sẽ được bỏ qua hoàn toàn trong cả hai bước và tập lệnh PowerShell của chúng tôi sẽ chạy trong môi trường mặc định, khá dễ đoán. Ở đây, bạn có thể thấy không có thông báo hồ sơ tùy chỉnh trong một trong hai vỏ được sinh ra.
Nếu bạn không cần quyền Quản trị viên trong tập lệnh PowerShell và bạn đã bỏ qua Bước 3, bạn có thể thực hiện mà không cần phiên bản PowerShell thứ hai và dòng thứ hai của tệp bó của bạn sẽ như sau:
PowerShell.exe -NoProfile -ExecutPolicy Bypass -Command "& '% ~ dpn0.ps1'"
Đầu ra sau đó sẽ trông như thế này:
(Tất nhiên, đối với các tập lệnh không phải là Quản trị viên, bạn có thể thực hiện mà không cần tạm dừng kết thúc tập lệnh trong tập lệnh PowerShell của mình tại thời điểm này vì mọi thứ được ghi lại trong cùng một cửa sổ bảng điều khiển và sẽ được giữ ở đó bằng cách tạm dừng ở cuối tập tin bó nào.)
Tập tin lô đã hoàn thành.
Tùy thuộc vào việc bạn có cần quyền của Quản trị viên cho tập lệnh PowerShell hay không (và bạn thực sự không nên yêu cầu họ nếu bạn không), tệp bó cuối cùng sẽ trông giống như một trong hai tập tin dưới đây.
Không có quyền truy cập của quản trị viên:
@ECHO TẮT PowerShell.exe -KhôngProfile -ExecutPolicy Bypass -Command "& '% ~ dpn0.ps1'" PAUSE
Với quyền truy cập của quản trị viên:
@ECHO TẮT PowerShell.exe -NoProfile -Command "& Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs" PAUSE
Hãy nhớ đặt tệp bó trong cùng thư mục với tập lệnh PowerShell mà bạn muốn sử dụng và đặt cùng tên. Sau đó, bất kể bạn đưa các tệp đó vào hệ thống nào, bạn sẽ có thể chạy tập lệnh PowerShell của mình mà không phải thực hiện bất kỳ cài đặt bảo mật nào trên hệ thống. Bạn chắc chắn có thể thực hiện các thay đổi đó theo cách thủ công mọi lúc, nhưng điều này giúp bạn tránh được rắc rối đó và bạn sẽ không phải lo lắng về việc hoàn nguyên các thay đổi sau này.
Tài liệu tham khảo:
- Chạy các tập lệnh PowerShell từ một tệp bó - Blog lập trình của Daniel Schroeder's
- Kiểm tra quyền của Quản trị viên trong PowerShell - Hey, Scripting Guy! Blog