C#混合cli和win form应用程序

C#混合cli和win form应用程序,c#,C#,我一直在研究如何创建混合winform和CLI应用程序。。。我以Winforms开始我的应用程序,现在我正在向它添加CLI。。。它似乎可以工作,但有一些问题我想弄清楚如何解决,但未能解决,可能是因为我缺乏C#方面的经验 如果我将VS中的输出类型设置为“windows应用程序”,并使用下面的代码,我可以运行GUI的winform部分,也可以从命令行为它提供参数,并且它可以工作,至少它输出了我编写的控制台代码,我有一个单独的c#类文件,其中包含我的主代码,因此它与winform GUI和最终的cli

我一直在研究如何创建混合winform和CLI应用程序。。。我以Winforms开始我的应用程序,现在我正在向它添加CLI。。。它似乎可以工作,但有一些问题我想弄清楚如何解决,但未能解决,可能是因为我缺乏C#方面的经验

如果我将VS中的输出类型设置为“windows应用程序”,并使用下面的代码,我可以运行GUI的winform部分,也可以从命令行为它提供参数,并且它可以工作,至少它输出了我编写的控制台代码,我有一个单独的c#类文件,其中包含我的主代码,因此它与winform GUI和最终的cli代码是分开的,它们都将用户输入提供给另一个“主”c#类。。无论如何,这是代码

     [STAThreadAttribute]

    [DllImport("kernel32.dll")]
    static extern bool AttachConsole(int dwProcessId);
    private const int ATTACH_PARENT_PROCESS = -1;

    static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new form_Main());
        }
        else
        {   
            AttachConsole(ATTACH_PARENT_PROCESS);

            cli_main cli = new cli_main();
            cli.start_cli(args);
        }
    }
它在gui中工作,我可以访问我的菜单并创建不同的win表单,当我单击按钮执行操作时,我得到以下异常:

用户代码未处理System.Threading.ThreadStateException Message=在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式。确保主函数上标记了STAThreadAttribute。只有将调试器附加到进程时,才会引发此异常

如果我随后将输出类型更改为“console application”,它在cli和GUI中的所有方式都能完美工作,但当它打开winform/GUI部分时,我会看到这个丑陋的CMD窗口,它不会消失。。这是我使用的代码,基本上就是我在添加上述代码之前开始使用的代码

    static void Main(string[] args)
    {


        if (args.Length == 0)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new form_Main());
        }
        else
        {            
            cli_main cli = new cli_main();
            cli.start_cli(args);
        }
    }

同样,由于我对C#缺乏了解,我希望有人能给我一个解决方案。我更愿意将应用程序保持为输出“控制台应用程序”,并找到一种方法来隐藏启动winform/gui部分时打开的控制台。。??提前感谢。

您是否按照错误消息中的说明执行了操作

确保主函数上标记了stathreadtribute

在粘贴的代码中,
STAThread
属性没有标记
Main
方法,而是标记
AttachConsole
外部函数。把它移到应该的地方,你就不会有任何问题了

如果您的应用程序是一个控制台应用程序,如果尚未连接控制台窗口,它将自动获得一个控制台窗口。这就是使其成为控制台应用程序的意义所在。您可以使用
FindWindow
ShowWindow(SW\u HIDE)
在运行时隐藏它,但它仍会在屏幕上短暂闪烁


如果您计划大部分时间从现有控制台窗口启动应用程序,则应将其保留为控制台应用程序,因为默认情况下它将继承父进程的控制台窗口。如果您计划从UI快捷方式或其他非控制台进程启动应用程序,您可能应该将其设置为Windows应用程序,并根据需要分配控制台。

谢谢您的帮助,但对以前的模式进行了一些更改

它的工作原理是:

static void Main(string[] args)
{
    // Test pattern
    args = new string[] { "-flag1", "value1", "-flag2", "value2", "-flag3", "value3" };

    if (args.Length == 0)
        MainWinApp();
    else
        MainCLI(args);

}

[STAThread]
static MainWinApp()
{
    // Your code for start GUI application
}
[STAThreadAttribute]
static void MainCLI(string[] args)
{
    // Your code for CLI application
}

如果在我的主函数中移动STATThread,它将不会编译,它希望位于我拥有它的位置,这是我创建的任何winform上的默认值。。。我现在正试图找出如何隐藏cmd窗口以查看它的工作情况,我也在考虑为控制台应用程序创建一个单独的c#项目,然后使用我的主类和其他类创建某种dll或库文件,然后让winform项目/应用程序和控制台项目/应用程序引用它,有两个。除了它不在函数内部,它在函数前面。属性附加到源代码中的下一个非属性元素。虽然听起来双可执行项目可能是你最好的选择。啊,我误解了,我回去了,我把STATThread放在main函数之前,它就工作了:)很抱歉,我只是因为我在main之前,在[DllImport]之前就有了它,一旦我将STATThread移过[DllImport]之后,我就会工作STATthread和主函数之间没有任何区别,非常感谢:)再次感谢。当你回答“欢呼”时,我正在键入这个。你的
STATthread
属性没有任何意义。文档特别指出,此属性对不是
Main()
的方法没有影响。