Results 1 to 20 of 20

Thread: Terminating and restarting an external program in linux and windows

  1. #1
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Terminating and restarting an external program in linux and windows

    Hi,
    my program has now the autoupdate feature. It works in this manner. When the application starts it contacts the remote server, downloads the last release xml file and check for updates; if yes, it starts an external program (in linux: system("updater");) which asks if download the update and, after downloading, it closes the main program (in linux: system("killall mainapp");), installs the new files and restarts the main program (in linux: system("mainapp");) and closes itself.

    1st question: is all this method ok? In linux it works but I don't know if there is a better way.

    2nd question: how accomplish this in windows? how kill a running program and restart it?

    Thanks
    Giuseppe CalÃ

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,713
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Terminating and restarting an external program in linux and windows

    few threads you might find interesting.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  3. #3
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Terminating and restarting an external program in linux and windows

    Quote Originally Posted by high_flyer View Post
    few threads you might find interesting.
    Sorry, may you be more precise? You are advising me to use threads instead of my system? I did this way because the main program is using the files to be updated so I close it, install the new files and restart it. Using threads is safer?

    Thanks

    EDIT: only now I understand: threads=discussions.

    Bytheway no one seems responding my questions.
    Giuseppe CalÃ

  4. #4
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,713
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Terminating and restarting an external program in linux and windows

    Bytheway no one seems responding my questions.
    I did!

    -----------------------------------------------------------------
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  5. #5
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Terminating and restarting an external program in linux and windows

    No one of the discussions you suggested.

    Regards
    Giuseppe CalÃ

  6. #6
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,713
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Terminating and restarting an external program in linux and windows

    Well, I think several threads were dealing with very similar issues to yours.
    But I guess that is a matter of opinion.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  7. #7
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Terminating and restarting an external program in linux and windows

    Hi,
    I have found here a program which does what i want. Attached to this post there is the source code.

    I have downloaded and tested it on windows with mingw (with the command: g++ exam28.cpp): it compiles and works right.

    After, I have tryed compiling the program with qmake && make but I got the following errors:

    killwinproc.cpp: In function `int KILL_PROC_BY_NAME(const char*)':
    killwinproc.cpp:138: error: cannot convert `char*' to `TCHAR*' in argument passing
    killwinproc.cpp:223: error: cannot convert `WCHAR*' to `const char*' for argument `1' to `int strcmp(const char*, const char*)'
    Why the same code and the same compiler gives errors with qmake && make?

    Thanks
    Attached Files Attached Files
    Giuseppe CalÃ

  8. #8
    Join Date
    Nov 2007
    Posts
    89
    Thanked 21 Times in 18 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Terminating and restarting an external program in linux and windows

    I wouldn't kill the application. I would find the way to make it quit gracefully.

    You could do this way: when application starts, check if an update is available. If yes, launch updater (I would use QProcess, but I guess system() is fine) and quit. Meanwhile, updater asks user if download update files and downloads them. Main application should have all the time to quit*. Then updater installs update files, and reruns application. If user doesn't want to update, simply reruns application without download or install anything (after setted to not check for updates).

    Else, you could use some inter process communication from updater to ask main application to quit. Something like DBus, mailslots, or even QTcpSocket.

    Else, you could tell user to launch updater manually, after shut down main application.


    * To get more time, you could launch updater when QCoreApplication::aboutToQuit() is emitted.

  9. #9
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Terminating and restarting an external program in linux and windows

    Hi,
    On Planet Source Code I have found this code. After removing some lines and added new ones to let it work with Qt this is the final working code.

    Qt Code:
    1. #ifdef Q_OS_WIN32
    2. void strcpy_wc(char *dest, wchar_t *src)
    3. {
    4. while (*src) {
    5. *dest++ = *src++;
    6. }
    7. *dest = 0;
    8. }
    9.  
    10. void MainWindow::killwinproc(const char *process_name)
    11. {
    12. DWORD Process_TID;
    13. HANDLE ProcessHandle;
    14. DWORD Reserved;
    15. PROCESSENTRY32 proc;
    16. HANDLE snapshot;
    17. int gotime=0; //did we find'em?
    18. proc.dwSize = sizeof(proc);
    19. snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
    20. Process32First(snapshot, &proc);
    21.  
    22. do {
    23. // Find the Given Process
    24. char dest[256];
    25. strcpy_wc(dest, proc.szExeFile);
    26. if(strcmp(dest,process_name)==0) {
    27. Process_TID = proc.th32ProcessID;
    28. gotime++;
    29. }
    30. } while (Process32Next(snapshot, &proc));
    31. CloseHandle(snapshot);
    32. // Get the Process's handle and blow it away
    33. if(gotime>0) {
    34. ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_TERMINATE, FALSE, Process_TID);
    35. TerminateProcess(ProcessHandle, (DWORD)0);
    36. }
    37. }
    38. #endif
    To copy to clipboard, switch view to plain text mode 

    Quote Originally Posted by bender86 View Post
    I wouldn't kill the application. I would find the way to make it quit gracefully.
    ...
    Else, you could use some inter process communication from updater to ask main application to quit. Something like DBus, mailslots, or even QTcpSocket.
    I agree with you that should be better closing it gracefully; the problem is that my application must run in windows too so dbus perhaps is not usable. Have you some link with simple example showing interprocess communication with QTcpSocket?

    Regards
    Giuseppe CalÃ

  10. #10
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,518 Times in 1,388 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Terminating and restarting an external program in linux and windows

    Why system(), why not QProcess?
    J-P Nurmi

  11. #11
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Terminating and restarting an external program in linux and windows

    If I run the updater as a qprocess when the updater closes the main program to apply updates what appens to the updater? Will it continue running?
    Giuseppe CalÃ

  12. #12
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,518 Times in 1,388 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Terminating and restarting an external program in linux and windows

    Well, you can always start it detached. However, I didn't read the thread very carefully. All this process handling just looked pretty complex to me...
    J-P Nurmi

  13. #13
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Terminating and restarting an external program in linux and windows

    After a deep testing in windows I found my method (killwinproc(const char *process_name)) is not working very good. So as suggested I now use qprocess to start the updater. Now the problem is how send a signal from the updater to the main program to make it quit gracefully.

    I don't have any code to post because I don't know which is the better way. Maybe a solution is QTcpSocket but I have never used it so a link to a simple code illustrating intercommunication process with this class should be very appreciated.

    Thanks
    Giuseppe CalÃ

  14. #14
    Join Date
    Nov 2007
    Posts
    89
    Thanked 21 Times in 18 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Terminating and restarting an external program in linux and windows

    Examples for QTcpSocket are here and here.

    Basically, main application will start a QTcpServer that listens on QHostAddress::LocalHost. When someone connects to this server, it emits a QTcpServer::newConnection signal. You can just quit now, or read incoming data for checking if quit request is from updater.

    Client should just create a QTcpSocket, call QAbstractSocket::connectToHost. If main app checks incoming data, when connected sends quit request. When socket emits QAbstractSocket::disconnected() signal, it means that main application is quitting.

  15. #15
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,518 Times in 1,388 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Terminating and restarting an external program in linux and windows

    You can also use QAssistantClient as one example.
    J-P Nurmi

  16. #16
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Terminating and restarting an external program in linux and windows

    Hi, I have read the suggested examples; this is the partial code.

    In the main program I have added the following lines:

    Qt Code:
    1. tcpServer = new QTcpServer(this);
    2. if (!tcpServer->listen()) {
    3. QMessageBox::critical(this, tr("Server"),
    4. tr("Unable to start the server: %1.")
    5. .arg(tcpServer->errorString()));
    6. close();
    7. return;
    8. }
    9.  
    10. port = tcpServer->serverPort();
    To copy to clipboard, switch view to plain text mode 

    I call the updater this way:

    Qt Code:
    1. QString program = "updater";
    2. args << port.toString();
    3.  
    4. myProcess = new QProcess(this);
    5. myProcess->startDetached(program, args);
    To copy to clipboard, switch view to plain text mode 

    In the updater I added:

    Qt Code:
    1. tcpSocket = new QTcpSocket(this);
    2. tcpSocket->connectToHost("localhost", port.toInt());
    To copy to clipboard, switch view to plain text mode 

    and send the quit command this way:

    Qt Code:
    1. void Updater::sendQuit()
    2. {
    3. QByteArray block;
    4. QDataStream out(&block, QIODevice::WriteOnly);
    5. out.setVersion(QDataStream::Qt_4_0);
    6. out << (quint16)0;
    7. out << "quit";
    8. out.device()->seek(0);
    9. out << (quint16)(block.size() - sizeof(quint16));
    10.  
    11. tcpSocket->write(block);
    12. tcpSocket->disconnectFromHost();
    13. }
    To copy to clipboard, switch view to plain text mode 

    Now, how the server reads the incoming data? In the fortune client/server example the server has the following connection:

    Qt Code:
    1. connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendFortune()));
    To copy to clipboard, switch view to plain text mode 

    and the function sendFortune() only sends data. Besides, the client reads data but uses as i/o device tcpSocket so perhaps I can't copy and paste its readFortune() code in main program.

    Regards
    Giuseppe CalÃ

  17. #17
    Join Date
    Nov 2007
    Posts
    89
    Thanked 21 Times in 18 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Terminating and restarting an external program in linux and windows

    You can use QDataStream or QTextStream directly with QAbstractSocket (because is a QIODevice).
    Qt Code:
    1. void Updater::sendQuit()
    2. {
    3. QDataStream out(tcpSocket, QIODevice::WriteOnly);
    4. out.setVersion(QDataStream::Qt_4_0);
    5. out << QString("quit");
    6.  
    7. tcpSocket->disconnectFromHost();
    8. }
    9.  
    10. ...
    11.  
    12. void MainApp::recvQuit()
    13. {
    14. QDataStream(int(tcpSocket,QIODevice::ReadOnly);
    15. in.setVersion(QDataStream::Qt_4_0);
    16. QString string;
    17. in >> string;
    18. if(string == QString("quit")) {
    19. // Quit application.
    20. QCoreApplication::instance()->quit();
    21. }
    22. }
    To copy to clipboard, switch view to plain text mode 

    Now, how the server reads the incoming data?
    When you get a new connection on QTcpServer, call QIODevice::bytesAvailable on the socket: if returns > 0, simply read data, else connects its signal QIODevice::readyRead() to a slot where you read data.

  18. #18
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Terminating and restarting an external program in linux and windows

    Quote Originally Posted by bender86 View Post
    Qt Code:
    1. void MainApp::recvQuit()
    2. {
    3. QDataStream in(tcpSocket,QIODevice::ReadOnly);
    4. in.setVersion(QDataStream::Qt_4_0);
    5. QString string;
    6. in >> string;
    7. if(string == QString("quit")) {
    8. // Quit application.
    9. QCoreApplication::instance()->quit();
    10. }
    11. }
    To copy to clipboard, switch view to plain text mode 
    Is right connecting recvQuit() to QTcpServer::newConnection() signal?

    In MainApp I haven't QTcpSocket object (only QTcpServer): I need to create one, right?

    Thanks
    Giuseppe CalÃ

  19. #19
    Join Date
    Nov 2007
    Posts
    89
    Thanked 21 Times in 18 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Terminating and restarting an external program in linux and windows

    Quote Originally Posted by jiveaxe View Post
    Is right connecting recvQuit() to QTcpServer::newConnection() signal?
    No, you should get new connection socket, and connect its readyRead signal to recvQuit.



    In MainApp I haven't QTcpSocket object (only QTcpServer): I need to create one, right?
    When QTcpServer::newConnection is emitted, you should do:
    Qt Code:
    1. void MainApp::newConnectionSlot()
    2. {
    3. // Loop on all incoming connections.
    4. while(tcpServer->hasPendingConnections()) {
    5. QTcpSocket *socket = tcpServer->nextPendingConnection();
    6. // Connect socket's signal, etc...
    7. }
    8. }
    To copy to clipboard, switch view to plain text mode 

  20. #20
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Terminating and restarting an external program in linux and windows

    Hi,
    finally the problem is solved thanks to bender86 last post. This is the final code (if it may be useful to somebody else):

    Qt Code:
    1. class MainApp: public QDialog
    2. {
    3. ...
    4. private slots:
    5. void startUpdater();
    6. void readIncomingData();
    7. void newConnectionSlot();
    8. ...
    9.  
    10. private:
    11. QProcess *myProcess;
    12. QTcpServer *tcpServer;
    13. QTcpSocket *tcpSocket;
    14. ...
    15. };
    16.  
    17. MainApp::MainApp(QWidget *parent)
    18. :QDialog(parent)
    19. {
    20. myProcess = 0;
    21.  
    22. ...
    23.  
    24. tcpServer = new QTcpServer(this);
    25. if (!tcpServer->listen()) {
    26. QMessageBox::critical(this, tr("Server"),
    27. tr("Unable to start the server: %1.")
    28. .arg(tcpServer->errorString()));
    29. close();
    30. return;
    31. }
    32.  
    33. connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()));
    34.  
    35. ...
    36.  
    37. connect(pushButton_1, SIGNAL(clicked()), this, SLOT(startUpdater()));
    38.  
    39. ...
    40. }
    41.  
    42. void MainApp::startUpdater()
    43. {
    44. QString program = "updater";
    45. args << port.toString();
    46.  
    47. ...
    48.  
    49. myProcess = new QProcess(this);
    50. myProcess->startDetached(program, args);
    51. }
    52.  
    53. void MainApp::newConnectionSlot()
    54. {
    55. while(tcpServer->hasPendingConnections()) {
    56. tcpSocket = tcpServer->nextPendingConnection();
    57. connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readIncomingData()));
    58. }
    59. }
    60.  
    61. void MainApp::readIncomingData()
    62. {
    63. ...
    64.  
    65. QDataStream in(tcpSocket);
    66. in.setVersion(QDataStream::Qt_4_0);
    67. QString string;
    68. in >> string;
    69. if(string == QString("quit")) {
    70. // Quit application.
    71. QCoreApplication::instance()->quit();
    72. }
    73. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. class Updater: public QDialog
    2. {
    3. ...
    4. private slots:
    5. void sendQuitCommand();
    6. ...
    7.  
    8. private:
    9. QTcpSocket *tcpSocket;
    10. ...
    11. };
    12.  
    13. Updater::Updater(char *p, QWidget *parent)
    14. :QDialog(parent)
    15. {
    16. port = p;
    17.  
    18. ...
    19.  
    20. tcpSocket = new QTcpSocket(this);
    21. tcpSocket->connectToHost("localhost", port.toInt());
    22.  
    23. ...
    24. }
    25.  
    26. void Updater::sendQuitCommand()
    27. {
    28. QDataStream out(tcpSocket);
    29. out.setVersion(QDataStream::Qt_4_0);
    30. out << QString("quit");
    31. tcpSocket->disconnectFromHost();
    32. }
    To copy to clipboard, switch view to plain text mode 

    Regards
    Giuseppe CalÃ

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.