Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qprocess read Jlink Commander line
Forum Updated to NodeBB v4.3 + New Features

Qprocess read Jlink Commander line

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 4 Posters 1.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • NaireyangN Offline
    NaireyangN Offline
    Naireyang
    wrote on last edited by
    #1

    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:
    7b93d545-788b-4f61-8828-0de0ac24bc3d-image.png

    jlink cmd ,similar to windows cmd ,but I cant read anything from it.
    bbc19ed3-0ab4-4ac3-b667-bc42d43a0de3-image.png

    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Why do you want to wait for readyRead() here? Looks like the program finishes directly so better call waitForFinished() and read stdout/err then.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      2
      • NaireyangN Offline
        NaireyangN Offline
        Naireyang
        wrote on last edited by
        #3

        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?

        KroMignonK JonBJ 2 Replies Last reply
        0
        • NaireyangN Naireyang

          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?

          KroMignonK Offline
          KroMignonK Offline
          KroMignon
          wrote on last edited by KroMignon
          #4

          @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?

          It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

          1 Reply Last reply
          0
          • NaireyangN Naireyang

            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?

            JonBJ Online
            JonBJ Online
            JonB
            wrote on last edited by
            #5

            @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 as cmd.exe does.

            NaireyangN 1 Reply Last reply
            0
            • NaireyangN Offline
              NaireyangN Offline
              Naireyang
              wrote on last edited by Naireyang
              #6

              @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.

              KroMignonK 1 Reply Last reply
              0
              • JonBJ JonB

                @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 as cmd.exe does.

                NaireyangN Offline
                NaireyangN Offline
                Naireyang
                wrote on last edited by
                #7

                @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"
                JonBJ 1 Reply Last reply
                0
                • NaireyangN Naireyang

                  @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"
                  JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by JonB
                  #8

                  @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.

                  1 Reply Last reply
                  0
                  • NaireyangN Offline
                    NaireyangN Offline
                    Naireyang
                    wrote on last edited by
                    #9

                    @JonB Thanks! I will have a try.

                    1 Reply Last reply
                    0
                    • NaireyangN Naireyang

                      @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.

                      KroMignonK Offline
                      KroMignonK Offline
                      KroMignon
                      wrote on last edited by
                      #10

                      @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");
                      
                      

                      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                      1 Reply Last reply
                      0
                      • NaireyangN Offline
                        NaireyangN Offline
                        Naireyang
                        wrote on last edited by
                        #11

                        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";
                        

                        4bb421ae-a745-45f6-b211-d40b52af17b2-image.png
                        Good Night

                        JonBJ 1 Reply Last reply
                        1
                        • NaireyangN Naireyang

                          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";
                          

                          4bb421ae-a745-45f6-b211-d40b52af17b2-image.png
                          Good Night

                          JonBJ Online
                          JonBJ Online
                          JonB
                          wrote on last edited by
                          #12

                          @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.

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved