qt启动控制台程序,启动后隐藏到后台(windows)

一些控制台程序在Windows会有黑窗口弹出,有的时候不想在前台看到,想把它后台运行就行。这时候利用Windows的相关app函数实现。

实现方式如下:

 PROCESS_INFORMATION pi;
		STARTUPINFO si;      //隐藏进程窗口
		si.cb = sizeof(STARTUPINFO);
		si.lpReserved = NULL;
		si.lpDesktop = NULL;
		si.lpTitle = NULL;
		si.dwFlags = SW_SHOWDEFAULT ;
		si.wShowWindow = SW_SHOW;
		si.cbReserved2 = NULL;
		si.lpReserved2 = NULL;
		
		QString namestr = subelement.attribute("path");
		QString argstr = subelement.attribute("arg");
		QString name_ = apppath + "/" + namestr;  
		
		bool ishind = true;
		if (ishind)  ///flag为真为隐藏启动
		{
			si.dwFlags = STARTF_USESHOWWINDOW;
			si.wShowWindow = SW_HIDE;	
		}
	
		BOOL ret = FALSE;

		if (!argstr.isEmpty())
		{
			name_ += " " + argstr;
		}

	
		if (!currentdir.isEmpty())
		{
			ret = CreateProcess(NULL,LPWSTR(name_.toStdWString().c_str()),NULL,NULL,NULL,CREATE_NEW_CONSOLE,NULL,LPWSTR(currentdir.toStdWString().c_str()),&si,&pi);
		}
		else
		{
			ret = CreateProcess(NULL,LPWSTR(name_.toStdWString().c_str()),NULL,NULL,NULL,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi);
		}

		if (ret == 0)
		{
			int errorcode = GetLastError();
			continue ;
		}

		if (ret != 0)
		{
			qDebug() <<  "start : " << name_;
			reStr += QString("<program name='%1' statue='1'/>\n").arg(namestr);
		}else
		{
			reStr += QString("<program name='%1' statue='-1'/>\n").arg(namestr);
			qDebug() <<  "start erro: " << name_;
		}

方法2

/将此代码复制到main函数所在cpp任何处就ok了/
#pragma comment( linker, “/subsystem:“windows” /entry:“mainCRTStartup”” )//隐藏DOS黑窗口

