changeset 827:8de162b91a22

(Issue49) Create a Scheduled daily task to run trustbridge
author Andre Heinecke <andre.heinecke@intevation.de>
date Wed, 23 Jul 2014 19:47:59 +0200
parents 4aa33c408776
children 95e14add5c50
files ui/CMakeLists.txt ui/main.cpp ui/taskscheduler.cpp ui/taskscheduler.h
diffstat 4 files changed, 254 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/ui/CMakeLists.txt	Mon Jul 21 18:53:13 2014 +0200
+++ b/ui/CMakeLists.txt	Wed Jul 23 19:47:59 2014 +0200
@@ -40,6 +40,7 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/processhelp_linux.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/processwaitdialog.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/textoverlaybutton.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskscheduler.cpp
     ${CERTIFICATELIST_SOURCES}
     ${DOWNLOADER_SOURCES}
 )
@@ -94,8 +95,9 @@
    set(WINDOWS_EXTRA_LIBS
         -L${_qtpath}
         -lwinspool -lshlwapi -lfreetype -lbz2 -lpng16
-        -lQt5PlatformSupport -lQt5Gui -lcomdlg32 -loleaut32 -limm32 -lwinmm
-        -lglu32 -lopengl32 -lgdi32 -ljpeg -lpng -lQt5Core -lole32 -luuid -lws2_32
+        -lQt5PlatformSupport -lQt5Gui -lcomdlg32 -loleaut32 -limm32
+        -lharfbuzz -lglib-2.0 -lintl -liconv -lwinmm
+        -lglu32 -lopengl32 -lgdi32 -ljpeg -lpng -lQt5Core -lole32 -lmstask -luuid -lws2_32
         -ladvapi32 -lshell32 -luser32 -lkernel32 -lz -lsicuin -lsicuuc -lsicudt -lpcre16)
 
    set(EXTRA_STATIC_LIBS Qt5::QWindowsIntegrationPlugin ${WINDOWS_EXTRA_LIBS} -lwinhttp -lcrypt32)
--- a/ui/main.cpp	Mon Jul 21 18:53:13 2014 +0200
+++ b/ui/main.cpp	Wed Jul 23 19:47:59 2014 +0200
@@ -9,6 +9,9 @@
 #include "processhelp.h"
 #include "logging.h"
 #include "selftest.h"
+#ifdef WIN32
+#include "taskscheduler.h"
+#endif
 
 #include <QApplication>
 #include <QSystemTrayIcon>
@@ -97,6 +100,14 @@
         return 1;
     }
 
+#ifdef Q_OS_WIN
+    {
+        TaskScheduler taskSched;
+        qDebug() << " task sched done: " << taskSched.createDailyTask(QCoreApplication::applicationFilePath(),
+                QString::fromLatin1("--tray"), QTime::currentTime());
+    }
+#endif
+
     MainWindow mainWin(trayMode);
 
     return app.exec();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/taskscheduler.cpp	Wed Jul 23 19:47:59 2014 +0200
