简体   繁体   English

可以从控制台运行但不创建窗口的C#应用​​程序

[英]C# application that can be run from console but does not create a window

I'd like to create a C# application that behaves like a console application when you run it from a console window (and can output text to the console) but that does not create a console window when run externally. 我想创建一个C#应用程序,当您从控制台窗口运行它时,它的行为类似于控制台应用程序(并且可以将文本输出到控制台)但是在外部运行时不会创建控制台窗口。 I've done a bit of research and the usual suggestion is to create a C# console application, then change its project type to a Windows Application. 我做了一些研究,通常的建议是创建一个C#控制台应用程序,然后将其项目类型更改为Windows应用程序。 However that stops the Console.WriteLine messages from being written when run from a console. 但是,这会阻止从控制台运行时写入Console.WriteLine消息。

Is there any way to run a program like this? 有没有办法运行这样的程序? I don't need it to take any console input. 我不需要它来接受任何控制台输入。 Perhaps there's some other method I can use to get text to display when run from the console? 也许还有一些其他方法可以用来从控制台运行时显示文本?

so all the console output shows up oddly after the prompt 因此所有控制台输出在提示后都显示奇怪

Using AttachConsole() just doesn't work that well in practice. 使用AttachConsole()在实践中效果不佳。 The command processor looks at your .exe file and does two different things, depending if it is a console mode app or a GUI app. 命令处理器会查看您的.exe文件并执行两项不同的操作,具体取决于它是控制台模式应用程序还是GUI应用程序。 If it is console mode app then it waits for the program to exit, then displays the prompt. 如果是控制台模式应用程序,则等待程序退出,然后显示提示。 If it is a GUI app then it doesn't wait, it assumes that the program will display its own window. 如果它是一个GUI应用程序然后它等待,它假定程序将显示自己的窗口。

Which is what happened, it displayed the prompt after starting your program and waits for input. 发生了什么,它在启动程序后显示提示并等待输入。 Your Console.Write() output now intermingles with the command processor output. 您的Console.Write()输出现在与命令处理器输出混合 You'll also have a problem with Console.ReadLine(), the first line that the user types goes to the command processor, not to you. 您还会遇到Console.ReadLine()的问题,用户输入的第一行是命令处理器,而不是您。 Greatly confuzzling the user. 大大困扰用户。

The workaround is to start your program differently. 解决方法是以不同方式启动您的程序。 You have type 你有类型

  start /wait yourapp.exe args...

Which makes the command processor wait for your program to exit, just like it would for a console mode app. 这使得命令处理器等待程序退出,就像控制台模式应用程序一样。

This is not very practical, the user of your app just won't think to use start /wait . 这不太实用,你的应用程序的用户只是不会想到使用start /wait No simple fix for this, you'll need to use AllocConsole(). 没有简单的解决方法,你需要使用AllocConsole()。 If that's a deal breaker then you'll just need to create another little EXE project that's a console app. 如果这是一个交易破坏者,那么你只需要创建一个控制台应用程序的另一个小EXE项目。 Which starts your GUI app, passing the command line. 通过命令行启动GUI应用程序。 If you give it the same name as your GUI exe but give the .com filename extension then it will always be found first. 如果你给它的名称与你的GUI exe相同,但给出.com文件扩展名,那么它将始终首先找到。 It can look like this, works for any gui app: 它看起来像这样,适用于任何gui应用程序:

using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;

class Program {
    static void Main(string[] args) {
        try {
            var path = Assembly.GetExecutingAssembly().Location;
            var dir = Path.GetDirectoryName(path);
            var file = Path.GetFileNameWithoutExtension(path);
            path = Path.Combine(dir, file + ".exe");

            var prc = Process.Start(path, Environment.CommandLine);
            if (args.Length > 0) prc.WaitForExit();
        }
        catch (Exception ex) {
            Console.WriteLine(ex.Message);
            Environment.Exit(1);
        }
    }
}

Honestly I needed this too and was looking for an answer and found this in 老实说,我也需要这个,并且正在寻找答案,并发现了这一点

Show Console in Windows Application? 在Windows应用程序中显示控制台

public static void ShowConsoleWindow()
{
    var handle = GetConsoleWindow();

    if (handle == IntPtr.Zero)
    {
        AllocConsole();
    }
    else
    {
        ShowWindow(handle, SW_SHOW);
    }
}

public static void HideConsoleWindow()
{
    var handle = GetConsoleWindow();

    ShowWindow(handle, SW_HIDE);
}

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AllocConsole();

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

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

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

This looks like a nice solution to all the others that have been suggested in this thread. 对于此线程中建议的所有其他内容,这看起来是一个很好的解决方案。

For reference, here's what I did. 作为参考,这是我做的。 I made a simple "Windowless CLI" executable. 我做了一个简单的“无窗口CLI”可执行文件。 I created a new console application, changed it to a Windows Application and passed through the arguments: 我创建了一个新的控制台应用程序,将其更改为Windows应用程序并通过参数传递:

static void Main(string[] args)
{
    string programFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    string passArguments = string.Join(" ", args.Select(WrapArgument));

    Process.Start(new ProcessStartInfo(Path.Combine(programFolder, "VidCoderCLI.exe"))
    {
        Arguments = passArguments,
        WindowStyle = ProcessWindowStyle.Hidden
    });
}

private static string WrapArgument(string arg)
{
    if (arg.EndsWith(@"\"))
    {
        return "\"" + arg + "\\\"";
    }

    return "\"" + arg + "\"";
}

Anything that needs to make a call without a window showing up goes through there. 任何需要在没有窗口显示的情况下打电话的东西都会通过那里。 It's nice because I avoid dealing with output redirection and console shenanigans. 这很好,因为我避免处理输出重定向和控制台恶作剧。

Though it's not technically what I asked so I won't accept this answer. 虽然技术上不是我问的所以我不会接受这个答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM