Qprocess read Jlink Commander line
-
There's no problem when use QProcess to read or write "cmd" in windows.
But when I change the "cmd" to the "jlink.exe" procedure, there's only started signal and no readyRead signal, run results are below.
I tried 2 versions of Jlink, neither runs correctly.bool ret; QProcess process; // process.setProgram("D:\\Program Files (x86)\\SEGGER\\JLinkARM_V466\\JLink.exe"); // process.start(QIODevice::ReadWrite); process.setProgram("D:\\Program Files (x86)\\SEGGER\\JLink_V640\\JLink.exe"); process.start(QIODevice::ReadWrite); ret = process.waitForStarted(100); qDebug()<<"waitForStarted"<<ret; ret = process.waitForReadyRead(1000); qDebug()<<"waitForReadyRead"<<ret; QByteArray byteArray = process.readAllStandardOutput(); QString str = QString::fromLocal8Bit(byteArray); qDebug()<<str process.close();
run reuslt:
jlink cmd ,similar to windows cmd ,but I cant read anything from it.
-
Why do you want to wait for readyRead() here? Looks like the program finishes directly so better call waitForFinished() and read stdout/err then.
-
I tried. It still doesn't work. Actually the procedure can't finish by itself.
I think it is supposed to work with the readyRead(), because the operation of jlink cmd is similar to the window cmd. It inputs and outputs by line.
Do you have any other opinion? -
@Naireyang said in Qprocess read Jlink Commander line:
Do you have any other opinion?
As I can see,
J-Link.exe
without arguments starts a kind of command processing console.
So I would suggest you to add required parameter to ensure it will stop after command execution.
Or do you want to send commands and await replies? -
@Naireyang
Your question is not clear. But if you mean: you do not wait for finished on a subprocess, and you do not receive output from it while still running at the time you would like to, that will be to do with buffering of the output at the sub-process side, so it does not arrive immediately. There may be little you can do about this, depends on that sub-process. You can test this probably by piping the output to somewhere else that isn't a Qt program.jlink.exe
may not behave the same ascmd.exe
does. -
@KroMignon That's true. I know it will probably work if I add an file argument behind the .exe as the jlink mannul says. And I am just going to try it.
However, I prefer to realize the latter case of what you say. But I can't wait for the reply but only start signal. So how can I read the reply. -
@JonB I can run the jlink.exe directly, independently and manually. I would get a reply on the screen when I send a command line with enter key. I also send \r\n to jlink in the QT, but get nothing. So I don't think there's buffers.
- -! so unfriendly
"ERROR
As a new user, you can only post once every 600 second(s) until you have earned 1 reputation - please wait before posting again"
- -! so unfriendly
-
@Naireyang said in Qprocess read Jlink Commander line:
I would get a reply on the screen
So I don't think there's buffers.
That's why I stressed that you need to try piping. Output down a pipe is not necessarily anything like output to a console (buffering-wise). And running a subprocess reading its output is piping.
-
@Naireyang said in Qprocess read Jlink Commander line:
However, I prefer to realize the latter case of what you say. But I can't wait for the reply but only start signal. So how can I read the reply.
QProcess
can be used asynchronously (signals/slots) or synchronously (waitXXX() functions), but you cannot mix them up.If you wan't to communicate with the command processor, you should you the asynchronous mode:
auto jlink = new QProcess(this); connect(jlink, &QProcess::readyReadStandardOutput, this, [this, jlink]() { // I suppose Buffer is an instance variable Buffer.append(QString::fromLocal8Bit(jlink->readAllStandardOutput()); if(Buffer.endsWith("J-Link>")) { qDebug() << "Recv:" <<Buffer; Buffer.clear(); // do to: send next command or quit jlink->write("quit\r\n"); } }); connect(jlink, &QProcess::stateChanged, [jlink](QProcess::ProcessState newState) { // cleanup on end if(newState == QProcess::NotRunning) jlink->deleteLater(); }); jlink.start("D:/Program Files (x86)/SEGGER/JLink_V640/JLink.exe");
-
Finally, I find the solution.
-
way1. use command args to read batch file. It need a 'q'( means quit) in batch file so that Replies can be get.
-
way2. use windows api "CreatePipe" and "CreateProcess" in windows.h or qt-windows.h. thanks to @JonB
however there's still a small problem of buffer size. It'll solve later.- Perhaps similar problems can be solved by this way.
details as below, with comments in Chinese. More can be explored by searching CreatePipe().
#include <qt_windows.h> ... STARTUPINFO si; PROCESS_INFORMATION pi; char ReadBuf[100]; DWORD ReadNum; HANDLE hRead; // 管道读句柄 HANDLE hWrite; // 管道写句柄 BOOL bRet = CreatePipe(&hRead, &hWrite, NULL, 0); // 创建匿名管道 if (bRet == TRUE) qDebug()<<"成功创建匿名管道!\n"; else qDebug()<<"创建匿名管道失败,错误代码:%d\n"; // 得到本进程的当前标准输出 HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE); // 设置标准输出到匿名管道 SetStdHandle(STD_OUTPUT_HANDLE, hWrite); GetStartupInfo(&si); // 获取本进程的STARTUPINFO结构信息 bRet = CreateProcess(NULL, "D:\\Program Files (x86)\\SEGGER\\JLinkARM_V466\\JLink.exe" , NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi); // 创建子进程 SetStdHandle(STD_OUTPUT_HANDLE, hTemp); // 恢复本进程的标准输出 if (bRet == TRUE) // 输入信息 qDebug()<<"成功创建子进程!\n"; else qDebug()<<"创建子进程失败,错误代码:%d\n"; CloseHandle(hWrite); // 关闭写句柄 // 读管道直至管道关闭 while (ReadFile(hRead, ReadBuf, 100, &ReadNum, NULL)) { ReadBuf[ReadNum] = '\0'; qDebug()<<"从管道["<<ReadBuf<<"]读取"<<ReadNum<<"字节数据\n"; } if (GetLastError() == ERROR_BROKEN_PIPE) // 输出信息 qDebug()<<"管道被子进程关闭\n"; else qDebug()<<"读数据错误,错误代码:%d\n";
Good Night -
-
@Naireyang said in Qprocess read Jlink Commander line:
way2. use windows api "CreatePipe" and "CreateProcess" in windows.h or qt-windows.h. thanks to @JonB
I don't know, and certainly not for Windows, but I would have thought you could achieve whatever you've done with
QProcess
settings. It depends just what the vital bit is, whether you can affect it. Anyway if you do need and you are happy with your Windows code solution for this that's fine.