如何使用 DBus 和 UDisks2 列出所有可移动设备?

How to list all the removable devices with DBus and UDisks2?

我需要使用 UDisks2 列出、过滤和打开块设备。我正在尝试列出所有可移动设备。

UDisks2提供的GetBlockDevices method需要a{sv}类型。如果我没记错的话,它是字符串键和变体值的哈希表。

如何使用此信息列出设备​​?到目前为止,我尝试了以下方法:

import std.stdio, ddbus;

void main()
{
    Connection conn = connectToBus();
    PathIface obj = new PathIface(conn, "org.freedesktop.UDsks2",
            "/org/freedesktop/UDisks2/Manager", "org.freedesktop.UDisks2.Manager");

    writeln(obj.call!string("GetBlockDevices", "org.freedesktop.DBus", ???));
}

call 方法需要一个 Arg 作为最后一个参数。我怎样才能在其中提供 a{sv}


我正在使用 ddbus 库。


对于 args,我使用了 Variant!string[string],因为 Variant 本身是一个模板类型。我还从调用方法参数中删除了多余的“org.freedesktop.DBus”。

import std.stdio, ddbus;
import ddbus: Variant;

void main()
{
    Connection conn = connectToBus();
    PathIface obj = new PathIface(conn, "org.freedesktop.DBus",
            "/org/freedesktop/UDisks2/Manager", "org.freedesktop.UDisks2.Manager");

    Variant!string[string] arg;
    writeln(obj.call!string("GetBlockDevices", arg));
}

但是我收到以下错误:

ddbus.exception.DBusException@../../.dub/packages/ddbus-2.3.0/ddbus/source/ddbus/thin.d(833): org.freedesktop.DBus does not understand message GetBlockDevices

您的问题是:

  1. D-Bus名称org.freedesktop.UDisks2在系统总线上(不在会话总线上),所以需要更改connectToBus()调用。
  2. 总线名称是org.freedeskop.UDisks2,不是org.freedesktop.DBus
  3. GetBlockDevices 的 return 值为 ao(对象路径数组),但您使用 call!string 调用它,这意味着您将取回一个字符串。将其更改为 call!(ObjectPath[])
  4. (可选)你提出了你的论点 Variant!string[string]。 ddbus 中的 Variant!T 类型是一个帮助程序,它只会使任何类型 T 充当 dbus 协议中的变体,但它实际上不允许任何其他类型。如果你想支持传递任何类型 ddbus 支持使用 std.variant : Variant 或者有一个特殊类型你可以使用 Variant!DBusAny 与 ddbus 变体一起使用,这是一个更轻量级的标记联合,只支持所有 dbus类型(以及更多的内省)

我相信这段代码是您想要的,并且已解决所有问题:

import std.stdio, ddbus;
import ddbus : Variant;
import ddbus.c_lib;

void main()
{
    Connection conn = connectToBus(DBusBusType.DBUS_BUS_SYSTEM);
    PathIface obj = new PathIface(conn,
        busName("org.freedesktop.UDisks2"),
        ObjectPath("/org/freedesktop/UDisks2/Manager"),
        interfaceName("org.freedesktop.UDisks2.Manager"));

    Variant!DBusAny[string] arg;
    writeln(obj.call!(ObjectPath[])("GetBlockDevices", arg));
}

在这段代码中我还使用了type-safe ddbus API,这使得PathIface 中的参数更加清晰。 type-safe API 需要 ddbus 3.0.0-beta.1 或更高版本。

示例输出:

[/org/freedesktop/UDisks2/block_devices/sdc1, /org/freedesktop/UDisks2/block_devices/sdb1, /org/freedesktop/UDisks2/block_devices/sda, /org/freedesktop/UDisks2/block_devices/nvme0n1p2, /org/freedesktop/UDisks2/block_devices/sdb3, /org/freedesktop/UDisks2/block_devices/sdc, /org/freedesktop/UDisks2/block_devices/nvme0n1, /org/freedesktop/UDisks2/block_devices/sr0, /org/freedesktop/UDisks2/block_devices/nvme0n1p1, /org/freedesktop/UDisks2/block_devices/sde, /org/freedesktop/UDisks2/block_devices/sdb2, /org/freedesktop/UDisks2/block_devices/sdb, /org/freedesktop/UDisks2/block_devices/sda1, /org/freedesktop/UDisks2/block_devices/sde1, /org/freedesktop/UDisks2/block_devices/sdb4, /org/freedesktop/UDisks2/block_devices/sdd]