Cách chạy ứng dụng bảng điều khiển C # với bảng điều khiển bị ẩn


140

Có cách nào để ẩn cửa sổ giao diện điều khiển khi thực hiện một ứng dụng giao diện điều khiển không?

Tôi hiện đang sử dụng ứng dụng Windows Forms để bắt đầu quá trình điều khiển, nhưng tôi không muốn cửa sổ giao diện điều khiển được hiển thị trong khi tác vụ đang chạy.


hãy thử chạy ứng dụng console từ tác vụ theo lịch trình.

Câu trả lời:


158

Nếu bạn đang sử dụng ProcessStartInfolớp, bạn có thể đặt kiểu cửa sổ thành ẩn - trong trường hợp các ứng dụng bảng điều khiển (không phải GUI), bạn phải đặt CreatNoWindow thành true:

System.Diagnostics.ProcessStartInfo start =
      new System.Diagnostics.ProcessStartInfo();
start.FileName = dir + @"\Myprocesstostart.exe";
start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; //Hides GUI
start.CreateNoWindow = true; //Hides console

26
Chỉ là những gì tôi sẽ đăng :)
Jon Skeet

75
Holy crap - ai đó nhanh hơn Jon! =)
Erik Forbes

75
Tôi đã phải điều tiết kết nối internet của anh ấy để đánh bại anh ấy;)
Adam Markowitz

11
Nó không hoạt động để gọi một công cụ dòng lệnh. Đã sử dụng your process.StartInfo.CreateNoWindow = true; thay vào đó, xem bên dưới.
Christian

12
Không ẩn cửa sổ giao diện điều khiển, StartInfo.CreateNoWindow = true là bắt buộc.
Daniel

201

Nếu bạn đã viết ứng dụng console, bạn có thể ẩn nó theo mặc định.

Tạo một ứng dụng bảng điều khiển mới sau đó thay đổi loại "Loại đầu ra" thành "Ứng dụng Windows" (được thực hiện trong thuộc tính dự án)


6
Tôi đã cố gắng để ẩn bảng điều khiển của riêng mình, không gọi một cái gì đó khác và sau đó ẩn nó (như giả định câu trả lời được chấp nhận) - vì vậy đây là cái tốt nhất cho tôi. cảm ơn!
iamserious

6
Cảm ơn cậu ! Đây là những gì tôi đang tìm kiếm quá!
Varun Sharma

3
Câu trả lời được chấp nhận cho rằng bởi vì nó được nêu trong câu hỏi.
thủy

Cách đơn giản nhất..thực sự thích nó..chúng tôi chắc chắn không muốn hiển thị cửa sổ vì nó sẽ khởi động một quy trình khác từ nó cho tôi ..
Sai Avinash

1
Điều này xoay quanh các vấn đề với ProcessStartInfo nơi bạn chỉ định thông tin đăng nhập của người dùng và người dùng đó tình cờ đăng nhập hoặc người dùng hiện tại. Trong tình huống đó, thuộc tính CreatNoWindow bị bỏ qua để bạn luôn có được cửa sổ giao diện điều khiển. Bằng cách đặt ứng dụng bảng điều khiển thành Ứng dụng Windows nhưng không có cửa sổ thì bạn không có cửa sổ.
tjmoore

67

Nếu bạn đang sử dụng Lớp quy trình thì bạn có thể viết

yourprocess.StartInfo.UseShellExecute = false;
yourprocess.StartInfo.CreateNoWindow = true;

trước yourprocess.start();và quá trình sẽ được ẩn


4
Chúc may mắn nếu bạn phải dừng quá trình đó sớm. Quá trình.Kill chấm dứt đột ngột. Process.CloseMainWindow không thành công. GenerateConsoleCtrlEvent không gửi được ctrl + c hoặc ctrl + break cho tiến trình. WM_CLOSE cho tất cả các cửa sổ luồng trong quá trình không thành công. Dường như không có cách nào để kết thúc một quá trình bắt đầu với hai giá trị tham số đó. Xem câu hỏi của tôi ở đây: stackoverflow.com/questions/16139571/ từ
Triynko

Cảm ơn tấn này là đơn giản nhất. Ngoài ra nếu bạn sở hữu (hoặc phòng) mã cho bàn điều khiển, tôi thấy ví dụ mutex này là dễ nhất để tắt máy. stackoverflow.com/a/31586184/1877412
cbuteau

1
@Triynko: Bạn không thể kết thúc một cách sạch sẽ bất kỳ quy trình nào, trừ khi quá trình đó tích cực hợp tác. Đây không phải là vấn đề cờ hay bất cứ điều gì khác. Không có gì trong HĐH có thể kích hoạt tắt máy sạch. Giải pháp phổ biến ở đây là sử dụng một đối tượng hạt nhân có thể chờ, được báo hiệu trong quá trình kiểm soát, khi quá trình nô lệ sẽ chấm dứt. Quá trình nô lệ cần chủ động theo dõi trạng thái của vật thể chờ đợi này và bắt đầu tắt máy một khi nó báo hiệu.
IInspectable 20/8/2016

