วิธีเรียกใช้แอปพลิเคชันคอนโซล C # ด้วยคอนโซลที่ซ่อนอยู่


141

มีวิธีซ่อนหน้าต่างคอนโซลเมื่อเรียกใช้แอปพลิเคชันคอนโซลหรือไม่

ขณะนี้ฉันกำลังใช้แอปพลิเคชัน Windows Forms เพื่อเริ่มกระบวนการคอนโซล แต่ฉันไม่ต้องการให้หน้าต่างคอนโซลปรากฏขึ้นในขณะที่งานกำลังทำงานอยู่


ลองเรียกใช้แอปพลิเคชันคอนโซลจากงานที่กำหนดเวลาไว้

คำตอบ:


158

หากคุณใช้ProcessStartInfoคลาสที่คุณสามารถตั้งค่าลักษณะหน้าต่างเป็นซ่อน - ในกรณีของแอปพลิเคชันคอนโซล (ไม่ใช่ GUI) คุณต้องตั้งค่า CreateNoWindow เป็น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
เพียงแค่สิ่งที่ผมจะโพสต์ :)
จอนสกีต

75
อึศักดิ์สิทธิ์ - ใครบางคนเร็วกว่าจอน! =)
Erik Forbes

75
ผมต้องเค้นการเชื่อมต่ออินเทอร์เน็ตของเขาที่จะเอาชนะเขา;)
อดัม Markowitz

11
มันไม่ทำงานสำหรับการเรียกใช้เครื่องมือบรรทัดคำสั่ง ใช้ yourprocess.StartInfo.CreateNoWindow = true; แทนดูด้านล่าง
คริสเตียน

12
ไม่ซ่อนหน้าต่างคอนโซล StartInfo.CreateNoWindow = true จำเป็นต้องมี
แดเนียล

201

หากคุณเขียนแอปพลิเคชันคอนโซลคุณสามารถซ่อนมันเป็นค่าเริ่มต้น

สร้างแอปคอนโซลใหม่จากนั้นเปลี่ยนประเภท "ประเภทเอาท์พุท" เป็น "แอปพลิเคชัน Windows" (ทำในคุณสมบัติโครงการ)


6
ฉันพยายามซ่อนคอนโซลของตัวเองไม่ได้โทรหาอย่างอื่นแล้วซ่อนไว้ (เช่นคำตอบที่ยอมรับ) - ดังนั้นนี่จึงเป็นสิ่งที่ดีที่สุดสำหรับฉัน ขอบคุณ!
iamserious

6
ขอบคุณเพื่อน ! นี่คือสิ่งที่ฉันกำลังมองหาเช่นกัน!
Varun Sharma

3
คำตอบที่ยอมรับถือว่าเป็นเพราะมันระบุไว้ในคำถาม
น้ำ

วิธีที่ง่ายที่สุด .. ชอบจริงๆ .. เราไม่ต้องการแสดงหน้าต่างเพราะมันกำลังจะเปิดตัวกระบวนการอื่นจากนั้นสำหรับฉัน ..
Sai Avinash

1
อันนี้มีปัญหาเกี่ยวกับ ProcessStartInfo ที่คุณระบุข้อมูลประจำตัวผู้ใช้และผู้ใช้นั้นจะเข้าสู่ระบบหรือผู้ใช้ปัจจุบัน ในสถานการณ์นั้นคุณสมบัติ CreateNoWindow จะถูกข้ามดังนั้นคุณจะได้รับหน้าต่างคอนโซลเสมอ โดยการตั้งค่าแอพคอนโซลเป็น Windows Application แต่ไม่มีหน้าต่างคุณจะไม่มีหน้าต่าง
tjmoore

67

หากคุณกำลังใช้คลาสประมวลผลคุณสามารถเขียนได้

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

ก่อนyourprocess.start();และกระบวนการจะถูกซ่อนไว้


4
โชคดีถ้าคุณต้องหยุดกระบวนการก่อน กระบวนการยุติทันที Process.CloseMainWindow ล้มเหลว GenerateConsoleCtrlEvent ล้มเหลวในการส่งตัวแบ่ง ctrl + c หรือ ctrl + ไปยังกระบวนการ WM_CLOSE ในเธรด windows ทั้งหมดในกระบวนการล้มเหลว ดูเหมือนจะไม่มีทางที่จะจบกระบวนการอย่างสมบูรณ์ด้วยค่าพารามิเตอร์ทั้งสอง ดูคำถามของฉันที่นี่: stackoverflow.com/questions/16139571/ …
Triynko

ขอบคุณตันนี่เป็นวิธีที่ง่ายที่สุด นอกจากนี้หากคุณเป็นเจ้าของ (หรือ dept) รหัสสำหรับคอนโซลฉันพบว่าตัวอย่าง mutex นี้จะง่ายที่สุดสำหรับการปิดระบบใหม่ทั้งหมด stackoverflow.com/a/31586184/1877412
cbuteau

