2011-10-26 32 views
11

Tôi đã viết một máy chủ ssh trong C# và tôi nghĩ rằng nó sẽ được gọn gàng để treo lên powershell như một vỏ. Tôi đã thử 2 phương pháp để có được điều này để làm việc đúng cách, nhưng cả hai đều xa hoàn hảo. Dưới đây là những gì tôi đã thử:Có thể giả mạo cửa sổ giao diện điều khiển api không?

  1. Khởi chạy powershell.exe và chuyển hướng nó là std (vào/ra). Điều này không hoạt động tốt kể từ khi powershell.exe phát hiện nó được chuyển hướng, thay đổi hành vi của nó. Hơn nữa, nó hy vọng dữ liệu đầu vào trên các lệnh stdid, không phải là . Vì vậy, nó sử dụng giao diện điều khiển api để đọc lệnh.
  2. Quyền tác giả lưu trữ trong ứng dụng "trình bao bọc". Điều này có lợi thế là có thể cung cấp triển khai "bảng điều khiển" cho quyền hạn (thông qua PSHostRawUserInterface). Điều này hoạt động tốt hơn, nhưng bạn vẫn có thể gọi các lệnh (chủ yếu là các ứng dụng giao diện điều khiển thực) như "... | more", mong đợi để có thể sử dụng giao diện điều khiển api và sau đó cố đọc từ bảng điều khiển của trình bao bọc quá trình.

Vì vậy, những gì tôi muốn làm là có một bộ chức năng thay thế các chức năng đầu vào/đầu ra bàn điều khiển thông thường mà ứng dụng giao diện điều khiển sử dụng, vì vậy tôi có thể xử lý chúng. Nhưng điều đó có vẻ khá quyết liệt đến mức trở thành một ý tưởng thiết kế tồi tệ (imo).

Ngay bây giờ tôi đang trên ý tưởng thao tác bảng điều khiển bằng cách gửi các khóa có liên quan với các hàm gốc/Pinvoke như WriteConsoleInput. Tôi thu thập rằng nó có thể có thể giả mạo giao diện điều khiển theo cách đó. Nhưng tôi không thấy làm thế nào tôi sẽ "đọc" những gì xảy ra trên bàn điều khiển.

Cũng nên nhớ, đó là dịch vụ, vì vậy tốt nhất là không nên tạo ra một cửa sổ giao diện điều khiển thực tế, mặc dù có thể trong cửa sổ phiên 0 không hiển thị và không quan trọng.

Trả lời

3

Bạn có PSSession cho mục đích này và Enter-PSSession CmdLet. SSH của bạn với Powershell sẽ làm gì mà PSSession không làm?

Nhưng nếu bạn muốn làm điều đó ở đây là một giải pháp whithout writting bất cứ điều gì: Using PowerShell through SSH


Edited 02/11/2011

PowerShell inside cung cấp một cách khác để làm điều đó whithout writting bất cứ điều gì (miễn phí cho sử dụng cá nhân).

Host03 sample, có thể cung cấp mã cơ bản để làm những gì bạn cần làm.

+0

Vâng cho một tôi muốn truy cập ssh của tôi từ thiết bị di động Android của tôi. Tôi đã không nhìn thấy một khách hàng thực sự quyền năng cho điều đó. Có một phần "vui vẻ" tốt cho dự án này. Đối với Cygwin ... tôi cũng có vấn đề (có lẽ không hợp lý) với nó. –

+0

