• 905阅读
  • 10回复

在CONFIG +=console状态下,如何手动隐藏控制台? [复制链接]

上一主题 下一主题
离线ragtime
 

只看楼主 倒序阅读 楼主  发表于: 2023-05-30
回复本帖可获得10RMB金钱奖励!
每人最多可获奖1次,奖池剩余10RMB金钱 (中奖几率100%)
现在准备制作一个 GUI + 控制台混合的程序,两种运行状态有区别。
既可以双击exe正常启动,也可以命令行启动。
在main函数进行处理,判断进来有没有参数,有就不展示界面,没有就展示界面但是隐藏命令行窗口
这种可以实现吗?
不止windows,也要考虑苹果MAC端。
离线uidab

只看该作者 1楼 发表于: 2023-05-30
回帖奖励+ 10
自己试试啊,你都说得很清楚了。
有时候为了工作直接获得答案,而我却失去了思考的乐趣!


飘啊飘,何时能安居!
在线fsu0413

只看该作者 2楼 发表于: 2023-05-30
回帖奖励+ 10
印象中mac下需要app bundle才能做纯GUI,而app bundle双击就是不会出命令行的。要用命令行得用命令行手敲进bundle里面,所以好做。

windows不好弄。subsystem=console一定会开命令行。而subsystem=windows一定没有命令行。有没有命令行是链接时决定的,不是运行时决定的。
之前在公司用过一个windows上的软件(名字不便透露,是客户提供的)是做成弹出命令行但是后续自行关闭的这种,不过我升级windows11之后这个软件关闭命令行的功能失效了,可能是我把默认终端改成了windows terminal导致接口不一样的原因。

我的思路是全平台双可执行程序,如果满足开gui的条件,则在main函数里直接exec到gui程序里。
exec在Windows上是开新进程的,应该可以满足中止终端程序的要求,而在unix系列系统里(macos就是)则是就地将命令行程序替换为gui程序。
离线spygg

只看该作者 3楼 发表于: 2023-05-31
楼上的思路已经是比较好的解决方式了,为此还深扒了下Qt的源码发现subsytem=windows 时候入口函数是WinMain, 在windows下如果想实现隐藏用FindWindow查找窗口句柄然后隐藏

    HWND h = ::FindWindow(NULL, reinterpret_cast<LPCTSTR >( a.applicationFilePath().replace("/", "\\").data()));
    if(h)
        ::ShowWindow(h, SW_HIDE);
签名就是这么浪
离线hitler++

只看该作者 4楼 发表于: 2023-05-31
回帖奖励+ 10
subsystem=windows ,启动要弹出命令行时候打开一个新进程  cmd.exe 将 管道重定向到这个进程,这样cout cin 等可以直接到这个cmd.exe
在线fsu0413

只看该作者 5楼 发表于: 2023-05-31
回 spygg 的帖子
spygg:楼上的思路已经是比较好的解决方式了,为此还深扒了下Qt的源码发现subsytem=windows 时候入口函数是WinMain, 在windows下如果想实现隐藏用FindWindow查找窗口句柄然后隐藏
    HWND h = ::FindWindow(NULL, reinterpret_cast<LPCTSTR >( a.applicatio .. (2023-05-31 09:33) 

这种很显然在Windows11下windows terminal为默认终端的情况用不了。。。
在线fsu0413

只看该作者 6楼 发表于: 2023-05-31
还有 入口函数是winmain的情况下用 CommandLineToArgvW + WideCharToMultiByte 然后调回main就行了,Qt就是这么干的,可以看qtmain.lib
离线spygg

只看该作者 7楼 发表于: 2023-06-02
回 fsu0413 的帖子
fsu0413:这种很显然在Windows11下windows terminal为默认终端的情况用不了。。。 (2023-05-31 20:08) 

这个我还真测过,是可用的,用spy++抓包终端确实好几个别的窗口,但是一隐藏当前进程的窗口名之后竟然全部隐藏了,连任务栏都没剩
签名就是这么浪
在线fsu0413

只看该作者 8楼 发表于: 2023-06-02
回 spygg 的帖子
spygg:这个我还真测过,是可用的,用spy++抓包终端确实好几个别的窗口,但是一隐藏当前进程的窗口名之后竟然全部隐藏了,连任务栏都没剩[表情]  (2023-06-02 09:11) 

Windows Terminal有一个设置,里面有个“新建实例行为”,把它改成“附加到此桌面上最近使用的窗口”
这个设置打开后,如果再开新终端,则不会在新的终端窗口里打开,而是在已有的窗口里新建标签页

在这种设置下,打开会隐藏终端窗口的软件,有下面两种情况之一可能发生:
1 FindWindow 找到窗口然后把窗口隐藏了,当前终端中的其他标签页也不可操作了,挂在后台,如果上面有任务跑着,这些跑着的任务就找不到了
2 FindWindow 找不到窗口,隐藏不了,终端一直开着,要实现的功能没了
离线spygg

只看该作者 9楼 发表于: 2023-06-16
查资料发现windows系统会使用一个叫做conhost.exe来承接命令行,如果通过此程序来启动进程就不会出现各个版本不统一的情况了,cmd.exe不行,我把xp下的cmd.exe拷贝到win11下双击运行依然是多标签窗口(真是日了狗了)
此方法可以通过
HWND hwnd = GetConsoleWindow();
ShowWindow(hwnd,SW_HIDE);
来实现隐藏命令行窗口

===================================

在windows下双击启动的父进程是explorer.exe, 命令行启动的话父进程是(cmd, pwsh等),
针对楼主需求,可以使用非命令行程序,如果父进程是explore则分配控制台

AllocConsole();//打开控制台
freopen("CON","w",stdout);//将输出定向到控制台

当然qdebug()之类的也要重定向一份到输出到控制台
签名就是这么浪
在线fsu0413

只看该作者 10楼 发表于: 2023-06-17
回 spygg 的帖子
spygg:查资料发现windows系统会使用一个叫做conhost.exe来承接命令行,如果通过此程序来启动进程就不会出现各个版本不统一的情况了,cmd.exe不行,我把xp下的cmd.exe拷贝到win11下双击运行依然是多标签窗口(真是日了狗了)
此方法可以通过
HWND hwnd = GetConsoleWindow();
ShowWindow(hwn .. (2023-06-16 17:19) 

cmd是那个脚本解释器,窗口在Windows 10之前一直是conhost,Windows 11开始可以变成默认是Windows Terminal。针对默认终端是windows terminal的情况,一定要判断我上面说的新建实例行为,把其他终端隐藏了就是有问题的了
快速回复
限100 字节
 
上一个 下一个