1
@Triynko: คุณไม่สามารถยุติกระบวนการใด ๆ ได้อย่างสมบูรณ์เว้นแต่ว่ากระบวนการนั้นจะทำงานร่วมกันอย่างแข็งขัน นี่ไม่ใช่เรื่องของธงหรือสิ่งอื่นใด ไม่มีอะไรในระบบปฏิบัติการที่สามารถปิดการทำงานได้อย่างสมบูรณ์ วิธีแก้ปัญหาทั่วไปที่นี่คือการใช้เคอร์เนลวัตถุที่รอได้ซึ่งเป็นสัญญาณในกระบวนการควบคุมเมื่อกระบวนการทาสควรยุติ กระบวนการทาสต้องติดตามสถานะของวัตถุที่รอได้นี้อย่างกระตือรือร้นและเริ่มต้นการปิดระบบใหม่ทั้งหมดเมื่อมีการส่งสัญญาณ
IIsspectable

43

คำตอบง่ายๆคือ: ไปที่คุณสมบัติของแอปคอนโซล (คุณสมบัติของโครงการ) ในแท็บ "แอปพลิเคชัน" เพียงแค่เปลี่ยน "ประเภทเอาท์พุท" เป็น "แอปพลิเคชัน Windows" นั่นคือทั้งหมดที่


4
เป้า สิ่งนี้เหมือนกับการสร้างแอปพลิเคชัน Windows ที่ไม่ได้เรียกฟอร์มใด ๆ
ashes999

1
นี่คือคำตอบที่ถูกต้อง ไม่มีวิธีการ bandaid อื่น ๆ ของคุณ นี่คือคำตอบที่ถูกต้องจริง คุณต้องการให้แอปพลิเคชันของคุณไม่เคยเปิดคอนโซลตั้งแต่แรก นอกจากนี้คุณต้องการเปิดฟอร์มได้ตลอดเวลา ดังนั้นคุณเพียงแค่เรียกแบบฟอร์มเมื่อคุณต้องการ นั่นคือแบบฟอร์มของเราจะถูกเรียกเมื่อผู้ใช้คลิกขวาที่ไอคอนถาดระบบและเลือกการตั้งค่า นี่คือคำตอบที่ถูกต้อง !!!
Bluebaron

20

คุณสามารถใช้FreeConsole API เพื่อแยกคอนโซลออกจากกระบวนการ:

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

(แน่นอนว่าสิ่งนี้ใช้ได้เฉพาะเมื่อคุณมีสิทธิ์เข้าถึงซอร์สโค้ดของแอปพลิเคชันคอนโซล)


ฉันต้องการที่จะไม่แสดงคอนโซล ในขณะFreeConsoleที่ชื่อของมันบอกว่ามันไม่ได้ป้องกัน Windows จากการแสดงคอนโซลก่อนที่มันจะถูกเรียก
Jader Dias

5
จากนั้นคอมไพล์โครงการเป็นแอปพลิเคชัน Windows ไม่ใช่แอปพลิเคชันคอนโซล
Thomas Levesque

1
สำหรับบันทึกนี้เป็นสิ่งที่ฉันต้องการจริงๆขอบคุณ นอกจากนี้ยังเป็นว่าสิ่งที่ชื่อขอ :) ดังนั้นในความสนใจของทัศนียภาพอื่น ๆ ของ Google ที่ 1
sehe

3
นอกจาก[DllImport("kernel32.dll")] static extern bool AllocConsole();จะช่วยให้คุณทำงานได้อย่างง่ายดายกับคอนโซลจากมาตรฐาน Win32 โปรแกรม
sehe

1
ใช้งานได้กับแอป. NET Core 2.2 ของฉัน - หากใครก็ตามที่กำลังมองหาสิ่งนี้
Medismal

7

หากคุณสนใจในผลลัพธ์คุณสามารถใช้ฟังก์ชันนี้:

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();
}

มันรันโปรแกรมบรรทัดคำสั่งที่กำหนดรอให้มันเสร็จสิ้นและส่งออกเป็นสตริง


4

หากคุณกำลังสร้างโปรแกรมที่ไม่ต้องการการป้อนข้อมูลจากผู้ใช้คุณสามารถสร้างมันเป็นบริการได้เสมอ บริการจะไม่แสดง UI ประเภทใด


แต่หากสิ่งที่คุณต้องการทำคือเรียกใช้กระบวนการจนกว่าจะออกจากระบบเช่นโดยเรียกจาก Task Scheduler บริการจะไม่สะดวกตามที่มีอยู่ต่อไป ในบางสถานการณ์การเปลี่ยนประเภทเอาต์พุตเป็นแอปพลิเคชัน Windows เมื่อเทียบกับ ProcessWindowStyle ทางเลือกที่ซ่อนอยู่นั้นสะดวกมาก
subsci

2

เพิ่มลงในคลาสของคุณเพื่อนำเข้าไฟล์ 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;

และถ้าคุณต้องการซ่อนมันให้ใช้คำสั่งนี้:

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

และถ้าคุณต้องการแสดงคอนโซล:

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

1
[DllImport ("user32.dll")] คง extern บูล ShowWindow (IntPtr hWnd, int nCmdShow); [DllImport ("kernel32.dll")] คง extern ภายนอก IntPtr GetConsoleWindow (); const int SW_HIDE = 0; const int SW_SHOW = 5;
Soulmachine

