liên quan:
Should I include a command line mode in my applications?
How to grab parent process standard output?
Can a console application detect if it has been run from Explorer?Có thể xây dựng một ứng dụng Console không hiển thị cửa sổ bảng điều khiển khi nhấp đúp không?
Tôi muốn xây dựng một ứng dụng giao diện điều khiển, đó là bình thường chạy từ dòng lệnh.
Nhưng, khi nó được nhấp đúp từ bên trong Explorer (trái với việc chạy từ dấu nhắc cmd.exe) thì tôi muốn chương trình KHÔNG hiển thị cửa sổ bảng điều khiển.
Tôi muốn tránh điều này:
alt text http://i36.tinypic.com/1088p5s.jpg
Có thể?
EDIT Tôi đoán một cách khác để hỏi nó là, là nó có thể cho một chương trình để biết làm thế nào nó đã được gọi - cho dù bằng cách double-click hoặc bằng dòng lệnh?
Tôi đang làm việc trong .NET, trên Windows.
CHỈNH SỬA 2: Từ this Old New Thing blog post Tôi đã học được một số nội dung hay. Dưới đây là những gì tôi biết bây giờ ...
Trong Windows, các tệp EXE được đánh dấu là GUI hoặc không phải GUI. Với csc.exe, điều này được chọn với /target:winexe
hoặc /target:exe
. Trước khi lệnh đầu tiên trong tiến trình thực thi, hạt nhân Windows thiết lập môi trường thực thi. Tại thời điểm đó, nếu EXE được đánh dấu GUI, hạt nhân thiết lập stdin/stdout cho tiến trình thành NULL, và nếu non-GUI (dòng lệnh) hạt nhân tạo một bảng điều khiển và đặt stdin/stdout cho quá trình đó giao diện điều khiển.
Khi khởi chạy quá trình, nếu không có stdin/stdout (== /target:winexe
), thì cuộc gọi sẽ trả về ngay lập tức. Vì vậy, khởi chạy một ứng dụng gui từ một cmd.exe, bạn sẽ ngay lập tức nhận được nhắc nhở cmd của bạn trở lại. Nếu có một stdin/stdout, và nếu chạy từ cmd.exe, thì cmd.exe cha mẹ chờ quá trình thoát.
"Trả về ngay lập tức" rất quan trọng vì nếu bạn mã ứng dụng GUI để đính kèm vào bảng điều khiển của cha mẹ, bạn có thể thực hiện giao diện điều khiển.vv. Nhưng lời nhắc cmd.exe đang hoạt động. Người dùng có thể gõ lệnh mới, bắt đầu một quy trình mới, v.v. Nói cách khác, từ một winexe, chỉ cần gắn vào bảng điều khiển cha với AttachConsole(-1)
sẽ không "biến nó thành" một ứng dụng giao diện điều khiển.
Tại thời điểm này tôi nghĩ rằng cách duy nhất để cho phép ứng dụng sử dụng giao diện điều khiển nếu nó được gọi từ cmd.exe, và KHÔNG sử dụng nó nếu nó là kích đúp, là để xác định exe như một bảng điều khiển thông thường exe (/target:exe
) và ẩn cửa sổ khi khởi động nếu thích hợp. Bạn vẫn nhận được một cửa sổ giao diện điều khiển xuất hiện một thời gian ngắn.
Tôi vẫn chưa tìm ra cách để biết liệu nó đã được khởi chạy từ trình thám hiểm hay cmd.exe, nhưng tôi đang tiến gần hơn ..
TRẢ LỜI
Nó không phải là có thể xây dựng một ứng dụng giao diện điều khiển không hiển thị một cửa sổ giao diện điều khiển.
Nó là có thể để tạo ứng dụng bảng điều khiển ẩn cửa sổ của ứng dụng rất nhanh, nhưng không quá nhanh đến mức cửa sổ không bao giờ xuất hiện.
Bây giờ, để xác định xem một ứng dụng giao diện điều khiển đã được đưa ra từ nhà thám hiểm, một số người đã đề nghị phải nhìn vào giao diện điều khiển nó đang chạy trong
(từ mgb's answer, và KB article 99115):
int left = Console.CursorLeft;
int top = Console.CursorTop;
bool ProcessWasRunFromExplorer = (left==0 && top==0);
này cho quý vị nếu quá trình này đã được khởi chạy trong bảng điều khiển của riêng nó, nhưng không phải là nó là nhà thám hiểm. Một cú nhấp đúp trong thám hiểm sẽ làm điều này, nhưng cũng là một Start.Process() từ bên trong một ứng dụng sẽ làm điều tương tự.
Nếu bạn muốn đối xử với những tình huống khác nhau, sử dụng này để tìm hiểu tên của quá trình cha mẹ:
System.Console.WriteLine("Process id: {0}", Process.GetCurrentProcess().Id);
string name = Process.GetCurrentProcess().ProcessName ;
System.Console.WriteLine("Process name: {0}", name);
PerformanceCounter pc = new PerformanceCounter("Process", "Creating Process Id", name);
Process p = Process.GetProcessById((int)pc.RawValue);
System.Console.WriteLine("Parent Process id: {0}", p.Id);
System.Console.WriteLine("Parent Process name: {0}", p.ProcessName);
// p.ProcessName == "cmd" or "Explorer" etc
Để ẩn cửa sổ một cách nhanh chóng sau khi quá trình này được đưa ra, sử dụng này:
private static readonly int SW_HIDE= 0;
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);
....
{
IntPtr myHandle = Process.GetCurrentProcess().MainWindowHandle;
ShowWindow(myHandle, SW_HIDE);
}
Nếu bạn sản xuất winexe
(ứng dụng WinForms) và tùy chọn đính kèm vào bảng điều khiển chính khi thích hợp với AttachConsole(-1)
, bạn không nhận được tương đương với ứng dụng bảng điều khiển thông thường. Đối với một winexe, quá trình cha mẹ (như cmd.exe) sẽ trở lại dấu nhắc lệnh ngay lập tức sau khi bắt đầu một ứng dụng GUI. Nói cách khác, dấu nhắc lệnh đang hoạt động và sẵn sàng cho đầu vào trong khi quá trình vừa được khởi chạy có thể phát ra đầu ra. Điều này là khó hiểu và có lẽ chỉ hữu ích để gỡ lỗi các ứng dụng winforms.
Điều này phù hợp với tôi.
Bạn muốn thay vào đó làm gì? –
Tôi muốn nó vô hình. – Cheeso
Kiểm tra để xác định xem chương trình đã được khởi động trong bảng điều khiển của riêng nó có sai không. Việc nhập 'cls & program.exe' vào dòng lệnh sẽ báo lỗi rằng chương trình đã được bắt đầu trong giao diện điều khiển của riêng nó. Bạn có thể làm điều tương tự từ một tập tin thực thi. Có khả năng có nhiều cách khác để đánh bại bài kiểm tra. –