43

Câu trả lời đơn giản là: Chuyển đến thuộc tính của ứng dụng bảng điều khiển (thuộc tính của dự án). Trong tab "Ứng dụng", chỉ cần thay đổi "Loại đầu ra" thành "Ứng dụng Windows". Đó là tất cả.


4
Bullseye. Điều này giống như việc tạo một ứng dụng Windows không gọi bất kỳ biểu mẫu nào.
tro999

1
Đây là câu trả lời chính xác. Không có cách tiếp cận nào khác của bạn. Đây là câu trả lời ĐÚNG thực tế. Bạn muốn ứng dụng của bạn không bao giờ mở giao diện điều khiển ở nơi đầu tiên. Ngoài ra, bạn muốn có thể mở một biểu mẫu bất cứ lúc nào. Vì vậy, bạn chỉ cần gọi các hình thức khi bạn muốn. tức là biểu mẫu của chúng tôi được gọi khi người dùng nhấp chuột phải vào biểu tượng khay hệ thống và chọn tùy chọn. ĐÂY LÀ CÂU TRẢ LỜI ĐÚNG!!!
Bluebaron

20

Bạn có thể sử dụng API FreeConsole để tách bảng điều khiển khỏi quy trình:

[DllImport("kernel32.dll")]
static extern bool FreeConsole();

(tất nhiên điều này chỉ áp dụng nếu bạn có quyền truy cập vào mã nguồn của ứng dụng bảng điều khiển)


Tôi muốn không hiển thị giao diện điều khiển. Mặc dù FreeConsoletên của nó nói gì nhưng nó không ngăn Windows hiển thị bảng điều khiển trước khi được gọi.
Jader Dias

5
Sau đó biên dịch dự án dưới dạng Ứng dụng Windows, không phải Ứng dụng Console
Thomas Levesque

1
Đối với hồ sơ, đây là chính xác những gì tôi cần, cảm ơn. Nó cũng chính xác là những gì tiêu đề yêu cầu :) Vì vậy, trong mối quan tâm của những người đi du lịch google khác, +1
sehe

3
Ngoài ra, [DllImport("kernel32.dll")] static extern bool AllocConsole();cho phép bạn dễ dàng chạy với bảng điều khiển từ ứng dụng Win32 tiêu chuẩn
sehe

1
Hoạt động cho ứng dụng .NET Core 2.2 của tôi - nếu bất kỳ ai đang tìm kiếm điều này một cách cụ thể.
Medismal

7

Nếu bạn quan tâm đến đầu ra, bạn có thể sử dụng chức năng này:

private static string ExecCommand(string filename, string arguments)
{
    Process process = new Process();
    ProcessStartInfo psi = new ProcessStartInfo(filename);
    psi.Arguments = arguments;
    psi.CreateNoWindow = true;
    psi.RedirectStandardOutput = true;
    psi.RedirectStandardError = true;
    psi.UseShellExecute = false;
    process.StartInfo = psi;

    StringBuilder output = new StringBuilder();
    process.OutputDataReceived += (sender, e) => { output.AppendLine(e.Data); };
    process.ErrorDataReceived += (sender, e) => { output.AppendLine(e.Data); };

    // run the process
    process.Start();

    // start reading output to events
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();

    // wait for process to exit
    process.WaitForExit();

    if (process.ExitCode != 0)
        throw new Exception("Command " + psi.FileName + " returned exit code " + process.ExitCode);

    return output.ToString();
}

Nó chạy chương trình dòng lệnh đã cho, đợi cho nó kết thúc và trả về đầu ra dưới dạng chuỗi.


4

Nếu bạn đang tạo một chương trình không yêu cầu đầu vào của người dùng, bạn luôn có thể tạo chương trình đó như một dịch vụ. Một dịch vụ sẽ không hiển thị bất kỳ loại UI nào.


Nhưng nếu tất cả những gì bạn muốn làm là chạy quy trình cho đến khi nó thoát, ví dụ như bằng cách gọi nó từ Trình lập lịch tác vụ, thì một dịch vụ sẽ bất tiện khi nó tiếp tục tồn tại. Trong một số trường hợp, việc thay đổi Loại đầu ra thành Ứng dụng Windows so với ProcessWindowStyle thay thế là ẩn rất thuận tiện.
subsci

2

Thêm phần này vào lớp của bạn để nhập tệp DLL:

[DllImport("user32.dll")] 
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 

[DllImport("kernel32.dll")] 
static extern IntPtr GetConsoleWindow();

const int SW_HIDE = 0;
const int SW_SHOW = 5;

Và sau đó nếu bạn muốn ẩn nó, hãy sử dụng lệnh này:

 var handle = GetConsoleWindow();
 ShowWindow(handle, SW_HIDE);

Và nếu bạn muốn hiển thị bảng điều khiển:

var handle = GetConsoleWindow();
ShowWindow(handle, SW_SHOW);

