42 #include "qtservice_p.h"
43 #include <QCoreApplication>
49 #if defined(QTSERVICE_DEBUG)
54 #if defined(Q_OS_WIN32)
55 #include <qt_windows.h>
63 static void qtServiceCloseDebugLog()
67 QString ps(QTime::currentTime().toString(
"HH:mm:ss.zzz ") + QLatin1String(
"--- DEBUG LOG CLOSED ---\n\n"));
68 f->write(ps.toLatin1());
75 void qtServiceLogDebug(QtMsgType type,
const char* msg)
78 QMutexLocker locker(&mutex);
79 QString s(QTime::currentTime().toString(
"HH:mm:ss.zzz "));
80 s += QString(
"[%1] ").arg(
81 #
if defined(Q_OS_WIN32)
82 GetCurrentProcessId());
88 #if defined(Q_OS_WIN32)
89 f =
new QFile(
"c:/service-debuglog.txt");
91 f =
new QFile(
"/tmp/service-debuglog.txt");
93 if (!f->open(QIODevice::WriteOnly | QIODevice::Append)) {
98 QString ps(QLatin1String(
"\n") + s + QLatin1String(
"--- DEBUG LOG OPENED ---\n"));
99 f->write(ps.toLatin1());
104 s += QLatin1String(
"WARNING: ");
107 s += QLatin1String(
"CRITICAL: ");
110 s+= QLatin1String(
"FATAL: ");
113 s += QLatin1String(
"DEBUG: ");
121 s += QLatin1String(
"\n");
123 f->write(s.toLatin1());
126 if (type == QtFatalMsg) {
127 qtServiceCloseDebugLog();
214 d->serviceName = name;
260 return d->serviceName;
305 const QString &password)
307 QStringList arguments;
308 arguments << QLatin1String(
"-i");
309 arguments << account;
310 arguments << password;
348 return start(QStringList());
411 : QObject(), d_ptr(service) {}
415 d_ptr->startService();
420 #include "qtservice.moc"
424 QtServiceBasePrivate::QtServiceBasePrivate(
const QString &name)
430 QtServiceBasePrivate::~QtServiceBasePrivate()
435 void QtServiceBasePrivate::startService()
440 int QtServiceBasePrivate::run(
bool asService,
const QStringList &argList)
442 int argc = argList.size();
443 QVector<char *> argv(argc);
444 QList<QByteArray> argvData;
445 for (
int i = 0; i < argc; ++i)
446 argvData.append(argList.at(i).toLocal8Bit());
447 for (
int i = 0; i < argc; ++i)
448 argv[i] = argvData[i].data();
450 if (asService && !sysInit())
454 QCoreApplication *app = QCoreApplication::instance();
462 QTimer::singleShot(0, &starter, SLOT(slotStart()));
627 #if defined(QTSERVICE_DEBUG)
628 qInstallMsgHandler(qtServiceLogDebug);
629 qAddPostRoutine(qtServiceCloseDebugLog);
632 Q_ASSERT(!QtServiceBasePrivate::instance);
633 QtServiceBasePrivate::instance =
this;
636 if (nm.length() > 255) {
637 qWarning(
"QtService: 'name' is longer than 255 characters.");
640 if (nm.contains(
'\\')) {
641 qWarning(
"QtService: 'name' contains backslashes '\\'.");
642 nm.replace((QChar)
'\\', (QChar)
'\0');
647 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
648 d_ptr->serviceFlags = ServiceFlags();
650 d_ptr->serviceFlags = 0;
653 for (
int i = 0; i < argc; ++i)
654 d_ptr->args.append(QString::fromLocal8Bit(argv[i]));
670 QtServiceBasePrivate::instance = 0;
690 return d_ptr->serviceDescription;
700 d_ptr->serviceDescription = description;
710 return d_ptr->startupType;
720 d_ptr->startupType = type;
731 return d_ptr->serviceFlags;
760 if (d_ptr->args.size() > 1) {
761 QString a = d_ptr->args.at(1);
762 if (a == QLatin1String(
"-i") || a == QLatin1String(
"-install")) {
766 if (d_ptr->args.size() > 2)
767 account = d_ptr->args.at(2);
768 if (d_ptr->args.size() > 3)
769 password = d_ptr->args.at(3);
770 if (!d_ptr->install(account, password)) {
771 fprintf(stderr,
"The service %s could not be installed\n",
serviceName().toLatin1().constData());
774 printf(
"The service %s has been installed under: %s\n",
775 serviceName().toLatin1().constData(), d_ptr->filePath().toLatin1().constData());
778 fprintf(stderr,
"The service %s is already installed\n",
serviceName().toLatin1().constData());
781 }
else if (a == QLatin1String(
"-u") || a == QLatin1String(
"-uninstall")) {
784 fprintf(stderr,
"The service %s could not be uninstalled\n",
serviceName().toLatin1().constData());
787 printf(
"The service %s has been uninstalled.\n",
791 fprintf(stderr,
"The service %s is not installed\n",
serviceName().toLatin1().constData());
794 }
else if (a == QLatin1String(
"-v") || a == QLatin1String(
"-version")) {
795 printf(
"The service\n"
796 "\t%s\n\t%s\n\n",
serviceName().toLatin1().constData(), d_ptr->args.at(0).toLatin1().constData());
797 printf(
"is %s", (d_ptr->controller.
isInstalled() ?
"installed" :
"not installed"));
798 printf(
" and %s\n\n", (d_ptr->controller.
isRunning() ?
"running" :
"not running"));
800 }
else if (a == QLatin1String(
"-e") || a == QLatin1String(
"-exec")) {
801 d_ptr->args.removeAt(1);
802 int ec = d_ptr->run(
false, d_ptr->args);
804 qErrnoWarning(
"The service could not be executed.");
806 }
else if (a == QLatin1String(
"-t") || a == QLatin1String(
"-terminate")) {
807 if (!d_ptr->controller.
stop())
808 qErrnoWarning(
"The service could not be stopped.");
810 }
else if (a == QLatin1String(
"-p") || a == QLatin1String(
"-pause")) {
811 d_ptr->controller.
pause();
813 }
else if (a == QLatin1String(
"-r") || a == QLatin1String(
"-resume")) {
814 d_ptr->controller.
resume();
816 }
else if (a == QLatin1String(
"-c") || a == QLatin1String(
"-command")) {
818 if (d_ptr->args.size() > 2)
819 code = d_ptr->args.at(2).toInt();
822 }
else if (a == QLatin1String(
"-h") || a == QLatin1String(
"-help")) {
823 printf(
"\n%s -[i|u|e|s|v|h]\n"
824 "\t-i(nstall) [account] [password]\t: Install the service, optionally using given account and password\n"
825 "\t-u(ninstall)\t: Uninstall the service.\n"
826 "\t-e(xec)\t\t: Run as a regular application. Useful for debugging.\n"
827 "\t-t(erminate)\t: Stop the service.\n"
829 "\t-v(ersion)\t: Print version and status information.\n"
830 "\t-h(elp) \t: Show this help\n"
831 "\tNo arguments\t: Start the service.\n",
832 d_ptr->args.at(0).toLatin1().constData());
836 #if defined(Q_OS_UNIX)
837 if (::getenv(
"QTSERVICE_RUN")) {
839 int ec = d_ptr->run(
true, d_ptr->args);
841 qErrnoWarning(
"The service failed to run.");
845 if (!d_ptr->start()) {
846 fprintf(stderr,
"The service %s could not start\n Run with argument -h for help.\n",
serviceName().toLatin1().constData());
875 return QtServiceBasePrivate::instance;
The QtServiceBase class provides an API for implementing Windows services and Unix daemons.
void setServiceDescription(const QString &description)
virtual void processCommand(int code)
QString serviceName() const
void setStartupType(QtServiceController::StartupType startupType)
QString serviceDescription() const
QtServiceBase(int argc, char **argv, const QString &name)
static QtServiceBase * instance()
QtServiceController::StartupType startupType() const
ServiceFlags serviceFlags() const
virtual int executeApplication()=0
virtual void createApplication(int &argc, char **argv)=0
The QtServiceController class allows you to control services from separate applications.
bool sendCommand(int code)
virtual ~QtServiceController()
QString serviceName() const
QString serviceFilePath() const
static bool install(const QString &serviceFilePath, const QString &account=QString(), const QString &password=QString())
QtServiceController(const QString &name)