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
Re: Terminating and restarting an external program in linux and windows
few threads you might find interesting.
Re: Terminating and restarting an external program in linux and windows
Quote:
Originally Posted by
high_flyer
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.
Re: Terminating and restarting an external program in linux and windows
Quote:
Bytheway no one seems responding my questions.
I did! :)
-----------------------------------------------------------------
Re: Terminating and restarting an external program in linux and windows
No one of the discussions you suggested.
Regards
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.
1 Attachment(s)
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:
Quote:
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
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.
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.
Code:
#ifdef Q_OS_WIN32
void strcpy_wc(char *dest, wchar_t *src)
{
while (*src) {
*dest++ = *src++;
}
*dest = 0;
}
void MainWindow::killwinproc(const char *process_name)
{
DWORD Process_TID;
HANDLE ProcessHandle;
DWORD Reserved;
PROCESSENTRY32 proc;
HANDLE snapshot;
int gotime=0; //did we find'em?
proc.dwSize = sizeof(proc);
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
Process32First(snapshot, &proc);
do {
// Find the Given Process
char dest[256];
strcpy_wc(dest, proc.szExeFile);
if(strcmp(dest,process_name)==0) {
Process_TID = proc.th32ProcessID;
gotime++;
}
} while (Process32Next(snapshot, &proc));
CloseHandle(snapshot);
// Get the Process's handle and blow it away
if(gotime>0) {
ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_TERMINATE, FALSE, Process_TID);
TerminateProcess(ProcessHandle, (DWORD)0);
}
}
#endif
Quote:
Originally Posted by
bender86
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
Re: Terminating and restarting an external program in linux and windows
Why system(), why not QProcess?
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?
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...
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
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.
Re: Terminating and restarting an external program in linux and windows
You can also use QAssistantClient as one example.
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:
Code:
if (!tcpServer->listen()) {
tr("Unable to start the server: %1.")
.arg(tcpServer->errorString()));
close();
return;
}
port = tcpServer->serverPort();
I call the updater this way:
Code:
args << port.toString();
myProcess->startDetached(program, args);
In the updater I added:
Code:
tcpSocket->connectToHost("localhost", port.toInt());
and send the quit command this way:
Code:
void Updater::sendQuit()
{
out << (quint16)0;
out << "quit";
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));
tcpSocket->write(block);
tcpSocket->disconnectFromHost();
}
Now, how the server reads the incoming data? In the fortune client/server example the server has the following connection:
Code:
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendFortune()));
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
Re: Terminating and restarting an external program in linux and windows
You can use QDataStream or QTextStream directly with QAbstractSocket (because is a QIODevice).
Code:
void Updater::sendQuit()
{
tcpSocket->disconnectFromHost();
}
...
void MainApp::recvQuit()
{
in >> string;
// Quit application.
}
}
Quote:
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.
Re: Terminating and restarting an external program in linux and windows
Quote:
Originally Posted by
bender86
Code:
void MainApp::recvQuit()
{
in >> string;
// Quit application.
}
}
Is right connecting recvQuit() to QTcpServer::newConnection() signal?
In MainApp I haven't QTcpSocket object (only QTcpServer): I need to create one, right?
Thanks
Re: Terminating and restarting an external program in linux and windows
Quote:
Originally Posted by
jiveaxe
Is right connecting recvQuit() to QTcpServer::newConnection() signal?
No, you should get new connection socket, and connect its readyRead signal to recvQuit.
Quote:
In MainApp I haven't QTcpSocket object (only QTcpServer): I need to create one, right?
When QTcpServer::newConnection is emitted, you should do:
Code:
void MainApp::newConnectionSlot()
{
// Loop on all incoming connections.
while(tcpServer->hasPendingConnections()) {
QTcpSocket *socket
= tcpServer
->nextPendingConnection
();
// Connect socket's signal, etc...
}
}
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):
Code:
{
...
private slots:
void startUpdater();
void readIncomingData();
void newConnectionSlot();
...
private:
...
};
{
myProcess = 0;
...
if (!tcpServer->listen()) {
tr("Unable to start the server: %1.")
.arg(tcpServer->errorString()));
close();
return;
}
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()));
...
connect(pushButton_1, SIGNAL(clicked()), this, SLOT(startUpdater()));
...
}
void MainApp::startUpdater()
{
args << port.toString();
...
myProcess->startDetached(program, args);
}
void MainApp::newConnectionSlot()
{
while(tcpServer->hasPendingConnections()) {
tcpSocket = tcpServer->nextPendingConnection();
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readIncomingData()));
}
}
void MainApp::readIncomingData()
{
...
in >> string;
// Quit application.
}
}
Code:
{
...
private slots:
void sendQuitCommand();
...
private:
...
};
Updater
::Updater(char *p,
QWidget *parent
){
port = p;
...
tcpSocket->connectToHost("localhost", port.toInt());
...
}
void Updater::sendQuitCommand()
{
tcpSocket->disconnectFromHost();
}
Regards