通过DBus使用Qt设置系统时间

通过DBus使用Qt设置系统时间,qt,dbus,freedesktop.org,Qt,Dbus,Freedesktop.org,我尝试通过以下方式使用Qt设置系统时间: #include <QDBusConnection> #include <QDBusInterface> #include <QDBusMessage> #include <QDebug> #include <QDateTime> #include <cstdlib> int main (int /*argc*/, char ** /*argv*/) { QDBusConn

我尝试通过以下方式使用Qt设置系统时间:

#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusMessage>
#include <QDebug>
#include <QDateTime>
#include <cstdlib>

int main (int /*argc*/, char ** /*argv*/)
{
    QDBusConnection dbConnection = QDBusConnection::systemBus ();
    QDBusInterface dbInterface (
            "org.freedesktop.timedate1.set-time"
          , "/org/freedesktop/timedate1/set-time/Manager"
          , "org.freedesktop.timedate1.set-time.Manager"
          , dbConnection);
    qDebug () << "DBus interface validation: " << dbInterface.isValid ();
    if (dbInterface.isValid () ) {
        QDBusMessage dbMessage = dbInterface.call ("SetTime", QDateTime::currentDateTime ().toMSecsSinceEpoch () * 1000, false, false);
        qDebug () << "DBus message: " << dbMessage;
    }

    return EXIT_SUCCESS;
}
我得到了一些相关的输出(因此看起来环境没有问题):


源代码和构建脚本位于。

简言之:
QDBusInterface
创建上的重试循环完成任务

我探索了更多。该dbus对象由
systemd timedated
服务提供。要了解其状态:

sudo systemctl status systemd-timedated
服务的配置位于
/lib/systemd/system/systemd timedated中。服务

[Unit]
Description=Time & Date Service
Documentation=man:systemd-timedated.service(8) man:localtime(5)
Documentation=http://www.freedesktop.org/wiki/Software/systemd/timedated

[Service]
ExecStart=/lib/systemd/systemd-timedated
BusName=org.freedesktop.timedate1
CapabilityBoundingSet=CAP_SYS_TIME
WatchdogSec=1min
PrivateTmp=yes
ProtectSystem=yes
ProtectHome=yes
BusName
设置负责所谓的“服务的D总线激活”。因此,当有人试图访问名称
org.freedesktop.timedate1
时,服务就会启动

但显然,这需要时间来开始。我不知道应该如何干净地完成,但您可以创建一个重试循环来创建
QDBusInterface
。您将看到
sudo systemctl status systemd timedated
变为活动状态,并且Qt检索一个有效的接口

我尝试过的对象名称和路径:

QDBusInterface dbInterface (
    "org.freedesktop.timedate1"
    , "/org/freedesktop/timedate1"
    , "org.freedesktop.timedate1"
    , dbConnection);

简而言之:
QDBusInterface
创建上的重试循环完成了任务

我探索了更多。该dbus对象由
systemd timedated
服务提供。要了解其状态:

sudo systemctl status systemd-timedated
服务的配置位于
/lib/systemd/system/systemd timedated中。服务

[Unit]
Description=Time & Date Service
Documentation=man:systemd-timedated.service(8) man:localtime(5)
Documentation=http://www.freedesktop.org/wiki/Software/systemd/timedated

[Service]
ExecStart=/lib/systemd/systemd-timedated
BusName=org.freedesktop.timedate1
CapabilityBoundingSet=CAP_SYS_TIME
WatchdogSec=1min
PrivateTmp=yes
ProtectSystem=yes
ProtectHome=yes
BusName
设置负责所谓的“服务的D总线激活”。因此,当有人试图访问名称
org.freedesktop.timedate1
时,服务就会启动

但显然,这需要时间来开始。我不知道应该如何干净地完成,但您可以创建一个重试循环来创建
QDBusInterface
。您将看到
sudo systemctl status systemd timedated
变为活动状态,并且Qt检索一个有效的接口

我尝试过的对象名称和路径:

QDBusInterface dbInterface (
    "org.freedesktop.timedate1"
    , "/org/freedesktop/timedate1"
    , "org.freedesktop.timedate1"
    , dbConnection);

