C# 如何实现带参数运行时相当于控制台应用程序,无参数时相当于Windows应用程序

我尝试这样(部分测试代码):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
static class Program //
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
public class ConsoleShow
{
/// <summary>
/// 启动控制台
/// </summary>
/// <returns></returns>
[DllImport("kernel32.dll")]
public static extern bool AllocConsole();
/// <summary>
/// 释放控制台
/// </summary>
/// <returns></returns>
[DllImport("kernel32.dll")]
public static extern bool FreeConsole();
}
[STAThread]
static void Main(string[] args)
{
if (args.Length > 0)
{
//控制台方式
ConsoleShow.AllocConsole();
Console.WriteLine(args[0]);
}
else
{
//窗口方式
ConsoleShow.FreeConsole();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
}
通过下面两种方式编译,但实现效果都不太好:
(1)输出类型为“Windows应用程序”时:双击运行,正常显示窗口。但命令行带参数运行时,输出的内容在新的命令行窗口中且一闪而过,不合要求。能否使它显示在原来的命令行窗口中?
(2)输出类型为“控制台应用程序”时:命令行带参数运行,输出内容正常显示。但双击运行时,能显示窗口,但窗口前有命令行窗口一闪而过,不完美。能否实现不闪呢?
分不多,聊表心意。
可能上面说的不清。
我的要求是:(设测试程序为:test.exe)
1.控制台中输入:“test.exe 123”,直接在下一行输出“123”,不许另开窗口。
2.在资源管理器中双击此test.exe,此时直接打开此程序的窗口面,不能显示控制台窗口(闪一下的也不要)。

第1个回答  推荐于2018-03-23

代码没问题,但是做的事情多余了。满足以下几点就可以了:

    输出方式为控制台应用程序

    有参数时,直接做该做的事情,不需要AllocConsole或FreeConsole,也就是保持原本的状态。

    无参数时,调用FreeConsole释放掉控制台,再运行Form。


这个方式有个问题,也不够完美,就是在FreeConsole之前还是会有个黑色窗口一闪而过的。就是你的第二个方案。但是相比方案一而言,应该是好很多的。


要用AllocConsole把流写入前面的控制台,有看到过解决方案,但是极其复杂且有兼容性问题,不建议做过多研究。

追问

多余的代码只为方便测试,对比输出方式为“控制台应用程序”和“Windows应用程序”时的不同。目前困扰我的就是一闪而过的窗口,请问大虾有没有方法解决,听说在代码加载时修改注册类型可以做到,但是不知如何做。

本回答被网友采纳
第2个回答  推荐于2016-08-18
我在本地测试了一下,基本符合你的要求

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
static class Program
{
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
if (args.Length > 0)
{
AttachConsole(-1);
Console.WriteLine("123");
return;
}

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}追问

不错的思路,但还是不够完善:



请问大虾能做到么?谢谢。

追答

改成这样,加个回车就可以了。。。

AttachConsole(-1);
Console.WriteLine("123");
System.Windows.Forms.SendKeys.SendWait("{ENTER}");
return;

追问

123前的D:\>

看来本方案也无法解决

追答

只是多了个盘符,问题应该不大吧-__# 别的没啥好办法了。

本回答被提问者采纳
第3个回答  2017-03-30

C#不精通,只是提个思路:主程序执行前加个“壳”Form1,Form1接收带参数的执行命令,由Form1来判断是用控制台还是用windows应用程序。

    给Form1建参数入口,并在构造函数中处理参数。

    load事件加自动判断,是Console还是调Form2。

    Form1在托盘的图标可以作为一个控制台,加个右键菜单什么的作为扩展应用。例如可以自如切换控制台模式还是windows模式。

笨方法,不喜勿喷,谢谢。

第4个回答  2014-10-13
一般来说,你的要求是无法实现的,除非你自己模拟黑窗口。一个比较简单的解决方案,供参考:写3个exe,依次为 test.exe,test_cmd.exe,test_win.exe,其中,test.exe 是一个 WinAPP,也就是你要直接打开的,不带参数就由其打开 test_win.exe(WinAPP),带参数就由其打开 test_cmd.exe(黑窗口APP,本质是假的DOS EXE)。
第5个回答  2014-10-13
新建一个窗体项目,和控制台分开,生成2个EXE,双击控制台test.exe时,test.exe运行窗体EXE
相似回答