<think>好的,我现在需要解决的问题是在Qt/C++中如何启动一个cmd进程,然后在其中输入命令来启动另一个程序并执行。让我仔细想想应该怎么做。 首先,我知道在Windows下,启动外部进程通常可以使用WinAPI或者Qt自己的QProcess类。因为用户提到的是Qt/C++,所以QProcess应该是更合适的选择,毕竟它跨平台而且和Qt集成得更好。 那问题来了,如何用QProcess启动cmd,然后在里面输入命令呢?QProcess本身可以用来启动外部程序,并且能够进行输入输出重定向。但cmd是一个交互式环境,可能需要持续地输入命令并获取输出。这时候可能需要用到标准输入来向cmd发送命令。 不过,有没有更直接的方法呢?比如,直接通过QProcess执行cmd命令,而不需要显式地启动cmd进程?比如,使用QProcess::start("cmd", QStringList() << "/C" << "mycommand")。这样可能更简单,因为"/C"参数会让cmd执行完命令后退出。但用户的需求可能是在cmd中启动程序并执行,可能需要保持cmd窗口打开,或者在cmd中执行多个命令?不过根据问题描述,可能只需要执行一个命令启动程序,然后退出。 不过用户的问题明确说要在启动cmd后,在cmd中输入启动程序并执行。所以可能需要先启动cmd进程,然后向其输入命令,比如"start myprogram.exe",然后退出。或者类似的操作。 那如何用QProcess来实现呢?步骤可能是这样的: 1. 使用QProcess启动cmd.exe,并且设置输入输出通道。 2. 向这个进程的标准输入写入命令,比如"myprogram.exe\n"。 3. 等待命令执行,处理输出或错误。 但需要考虑的问题是,cmd启动后是交互式的,可能需要处理提示符、换行符等问题。比如,每个命令可能需要以换行符结束,并且在完成后可能需要退出cmd。或者,是否可以在发送命令后关闭输入通道,让cmd执行完毕? 另外,可能需要注意cmd的启动参数。比如,使用"/K"参数可以让cmd执行命令后保持打开,而"/C"则执行后关闭。所以,如果用户想要在cmd中启动程序,并且可能查看输出,可能需要用"/K"。或者,如果只是想让程序后台运行,可能不需要保持cmd打开。 举个例子,假设要启动一个程序,比如notepad.exe,可以通过cmd执行。这时候,使用QProcess执行: QProcess::startDetached("cmd", QStringList() << "/C" << "notepad.exe"); 这样会启动cmd,执行notepad.exe,然后cmd关闭。但这样可能不会保留cmd窗口,如果用户希望看到cmd窗口的话可能不行。 或者,如果想在cmd窗口中保持运行,可能需要使用"/K"参数: QProcess::startDetached("cmd", QStringList() << "/K" << "notepad.exe"); 但这样,cmd窗口会保持打开,但执行notepad.exe之后,因为notepad是GUI程序,cmd可能立即返回提示符。或者,可能不会,这需要测试。 不过用户的问题可能更倾向于在启动的cmd进程中输入命令,比如需要多个步骤的命令。比如,先cd到某个目录,然后执行程序。这时候可能需要通过QProcess的输入通道来发送这些命令。 比如,代码可能像这样: QProcess *process = new QProcess; process->start("cmd"); if (process->waitForStarted()) { process->write("dir\n"); // 例如,执行dir命令 process->write("myprogram.exe\n"); // 可能需要关闭输入,或者发送exit命令? process->write("exit\n"); process->waitForFinished(); } 但这样可能会遇到问题,比如,cmd的输入可能需要处理回车,或者缓冲问题。此外,是否需要等待每个命令执行完成?比如,在发送dir\n之后,可能需要等待命令执行完毕,再发送下一个命令。否则,可能会将多个命令一起发送,导致cmd同时处理,出现错误。 或者,可以考虑将多个命令组合成一个字符串,用&&连接,或者用换行分隔,然后用cmd执行。例如: process->start("cmd", QStringList() << "/C" << "dir && myprogram.exe"); 这样,cmd会依次执行dir和myprogram.exe。但这种方式可能不够灵活,特别是当需要动态输入命令时。 回到原问题,用户希望的是启动cmd,然后在其中输入启动程序的命令。这可能有两种情况:一种是让用户与cmd交互,通过QProcess的输入输出;另一种是自动发送命令到cmd,无需用户干预。 如果是后者,自动发送命令,那么使用QProcess的write方法向进程的标准输入写入命令字符串,每个命令以换行符结束。但需要注意,cmd可能需要处理命令的顺序和完成情况。 例如,启动cmd,然后发送"cd C:\SomeDir\n",再发送"myprogram.exe\n",然后发送"exit\n"。这样,cmd会按顺序执行这些命令。 不过,这种方法的可靠性如何?例如,是否有必要在每次write之后等待一定的响应,比如等待命令提示符出现?或者是否有其他方法确保命令被正确执行? 这可能比较复杂,因为cmd在每次执行完命令后会输出提示符,比如" C:\Path >",但处理这样的输出可能比较麻烦,需要读取进程的输出,并等待特定的提示符出现后再发送下一个命令。这会增加代码的复杂性。 所以,可能更简单的方式是将所有命令合并到一个命令字符串中,通过cmd的/C参数执行。例如: QString command = "cd /D C:\\SomeDir && myprogram.exe"; QProcess::startDetached("cmd", QStringList() << "/C" << command); 这样,cmd会执行改变目录并启动程序。这种方法更简洁,不需要处理输入输出交互。 但用户的问题可能希望显式地启动cmd进程,并在其中输入命令,而不是直接执行单个命令。这可能涉及到更复杂的交互,比如需要保持cmd进程运行,并动态输入命令。 在这种情况下,正确的做法是使用QProcess的交互模式。例如: QProcess *process = new QProcess; process->setProcessChannelMode(QProcess::MergedChannels); connect(process, &QProcess::readyReadStandardOutput, this, [process](){ qDebug() << process->readAllStandardOutput(); }); process->start("cmd"); process->waitForStarted(); process->write("echo Hello\n"); process->write("myprogram.exe\n"); process->write("exit\n"); 但这种方法的问题在于,cmd可能不会立即执行写入的命令,或者可能存在缓冲问题。此外,如何确保所有命令都被正确执行,并且程序在适当的时候退出? 或者,是否需要使用start()而不是startDetached(),以便能够控制进程的输入输出? 另一个需要注意的问题是,当使用QProcess::write发送命令时,必须包含换行符(\n),这样cmd才会执行该命令。否则,命令会留在缓冲区中,直到换行符被发送。 此外,可能需要在发送所有命令后关闭输入通道,以便cmd知道输入结束。例如: process->closeWriteChannel(); 但如果在发送exit命令之后关闭,可能更合适。 例如: process->start("cmd"); process->waitForStarted(); process->write("myprogram.exe\n"); process->write("exit\n"); process->waitForFinished(); 这样,cmd会执行myprogram.exe,然后退出。但这里有个问题,如果myprogram.exe是一个GUI程序(例如记事本),那么cmd会立即返回,而不会等待其关闭。所以,当执行myprogram.exe后,cmd会继续运行,直到exit命令被执行。所以在这种情况下,exit会被立即执行,导致cmd关闭,而myprogram.exe继续运行(作为独立进程)。这可能是期望的行为。 但如果myprogram.exe是一个控制台程序,会阻塞cmd直到完成。例如,ping 127.0.0.1 -n 5,这时cmd会等待ping完成后执行exit。 所以,这种方法的可行性取决于被启动程序类型。 现在,回到用户的问题,可能需要根据具体情况选择不同的方法。如果用户只需要启动另一个程序,可能直接使用QProcess启动程序,或者通过cmd执行。例如: 如果直接启动程序: QProcess::startDetached("myprogram.exe"); 或者如果需要通过cmd启动,比如需要特定的工作目录或环境变量,可以使用: QProcess::startDetached("cmd /C myprogram.exe"); 但如果是必须在cmd中手动输入命令,比如模拟用户操作,则需要通过QProcess交互式发送命令。 总结可能的解决方案: 1. 直接使用QProcess启动目标程序,无需经过cmd。 2. 通过cmd执行命令,使用/C参数,并传递完整的命令字符串。 3. 启动cmd进程,并通过QProcess向其输入命令,模拟用户输入。 用户的问题可能更倾向于第三种情况,即启动cmd进程,并在其中输入命令来启动程序。但需要明确用户的具体需求,比如是否需要保持cmd窗口打开,是否需要执行多个命令,或者是否只是需要一个临时命令执行。 假设用户希望的是第三种情况,那么示例代码可能如下: QProcess *cmdProcess = new QProcess(); cmdProcess->start("cmd", QStringList() << "/K"); // 使用/K保持cmd打开 if (cmdProcess->waitForStarted()) { // 输入命令,注意换行符 cmdProcess->write("echo Starting my program...\n"); cmdProcess->write("myprogram.exe\n"); // 可以继续输入其他命令 } else { // 处理启动失败 } 或者,如果不需要保持cmd打开: cmdProcess->start("cmd"); cmdProcess->write("myprogram.exe\n"); cmdProcess->write("exit\n"); cmdProcess->waitForFinished(); 不过,这样可能的问题在于,当myprogram.exe是GUI程序时,exit会被立即执行,导致cmd关闭,但程序继续运行。如果是控制台程序,cmd会等待其完成。 此外,需要注意编码问题,确保写入的数据是正确的,比如换行符可能需要是\r\n还是\n。在Windows中,换行通常是\r\n,所以可能更好的做法是使用: cmdProcess->write("myprogram.exe\r\n"); 或者使用QTextStream,自动处理换行符: QTextStream stream(cmdProcess); stream << "myprogram.exe" << endl; 不过,QProcess的输入是QIODevice,QTextStream可以用于写入,处理编码和换行符。 这可能更可靠。例如: QProcess *cmdProcess = new QProcess; cmdProcess->start("cmd"); QTextStream stream(cmdProcess); stream << "myprogram.exe" << endl; stream << "exit" << endl; 这样,换行符会被正确处理。 但需要注意,当使用QTextStream时,可能需要确保进程已经启动,否则写入可能会失败。因此,在调用stream之前,应该确保进程已经启动,例如使用waitForStarted()。 总结可能的步骤: 1. 创建QProcess对象,启动cmd.exe。 2. 等待进程启动。 3. 使用QTextStream或write方法向进程输入命令,每个命令后跟换行符。 4. 发送exit命令以关闭cmd(如果需要)。 5. 等待进程结束,或处理其输出。 此外,如果用户希望看到cmd窗口,可能需要设置窗口的显示方式。默认情况下,QProcess启动的进程可能会隐藏窗口。要显示cmd窗口,可能需要使用特定的标志。例如,在Windows下,可以使用CREATE_NEW_CONSOLE标志: cmdProcess->start("cmd", QStringList(), QProcess::CreateNewConsole); 或者使用setCreateProcessArgumentsModifier来调整启动参数,确保新控制台窗口被创建。 例如: QProcess *cmdProcess = new QProcess; QProcess::CreateProcessArgumentModifier argsModifier = [](QProcess::CreateProcessArguments *args) { args->flags |= CREATE_NEW_CONSOLE; args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES; }; cmdProcess->setCreateProcessArgumentsModifier(argsModifier); cmdProcess->start("cmd"); 这样,cmd会在新窗口中显示,用户可以与之交互。但此时通过QProcess向该进程输入可能不会有任何效果,因为输入是发送到隐藏控制台。因此,如果需要用户与cmd窗口交互,可能需要使用startDetached,并让用户自行输入命令。 这种情况下,可能用户的问题需要明确:是否需要通过代码自动输入命令到cmd进程,还是仅仅启动cmd并让用户手动输入。 如果是前者,自动输入命令,那么需要处理输入输出,并且可能不需要显示窗口(或者需要隐藏)。如果是后者,则应该启动cmd窗口让用户自行操作,这时代码可能只需启动cmd即可: QProcess::startDetached("cmd"); 但用户的问题更可能是前者,即自动在启动的cmd进程中输入命令,执行程序。 综上所述,正确的做法可能是: - 使用QProcess启动cmd进程。 - 通过输入流发送命令,每个命令以换行符结束。 - 根据需要处理命令的输出和错误。 - 发送exit命令结束cmd进程。 但需要注意,这种方法可能在某些情况下不可靠,例如cmd的缓冲问题,或者程序执行顺序的问题。例如,如果发送多个命令,必须确保它们按顺序执行。或者,当启动GUI程序时,cmd不会等待其结束,因此后续命令可能立即执行。 最后,给出一个完整的示例代码,展示如何在Qt/C++中启动cmd进程,输入命令执行程序: #include <QCoreApplication> #include <QProcess> #include <QTextStream> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QProcess cmdProcess; cmdProcess.start("cmd"); // 启动cmd进程 if (cmdProcess.waitForStarted()) { QTextStream stream(&cmdProcess); stream << "echo Starting the program...\n"; stream << "notepad.exe\n"; // 启动记事本 stream << "exit\n"; // 退出cmd stream.flush(); // 确保所有数据被写入 cmdProcess.waitForFinished(); // 等待进程结束 qDebug() << "CMD process finished with exit code:" << cmdProcess.exitCode(); } else { qDebug() << "Failed to start cmd process"; } return a.exec(); } 但需要注意,当使用notepad.exe这样的GUI程序时,cmd不会等待其关闭,因此exit命令会立即执行,导致cmd进程退出,但记事本会继续运行。此外,如果希望cmd窗口保持打开,可能需要省略exit命令,并使用/K参数启动cmd: cmdProcess.start("cmd", QStringList() << "/K"); 然后在发送命令时不发送exit,这样cmd窗口会保持打开。不过在这种情况下,使用QTextStream发送命令可能不会有效,因为cmd进程会一直运行,等待用户输入,而QProcess的输入可能无法与用户手动输入交互。 因此,这种方法可能适用于后台自动执行一系列命令,而无需用户交互的情况。 最后,可能更推荐的方式是,如果要执行特定命令,直接通过cmd /C执行,或者直接启动目标程序,而不需要经过cmd。例如: // 直接启动程序 QProcess::startDetached("notepad.exe"); // 或者在特定目录下启动 QProcess process; process.setWorkingDirectory("C:\\MyDir"); process.startDetached("myprogram.exe"); 或者,通过cmd执行多条命令: QProcess::startDetached("cmd", QStringList() << "/C" << "cd /D C:\\MyDir && myprogram.exe"); 这样更简洁,不需要处理复杂的输入输出交互。</think>在Qt/C++中,通过`QProcess`启动`cmd`进程并执行命令可分为两种常见场景:**直接执行单条命令**或**交互式输入多命令**。以下是两种方法的实现示例: --- ### **方法一:直接执行单条命令** 使用`cmd /C`参数执行命令后自动关闭控制台: ```cpp #include <QProcess> // 直接启动程序(无需cmd) QProcess::startDetached("notepad.exe"); // 通过cmd执行复杂命令(如切换目录) QString command = "cd /D C:\\MyDir && myprogram.exe"; // 注意路径转义 QProcess::startDetached("cmd", QStringList() << "/C" << command); ``` --- ### **方法二:交互式输入多命令** 启动`cmd`进程后,通过输入流发送多个命令: ```cpp #include <QProcess> #include <QTextStream> QProcess cmdProcess; cmdProcess.start("cmd"); // 启动cmd if (cmdProcess.waitForStarted()) { QTextStream stream(&cmdProcess); stream << "echo Hello, CMD!\n" // 执行命令1 << "notepad.exe\n" // 启动记事本(非阻塞) << "exit\n"; // 退出cmd stream.flush(); // 确保命令发送 cmdProcess.waitForFinished(); // 等待cmd结束 } ``` --- ### **关键点说明** 1. **参数选择**: - `/C`:执行命令后关闭cmd。 - `/K`:执行命令后保持cmd打开(需手动`exit`)。 2. **路径处理**: - 使用`/D`参数确保`cd`切换驱动器(如`C:`到`D:`)。 - 路径中的反斜杠需转义(如`C:\\MyDir`)。 3. **GUI程序处理**: - 启动GUI程序(如`notepad.exe`)时,cmd不会阻塞,后续命令会立即执行。 - 控制台程序(如`ping`)会阻塞cmd直到执行完毕。 4. **显示cmd窗口**: 若需弹出可见的cmd窗口,需设置标志位: ```cpp #ifdef Q_OS_WIN cmdProcess.setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args) { args->flags |= CREATE_NEW_CONSOLE; // 显示新窗口 }); #endif cmdProcess.start("cmd", QStringList() << "/K"); // 保持窗口打开 ``` --- ### **总结** - **简单命令**:直接使用`QProcess::startDetached`或`cmd /C`。 - **复杂交互**:通过`QTextStream`向`cmd`进程写入命令流。 - **窗口控制**:通过`CREATE_NEW_CONSOLE`标志显示窗口,适用于调试场景。 根据实际需求选择合适的方法,避免不必要的进程交互以提升代码简洁性和可靠性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值