2010-01-23 19 views
15

Tôi cần có khả năng bắt đầu quy trình (cả bàn điều khiển và cửa sổ) mà không bị lấy cắp tiêu điểm. Cách duy nhất trong khuôn khổ .NET mà tôi tìm thấy để thực hiện điều này là Microsoft.VisualBasic.Interaction.Shell với Microsoft.VisualBasic.AppWinStyle. [Thu nhỏ | Bình thường] NoFocus (ánh xạ tới SW_SHOWMINNOACTIVE/SW_SHOWMA được chuyển tới ShellExecute).Bắt đầu một quá trình mà không lấy cắp tiêu điểm (C#)

Trong phiên bản hiện tại của mã của tôi (mà không lấy được tiêu điểm), tôi đang sử dụng System.Diagnostics.Process và dựa vào một số chức năng cung cấp cho tôi, phương thức Interaction.Shell thì không.

2 câu hỏi (một nghiêm trọng, và một trút sự thất vọng của tôi mà tôi không thực sự mong đợi một câu trả lời tốt đến)

1.) Tôi thích hợp mà tôi không có lựa chọn nào khác để bọc CreateProcess hoặc ShellExecuteEx bản thân mình, hoặc tôi thiếu một số giải pháp khác? Tôi đã thực sự hy vọng để tránh điều này, vì Process là một wrapper hoàn chỉnh và hữu ích khác với sự giám sát này, và sẽ có rất nhiều chức năng để thực hiện, P/Invoke các cuộc gọi để gỡ lỗi, và tất cả các loại đau đớn. 2. Tại sao một nhóm ở Microsoft tạo ra một trình bao bọc hoàn chỉnh (nếu không), và sau đó loại trừ một nửa các giá trị có thể có từ ProcessWindowStyle, trong khi một nhóm khác đã tạo ra một trình bao bọc tương tự ít hoàn chỉnh hơn, nhưng cung cấp tất cả phong cách cửa sổ hữu ích?

+0

Bạn đang mã hóa thứ gì đó bạn không muốn người dùng biết hoặc không muốn làm phiền người dùng? LOL nevermind ...: -/ – jasonco

+1

Không có lựa chọn? Không gian tên Microsoft.VisualBasic là một phần của khung công tác .NET và có sẵn trên bất kỳ cài đặt .NET nào. Không sử dụng nó sẽ là một sai lầm.Nó có nhiều tính năng khác nhưng bạn không thể tìm ra nếu bạn không thể vượt qua tên không gian tên. –

+0

Hi nobugz, tôi xin lỗi nếu tôi cho ấn tượng rằng tôi đã có một vấn đề với không gian tên. Đó không phải là vấn đề của tôi, trên thực tế tôi sử dụng một trình phân tích cú pháp tốt đẹp từ Microsoft.VisualBasic trong một phần khác của mã. Vấn đề là Microsoft.VisualBasic.Interaction.Shell không cho tôi khả năng được thông báo khi thoát hoặc hủy bỏ một tiến trình. Tôi sẽ phải bằng cách nào đó quấn nó để có được chức năng đó, trong đó lớp Process cho tôi cả những thứ đó. – psm321

Trả lời

11

Nhóm VB.Net đã thực hiện nhiều điều hơn nữa để làm cho nhà phát triển liên quan đến thiết bị, và tôi thấy không có vấn đề gì khi thêm một tham chiếu tới một dll VB và sử dụng trong chương trình C# của bạn.

Đó là hai đội có trọng tâm khác nhau, đó là tất cả. Và bạn không nên cảm thấy xấu về việc sử dụng Microsoft.VisualBasic.Interaction.Shell nếu nó giải quyết được vấn đề của bạn.

Bạn cũng có thể sử dụng Trình phản xạ để xem việc triển khai thực tế và tự triển khai mã nếu bạn không muốn tham chiếu dll.

[Chỉnh sửa - thêm mã ví dụ sau khi bình luận để hiển thị bạn có thể kết hợp Interaction.Shell và Process]

int pid = Interaction.Shell("notepad.exe", AppWinStyle.NormalFocus); 
Process p = Process.GetProcessById(pid); 
p.Exited += ((o, e) => Console.WriteLine("Exit")); 
p.EnableRaisingEvents = true; 
Console.ReadLine(); 

Ở đây tôi sử dụng phương pháp Shell để kick off quá trình này, có được một xử lý cho quá trình từ pid, và móc vào các sự kiện. Bạn thậm chí có thể làm p.Kill() để hủy bỏ quá trình.

[Edit - workaround cho cmd.exe]