1

ฉันรู้ว่าฉันไม่ตอบสิ่งที่คุณต้องการอย่างแน่นอน แต่ฉันสงสัยว่าคุณกำลังถามคำถามที่ถูกต้องหรือไม่

ทำไมคุณไม่ใช้อย่างใดอย่างหนึ่ง:

  1. บริการ windows
  2. สร้างกระทู้ใหม่และเรียกใช้กระบวนการของคุณในที่

เสียงเหล่านั้นเหมือนตัวเลือกที่ดีกว่าหากคุณต้องการเรียกใช้กระบวนการ


3
มีสถานการณ์มากมายที่การเรียกใช้แอปพลิเคชันคอนโซลยูทิลิตี้นั้นถูกต้องตามกฎหมายอย่างสมบูรณ์
Adam Robinson

ในกรณีของฉันจำเป็นต้องมีกระบวนการแยกต่างหากเนื่องจากไคลเอนต์ / เซิร์ฟเวอร์รุ่นที่ซอฟต์แวร์ที่ฉันใช้งานอยู่
45432 Aaron Aaron

มันไม่ได้แก้ปัญหาเพื่อสร้างหัวข้อใหม่ มีหลายครั้งที่คุณไม่ต้องการหน้าต่างที่น่ารำคาญในพื้นหลัง นอกจากนี้ถ้าคุณมีกระบวนการเริ่มต้นในลูปแล้วคุณจะไม่ทำงานใด ๆ เมื่อหน้าต่างคอนโซลปรากฏขึ้นในใบหน้าของคุณ
user890332

1
ฉันเปิดแอพคอนโซลแบบยูทิลิตี้แบบไม่มีหน้าต่างจาก Task Scheduler ไม่ต้องการบริการและไม่มีกระบวนการหลักที่จะแยกเธรด แอพเหล่านี้เขียนถึง EventLog หากต้องการเอาต์พุตเพิ่มเติม
subsci

1

แม้ว่าตามคำตอบอื่น ๆ ที่นี่บอกว่าคุณสามารถเปลี่ยน "ประเภทงานพิมพ์" เป็น "แอปพลิเคชัน Windows" ได้โปรดระวังว่านี่จะหมายความว่าคุณไม่สามารถใช้งานConsole.Inได้เพราะจะกลายเป็น NullStreamReader

Console.OutและConsole.Errorดูเหมือนว่าจะยังคงทำงานได้ดี


2
คุณจริงจังไหม ทำไมทุกคนจะใช้Console.Inเมื่อไม่มีคอนโซลในการป้อนข้อมูลบางอย่าง ที่อะไรควรมาจากที่สามารถเข้าถึงได้ผ่านทางConsole.In? มันไม่สมเหตุสมผลเลย กล่าวอีกนัยหนึ่ง: มันชัดเจนและมีเหตุผลซึ่งConsole.Inเป็นNullStreamReaderในกรณีนี้
Robert S.

1
@RobertS บางทีอาจเป็นท่อ นั่นคือผลลัพธ์ของโปรแกรมอื่น นั่นเป็นกรณีการใช้งานของฉันเมื่อฉันค้นพบสิ่งนี้
kjbartel

1

จากคำตอบของ Adam Markowitz ด้านบนใช้งานได้สำหรับฉัน:

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

ฉันมีวิธีทั่วไปในการแบ่งปัน:

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);
        }
    }
}

Magician.DisappearConsole();มีเพียงชั้นนี้ในโครงการของคุณและโทร

คอนโซลจะกระพริบเมื่อคุณเริ่มโปรแกรมโดยคลิกที่มัน เมื่อดำเนินการจากพรอมต์คำสั่งพรอมต์คำสั่งจะหายไปไม่นานหลังจากการดำเนินการ

ฉันทำสิ่งนี้เพื่อ Discord Bot ที่ทำงานตลอดไปในพื้นหลังของคอมพิวเตอร์ของฉันเป็นกระบวนการที่มองไม่เห็น มันง่ายกว่าการให้ TopShelf ทำงานให้ฉัน บทเรียน TopShelf คู่ล้มเหลวฉันก่อนที่ฉันจะเขียนด้วยความช่วยเหลือจากรหัสที่ฉันพบที่อื่น ; P

ฉันพยายามเปลี่ยนการตั้งค่าใน Visual Studio> โครงการ> คุณสมบัติ> แอปพลิเคชันเพื่อเปิดใช้เป็นแอปพลิเคชัน Windows แทนคอนโซลแอปพลิเคชันและบางสิ่งเกี่ยวกับโครงการของฉันทำให้ไม่สามารถซ่อนคอนโซลได้ - อาจเป็นเพราะ DSharpPlus ต้องการเปิดคอนโซล . ฉันไม่รู้ ไม่ว่าด้วยเหตุผลใดคลาสนี้ให้ฉันฆ่าคอนโซลได้ง่ายหลังจากที่มันโผล่ขึ้นมา

หวังว่านักเวทย์คนนี้จะช่วยใครซักคน ;)


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.