有几个问题

  • 使用了错误的D-Bus命令。在尝试编写Qt程序之前,我必须使用控制台调试该命令。所以正确的命令是:

    dbus-send \
        --system \
        --print-reply \
        --type=method_call \
        --dest='org.freedesktop.timedate1' \
               '/org/freedesktop/timedate1' \
                org.freedesktop.timedate1.SetTime \
                    int64:120000000 \
                    boolean:true \
                    boolean:false
    
  • 使用ntp服务时,将执行命令,错误为:
    自动时间同步已启用
    。因此(根据建议)必须禁用同步:

    timedatectl set-ntp 0
    
  • 如@Velcan所述,日期为时间的服务处于非活动状态:

    当有人试图访问该名称时,服务将启动
    org.freedesktop.timedate1

    在我的环境(
    KUbuntu 15.10 x86_64
    )中,服务在上次呼叫30秒后处于活动状态

  • 根据报告:

    bool QDBusAbstractInterface::isValid()const

    如果这是一个错误,则返回true 对远程对象的有效引用。如果存在错误,则返回false 创建此接口时出错(例如,如果 远程应用程序不存在)

    注意:在处理远程对象时,并不总是能够 在创建QDBusInterface时确定它是否存在

  • 即使
    QDBusAbstractInterface::isValid()
    返回
    false
    调用
    函数也会成功执行

  • 最后,正确的代码非常简短:

    QDBusInterface dbInterface (
        "org.freedesktop.timedate1"
      , "/org/freedesktop/timedate1"
      , "org.freedesktop.timedate1"
      , QDBusConnection::systemBus () );
    qDebug () << dbInterface.call ("SetTime", 120000000ll, true, false);  
    
    qdbus接口dbInterface(
    “org.freedesktop.timedate1”
    ,“/org/freedesktop/timedate1”
    ,“org.freedesktop.timedate1”
    ,QDBusConnection::systemBus());
    
    qDebug()有几个问题

  • 使用了错误的D-Bus命令。在尝试编写Qt程序之前,我必须使用控制台调试该命令。所以正确的命令是:

    dbus-send \
        --system \
        --print-reply \
        --type=method_call \
        --dest='org.freedesktop.timedate1' \
               '/org/freedesktop/timedate1' \
                org.freedesktop.timedate1.SetTime \
                    int64:120000000 \
                    boolean:true \
                    boolean:false
    
  • 使用ntp服务时,将执行命令,错误为:
    自动时间同步已启用
    。因此(根据建议)必须禁用同步:

    timedatectl set-ntp 0
    
  • 如@Velcan所述,日期为时间的服务处于非活动状态:

    当有人试图访问该名称时,服务将启动
    org.freedesktop.timedate1

    在我的环境(
    KUbuntu 15.10 x86_64
    )中,服务在上次呼叫30秒后处于活动状态

  • 根据报告:

    bool QDBusAbstractInterface::isValid()const

    如果这是一个错误,则返回true 对远程对象的有效引用。如果存在错误,则返回false 创建此接口时出错(例如,如果 远程应用程序不存在)

    注意:在处理远程对象时,并不总是能够 在创建QDBusInterface时确定它是否存在

  • 即使
    QDBusAbstractInterface::isValid()
    返回
    false
    调用
    函数也会成功执行

  • 最后,正确的代码非常简短:

    QDBusInterface dbInterface (
        "org.freedesktop.timedate1"
      , "/org/freedesktop/timedate1"
      , "org.freedesktop.timedate1"
      , QDBusConnection::systemBus () );
    qDebug () << dbInterface.call ("SetTime", 120000000ll, true, false);  
    
    qdbus接口dbInterface(
    “org.freedesktop.timedate1”
    ,“/org/freedesktop/timedate1”
    ,“org.freedesktop.timedate1”
    ,QDBusConnection::systemBus());
    
    qDebug()看起来需要实例化对象。当我用d型脚看时,它不在那里。然后我从终端启动
    $gdbus introspect--system--dest org.freedesktop.timedate1--object path/org/freedesktop/timedate1
    ,timedate1出现(然后Qt应用程序将其报告为有效)。@Velkan,
    看起来该对象需要实例化。
    我不熟悉D-Bus。你能解释一下我应该做什么吗?看起来这个对象需要实例化。当我用d型脚看时,它不在那里。然后我从终端启动
    $gdbus introspect--system--dest org.freedesktop.timedate1--object path/org/freedesktop/timedate1
    ,timedate1出现(然后Qt应用程序将其报告为有效)。@Velkan,
    看起来该对象需要实例化。
    我不熟悉D-Bus。你能解释一下我该做什么吗?谢谢你的回答