Nó bắt đầu trở thành một chút hackish để hương vị của tôi, nhưng nó hoạt động. Thay thế "NEWWINDOW" bằng một hướng dẫn ngẫu nhiên hoặc một cái gì đó để làm cho nó độc đáo.

Microsoft.VisualBasic.Interaction.Shell(@"cmd.exe /c ""start cmd.exe /k title NEWWINDOW""", AppWinStyle.NormalFocus); 
foreach (var process in Process.GetProcessesByName("cmd")) 
{ 
    if (process.MainWindowTitle.EndsWith("NEWWINDOW")) 
    { 
     process.Exited += ((o, e) => Console.WriteLine("Exit")); 
     process.EnableRaisingEvents = true; 
    } 
} 
+0

Tôi không có một vấn đề với việc sử dụng không gian tên Microsoft.VisualBasic. Vấn đề của tôi là thiếu các chức năng khác trong phương thức đó (thiếu một sự kiện đã thoát và khả năng hủy bỏ một tiến trình). Tôi đã xem xét nguồn gỡ lỗi mà Microsoft cung cấp cho cả hai phương pháp ... đó là cách tôi đã học về các cuộc gọi cơ bản và các cờ được truyền để thực hiện công việc này. Đó cũng là cách tôi nghĩ rằng việc cố gắng xử lý một số chức năng mà tôi muốn một mình sẽ rất đau đớn, vì dường như có các vấn đề về khóa phức tạp và tôi không thể sao chép mã vì nó vi phạm giấy phép. – psm321

+0

ý tưởng tuyệt vời! Tôi sẽ thử nó vào thứ hai và có thể chấp nhận câu trả lời. cảm ơn! – psm321

+0

Điều đó làm việc, nhưng có một sự phức tạp ... có vẻ như gọi Interaction.Shell() từ một ứng dụng bàn điều khiển, để chạy một ứng dụng giao diện điều khiển, sử dụng lại cùng một cửa sổ bảng điều khiển thay vì khởi chạy một cái mới như Console.Start. Bất kỳ ý tưởng nếu nó có thể tránh điều đó? – psm321

2

Có một cái nhìn ở đây:

 
System.Diagnostics.ProcessStartInfo procInfo = new System.Diagnostics.ProcessStartInfo(); 
procInfo.CreateNoWindow = true; 
procInfo.UseShellExecute = true; 
procInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
System.Diagnostics.Process proc = new System.Diagnostics.Process(); 
proc.StartInfo = procInfo; 
proc.EnableRaisingEvents = true; 
proc.Exited += new EventHandler(proc_Exited); 
proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived); 
proc.Start(...) 
// Do something with proc.Handle... 
void proc_OutputDataReceived(object sender, DataReceivedEventArgs e) 
{ 
    /* Do something here... */ 
} 

void proc_Exited(object sender, EventArgs e) 
{ 
/* Do something here... */ 
} 

Edit: tôi đã sửa đổi mã để hiển thị các phương tiện nâng cao sự kiện và xử lý chúng, cũng, tôi đã cho thấy việc sử dụng các Handle tài sản đó là xử lý của quá trình đang chạy.

+0

Cảm ơn con trỏ. Thật không may, ẩn không làm những gì tôi muốn, kể từ 1.) từ những gì tôi thu thập, nó chỉ là tư vấn cho các ứng dụng bắt đầu và 2.) ngay cả khi đó không phải là trường hợp, tôi cần ứng dụng để được hiển thị cho người dùng nếu anh ta/cô ấy chọn tập trung nó, chỉ không ăn cắp lấy nét theo mặc định. Vì vậy, tôi _think_ những gì tôi thực sự cần là hành vi tương đương với SW_SHOWMINNOACTIVE hoặc SW_SHOWMA (http://msdn.microsoft.com/en-us/library/ms633548%28VS.85%29.aspx), mà phương thức Shell() cung cấp, nhưng tiếc là không cung cấp cho tôi trở lại một quá trình xử lý mà tôi có thể thiết lập một sự kiện đã thoát, vv – psm321

+0

@ psm321: Đầu tiên, mã tôi đưa vào, có một xử lý sự kiện đã thoát cho đối tượng proc như được hiển thị ở trên! Tại sao tái tạo lại bánh xe? Thứ hai, tôi nghi ngờ đó là một thiết lập toàn hệ thống toàn cầu, có lẽ bạn có một addon ở đâu đó, nơi lấy cắp tiêu điểm theo mặc định là một hành vi cửa sổ .. Giống như tự động nâng một cửa sổ mà không cần nhấp vào nó mang nó đến nền trước. – t0mm13b

+0

Và bằng cách này, Xử lý là tài sản của đối tượng proc trong đó bạn có một quy trình xử lý ... – t0mm13b

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