@@ -0,0 +1,188 @@
+#ifdef WIN32
+#include "taskscheduler.h"
+
+/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+#include <windows.h>
+
+#include <QDate>
+#include <QDebug>
+#include <QApplication>
+
+#define TASK_NAME L"TrustBridge Update"
+
+TaskScheduler::TaskScheduler() :
+    mInitialized (false),
+    mTaskScheduler (NULL)
+{
+    HRESULT hr;
+
+    hr = CoInitialize(NULL);
+    if(FAILED(hr)) {
+        qDebug() << "TaskScheduler CoInitializeEx failed: " << hr;
+        return;
+    }
+
+    hr = CoCreateInstance(CLSID_CTaskScheduler,
+                          NULL,
+                          CLSCTX_INPROC_SERVER,
+                          IID_ITaskScheduler,
+                          (void**)&mTaskScheduler);
+    if(FAILED(hr)) {
+        qDebug() << "TaskScheduler create instance failed: " << hr;
+        CoUninitialize();
+        return;
+    }
+
+    mInitialized = true;
+    qDebug() << "Initialization done";
+    return;
+}
+
+TaskScheduler::~TaskScheduler() {
+    qDebug() << "TaskSched dtor;";
+
+    if (!isInitialized()) {
+        return;
+    }
+    mTaskScheduler->Release();
+    CoUninitialize();
+}
+
+bool createTrigger(ITask *task, const QTime &startTime)
+{
+    ITaskTrigger *pITaskTrigger = NULL;
+    WORD piNewTrigger = 0;
+    HRESULT hr;
+    TASK_TRIGGER pTrigger;
+    ZeroMemory(&pTrigger, sizeof (TASK_TRIGGER));
+    QDate startdate = QDate::currentDate();
+
+    if (!startTime.isValid() || task == NULL) {
+        qDebug() << "Invalid args.";
+        return false;
+    }
+
+    hr = task->CreateTrigger(&piNewTrigger,
+            &pITaskTrigger);
+
+    if (FAILED(hr)) {
+        qDebug() << "Failed to create trigger.";
+        return false;
+    }
+
+    pTrigger.wBeginDay = startdate.day();
+    pTrigger.wBeginMonth = startdate.month();
+    pTrigger.wBeginYear = startdate.year();
+    pTrigger.wStartHour = startTime.hour();
+    pTrigger.wStartMinute = startTime.minute();
+    pTrigger.cbTriggerSize = sizeof (TASK_TRIGGER);
+    pTrigger.TriggerType = TASK_TIME_TRIGGER_DAILY;
+    pTrigger.Type.Daily.DaysInterval = 1;
+
+    hr = pITaskTrigger->SetTrigger(&pTrigger);
+
+    pITaskTrigger->Release();
+    if (FAILED(hr)) {
+        qDebug() << "Failed to create trigger.";
+        return false;
+    }
+
+    return true;
+}
+
+bool TaskScheduler::createDailyTask(const QString &executable,
+                                    const QString &args,
+                                    const QTime &startTime) {
+    ITask *task = NULL;
+    IPersistFile *persistFile = NULL;
+    HRESULT hr;
+
+    hr = mTaskScheduler->NewWorkItem(TASK_NAME,
+            CLSID_CTask,
+            IID_ITask,
+            (IUnknown**)&task);
+
+    if (FAILED(hr)) {
+        qDebug() << "Failed to create new work item.";
+        return false;
+    }
+
+    /* Set the task parameters */
+    hr = task->SetApplicationName(reinterpret_cast<LPCWSTR> (executable.utf16()));
+    if (FAILED(hr)) {
+        qDebug() << "Failed to set application name.";
+        task->Release();
+        return false;
+    }
+
+    hr = task->SetParameters(reinterpret_cast<LPCWSTR> (args.utf16()));
+    if (FAILED(hr)) {
+        qDebug() << "Failed to set parameters.";
+        task->Release();
+        return false;
+    }
+
+    hr = task->SetComment(reinterpret_cast<LPCWSTR>(QObject::tr("TrustBridge automatic update check.").utf16()));
+    if (FAILED(hr)) {
+        qDebug() << "Failed to set comment.";
+        task->Release();
+        return false;
+    }
+
+    QString username = QString::fromLocal8Bit(qgetenv("USERNAME").constData());
+    if (username.isEmpty()) {
+        qDebug() << "Failed to obtain username from envrionment.";
+        task->Release();
+        return false;
+    }
+
+    hr = task->SetAccountInformation(reinterpret_cast<LPCWSTR>(username.utf16()), NULL);
+
+    if (FAILED(hr)) {
+        qDebug() << "Failed to set username.";
+        task->Release();
+        return false;
+    }
+
+    hr = task->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);
+
+    if (FAILED(hr)) {
+        qDebug() << "Failed to set flags.";
+        task->Release();
+        return false;
+    }
+
+    /* Now create the trigger for this task */
+    if (!createTrigger(task, startTime)) {
+        qDebug() << "Failed to create trigger.";
+        task->Release();
+        return false;
+    }
+
+    hr = task->QueryInterface(IID_IPersistFile,
+                             (void **)&persistFile);
+    task->Release();
+
+    if (FAILED(hr)) {
+        qDebug() << "Failed to get persist file interface.";
+        task->Release();
+        return false;
+    }
+
+    hr = persistFile->Save(NULL, TRUE);
+    persistFile->Release();
+    if (FAILED(hr)) {
+        qDebug() << "Failed to save task";
+        return false;
+    }
+
+    return true;
+}
+#endif /* WIN32 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/taskscheduler.h	Wed Jul 23 19:47:59 2014 +0200
@@ -0,0 +1,51 @@
+/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+#ifndef TASKSCHEDULER_H
+#define TASKSCHEDULER_H
+
+/**
+ * @file Interface to the Task Scheduler API
+ * @brief Provides a Qt / C++ API to work with the windows task scheduler
+ */
+
+#include <QString>
+#include <QTime>
+#ifndef INITGUID
+#define INITGUID
+#include <mstask.h>
+#undef INITGUID
+#endif
+
+//struct ITaskScheduler;
+
+class TaskScheduler
+{
+public:
+    /** @brief Initializes the COM objects */
+    TaskScheduler();
+
+    /**@brief Uninitializes the COM objects */
+    ~TaskScheduler();
+    /** @brief create a task that is executed daily if the user is logged in.
+     *
+     * @param[in] executable Absolute path to the executable to run.
+     * @param[in] args the arguements to pass to the executable.
+     * @param[in] startTime the preferred time to start the task.
+     *
+     * @returns True on success, false on error */
+    bool createDailyTask(const QString &executable, const QString &args, const QTime &startTime);
+
+    /** @brief check if the Initialization was successful */
+    bool isInitialized() {return mInitialized;}
+
+private:
+    bool mInitialized;
+    ITaskScheduler *mTaskScheduler;
+};
+
+#endif // TASKSCHEDULER_H

http://wald.intevation.org/projects/trustbridge/