Bạn có thử cái này [PowerShellInside] (http: //www.powershellinside không.com/powershell/ssh/download.aspx). Nó tồn tại một phiên bản kết nối miễn phí. – JPBlanc

+0

Humm, một tìm kiếm liên tục, tôi sẽ kiểm tra nó. Làm cho tôi tự hỏi làm thế nào họ giải quyết được vấn đề mặc dù. –

1

Tôi đã cài đặt PowerShellInside theo đề xuất của JPBlanc, nhưng không sử dụng nó trong thời gian rất dài. Một điều kết nối chỉ là quá hạn chế, và tôi không thích bị hạn chế (đặc biệt là nếu giới hạn đó là lợi nhuận dựa nhưng đó là một cuộc thảo luận toàn bộ khác tôi không nên nhận được vào). Và mặc dù là một giải pháp cho vấn đề ban đầu, nó cảm thấy không đạt yêu cầu bởi vì nó không giải quyết được vấn đề lập trình mà tôi gặp phải.

Tuy nhiên, cuối cùng tôi đã xoay sở để giải quyết vấn đề đã nói, thực sự bằng cách sử dụng các lệnh gọi api của windows trong một quy trình bao bọc. Bởi vì có khá nhiều cạm bẫy, tôi quyết định anwser câu hỏi của riêng tôi và cung cấp cho những người khác xem cùng một vấn đề một số gợi ý. Cấu trúc cơ bản như sau:

  • Bắt đầu quy trình trình bao bằng stdin/-out chuyển hướng (và stderr nếu bạn muốn).(Trong trường hợp của tôi stdin và out sẽ là dòng các chuỗi điều khiển xterm và dữ liệu, bởi vì đó là cách ssh)
  • Sử dụng GetStdHandle() retrive các đầu vào chuyển hướng và đầu ra xử lý. Tiếp theo SetStdHandle() của CreateFile() của "CONIN $" và "CONOUT $", sao cho các tiến trình con kế thừa giao diện điều khiển và không có các chuyển hướng của trình bao bọc. (Lưu ý rằng một mô tả bảo mật cho phép kế thừa là cần thiết cho createfile)
  • Thiết lập chế độ bàn điều khiển, kích thước, tiêu đề, xử lý Ctrl-C, v.v. Lưu ý: hãy chắc chắn đặt phông chữ nếu bạn muốn hỗ trợ unicode. (.FontFamily = 54, .FaceName = "Bảng điều khiển Lucida"). Nếu không có điều này, việc đọc các ký tự từ đầu ra bàn điều khiển của bạn sẽ trả về các phiên bản được mã hóa, điều này thật kinh khủng khi làm việc với mã được quản lý.
  • Đầu ra đọc có thể được thực hiện với SetWinEventHook(), đảm bảo sử dụng thông báo ngoài ngữ cảnh, vì tôi khá chắc chắn rằng ứng dụng được quản lý của bạn đột nhiên chạy trong một không gian địa chỉ/ngữ cảnh quy trình khác là Bad Idea ™ (Tôi chắc chắn rằng tôi thậm chí không thử). Sự kiện này sẽ kích hoạt cho mọi cửa sổ bảng điều khiển, không chỉ riêng cửa sổ của bạn. Vì vậy, lọc tất cả các cuộc gọi đến gọi lại bằng cách xử lý cửa sổ. Truy xuất lại tay cầm cửa sổ của ứng dụng giao diện điều khiển hiện tại bằng GetConsoleWindow(). Cũng đừng quên hủy bỏ cuộc gọi lại khi ứng dụng được thực hiện.
  • Lưu ý, đến thời điểm này, hãy đảm bảo không sử dụng (hoặc thực hiện bất kỳ thứ gì gây tải) lớp System.Console hoặc nhiều thứ có khả năng sẽ sai. Việc sử dụng sau thời điểm này sẽ hoạt động như thể quá trình con đã ghi vào đầu ra.
  • đẻ trứng quá trình phụ cần thiết (Lưu ý, bạn phải sử dụng .UseShellExecute = false hoặc nó sẽ không kế thừa giao diện điều khiển)
  • Bạn có thể bắt đầu cung cấp đầu vào cho giao diện điều khiển sử dụng WriteConsoleInput()
  • Tại thời điểm này (hoặc trên một chủ đề riêng biệt), bạn phải chạy một vòng lặp tin nhắn của cửa sổ hoặc bạn sẽ không nhận được lời gọi lại thông báo sự kiện giao diện điều khiển. Bạn có thể chỉ cần sử dụng Application.Run() không cần thiết để làm điều này. Để phá vỡ vòng lặp tin nhắn, bạn phải tại một số điểm gửi một tin nhắn thoát ra cho vòng lặp tin nhắn của bạn. Tôi đã làm điều này với Application.Exit() trong sự kiện .Exited của tiến trình con. (Lưu ý sử dụng .EnableRaisingEvents để làm việc này)
  • Cuộc gọi giờ đây sẽ được thực hiện cho cuộc gọi lại sự kiện giành chiến thắng của bạn khi có điều gì đó trên bảng điều khiển của bạn thay đổi. Chú ý đến sự kiện cuộn, điều này có thể làm việc hơi bất ngờ. Cũng không đưa ra giả định về phân phối đồng bộ. Nếu tiến trình con viết 3 dòng, vào lúc bạn xử lý sự kiện đầu tiên, 3 dòng còn lại có thể đã được viết. Để công bằng, các cửa sổ thực hiện một công việc tốt đẹp để soạn các sự kiện như vậy mà bạn không bị thay đổi với các thay đổi ký tự đơn lẻ và có thể theo kịp với các thay đổi.
  • Đảm bảo đánh dấu tất cả các định nghĩa PInvoke bằng CharSet = CharSet.Unicode nếu chúng chứa ký tự ở bất kỳ đâu trong đầu vào hoặc đầu ra. PInvoke.net đã bỏ lỡ một vài trong số này.

Kết quả thực của tất cả điều này: ứng dụng trình bao bọc cho giao diện điều khiển cửa sổ api. Trình bao bọc có thể đọc/ghi stdin chuyển hướng và stdout để giao tiếp với thế giới. Ofcourse nếu bạn muốn có được ưa thích, bạn có thể sử dụng bất kỳ dòng ở đây (tên ống, tcp/ip, vv ..). Tôi đã thực hiện một vài chuỗi điều khiển xterm và quản lý để có được một trình bao terminal hoàn toàn hoạt động, có khả năng bao gói bất kỳ trình điều khiển cửa sổ nào, dịch đầu vào xterm để nhập vào đầu vào của ứng dụng đích và xử lý đầu ra của ứng dụng tới các chuỗi điều khiển xterm. Tôi thậm chí có con chuột để làm việc. Bắt đầu từ PowerShell.exe là tiến trình con bây giờ giải quyết vấn đề ban đầu của chạy PowerShell trong một phiên ssh. Cmd.exe cũng hoạt động. Nếu bất cứ ai bị can thiệp, tôi sẽ xem về việc đăng mã đầy đủ ở đâu đó.

+0

Điều này sẽ thật tuyệt vời nếu bạn có thể chia sẻ mã này. –

+0

Đánh dấu, đó có thể là giới hạn dựa trên lợi nhuận. –

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