1
[DLLImport ("user32.dll")] bool extern tĩnh ShowWindow (IntPtr hWnd, int nCmdShow); [DLLImport ("kernel32.dll")] tĩnh ngoài IntPtr GetConsoleWindow (); const int SW_HIDE = 0; const int SW_SHOW = 5;
soulmachine

1

Tôi biết tôi không trả lời chính xác những gì bạn muốn, nhưng tôi tự hỏi liệu bạn có hỏi đúng câu hỏi không.

Tại sao bạn không sử dụng một trong hai:

  1. dịch vụ windows
  2. tạo một chủ đề mới và chạy quy trình của bạn trên đó

Những âm thanh đó giống như các tùy chọn tốt hơn nếu tất cả những gì bạn muốn là chạy một tiến trình.


3
Có rất nhiều tình huống trong đó việc khởi chạy một ứng dụng bảng điều khiển tiện ích là hoàn toàn hợp pháp.
Adam Robinson

Trong trường hợp của tôi, một quy trình riêng là cần thiết vì mô hình máy khách / máy chủ mà phần mềm tôi đang sử dụng.
Aaron Thomas

Nó không phải luôn luôn giải quyết vấn đề để tạo ra một chủ đề mới. Có những lúc bạn không muốn cửa sổ khó chịu ở chế độ nền. Ngoài ra, nếu bạn có một process.start trong một vòng lặp, thì bạn sẽ không hoàn thành bất kỳ công việc nào khi các cửa sổ điều khiển bật lên trên khuôn mặt của bạn.
dùng89032

1
Tôi khởi chạy các ứng dụng bảng điều khiển tiện ích không có cửa sổ từ Trình lập lịch tác vụ. Không cần dịch vụ, và không có quá trình cha mẹ để từ đó rẽ nhánh một luồng. Các ứng dụng này ghi vào EventLog nếu cần thêm đầu ra.
subsci

1

Mặc dù như các câu trả lời khác ở đây đã nói rằng bạn có thể thay đổi "Loại đầu ra" thành "Ứng dụng Windows", xin lưu ý rằng điều này có nghĩa là bạn không thể sử dụng Console.Invì nó sẽ trở thành NullStreamReader.

Console.OutConsole.Errordường như vẫn hoạt động tốt.


2
Bạn nghiêm túc chứ? Tại sao mọi người sẽ sử dụng Console.Inkhi không có bàn điều khiển để nhập một cái gì đó? Bất cứ điều gì nên đến từ đó có thể được truy cập thông qua Console.In? Điều này không có ý nghĩa gì cả. Nói cách khác: Đó là hoàn toàn rõ ràng và hợp lý mà Console.Inlà một NullStreamReadertrong trường hợp này.
Robert S.

1
@RobertS. Một đường ống có thể. Tức là đầu ra của một chương trình khác. Đó là trường hợp sử dụng của tôi khi tôi phát hiện ra điều này.
kjbartel

1

Dựa trên câu trả lời của Adam Markowitz ở trên, những điều sau đây có tác dụng với tôi:

process = new Process();
process.StartInfo = new ProcessStartInfo("cmd.exe", "/k \"" + CmdFilePath + "\"");
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
//process.StartInfo.UseShellExecute = false;
//process.StartInfo.CreateNoWindow = true;
process.Start();

1

Tôi đã có một giải pháp chung để chia sẻ:

using System;
using System.Runtime.InteropServices;

namespace WhateverNamepaceYouAreUsing
{
    class Magician
    {
        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        const int HIDE = 0;
        const int SHOW = 5;

        public static void DisappearConsole()
        {
            ShowWindow(GetConsoleWindow(), HIDE);
        }
    }
}

Chỉ cần bao gồm lớp này trong dự án của bạn, và gọi Magician.DisappearConsole();.

Một giao diện điều khiển sẽ nhấp nháy khi bạn khởi động chương trình bằng cách nhấp vào nó. Khi thực hiện từ dấu nhắc lệnh, dấu nhắc lệnh sẽ biến mất rất nhanh sau khi thực thi.

Tôi làm điều này cho Bot Discord chạy mãi trong nền máy tính của tôi như một quá trình vô hình. Nó dễ hơn là để TopShelf làm việc cho tôi. Một vài hướng dẫn TopShelf đã làm tôi thất bại trước khi tôi viết bài này với một số trợ giúp từ mã tôi tìm thấy ở nơi khác. ; P

Tôi cũng đã cố gắng đơn giản thay đổi cài đặt trong Visual Studio> Project> Properties> Application để khởi chạy dưới dạng Ứng dụng Windows thay vì Ứng dụng Console và điều gì đó về dự án của tôi đã ngăn điều này ẩn bảng điều khiển của tôi - có lẽ vì DSharpPlus yêu cầu khởi chạy bảng điều khiển khi khởi động . Tôi không biết. Dù lý do là gì, lớp này cho phép tôi dễ dàng giết bàn điều khiển sau khi nó bật lên.

Hy vọng pháp sư này sẽ giúp được ai đó. ;)


0

Chỉ viết

ProcessStartInfo psi= new ProcessStartInfo("cmd.exe");
......

psi.CreateNoWindow = true;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.