如何使用 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
您的问题是:
- D-Bus名称org.freedesktop.UDisks2在系统总线上(不在会话总线上),所以需要更改
connectToBus()
调用。
- 总线名称是org.freedeskop.UDisks2,不是org.freedesktop.DBus
- GetBlockDevices 的 return 值为
ao
(对象路径数组),但您使用 call!string
调用它,这意味着您将取回一个字符串。将其更改为 call!(ObjectPath[])
- (可选)你提出了你的论点
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]
我需要使用 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
您的问题是:
- D-Bus名称org.freedesktop.UDisks2在系统总线上(不在会话总线上),所以需要更改
connectToBus()
调用。 - 总线名称是org.freedeskop.UDisks2,不是org.freedesktop.DBus
- GetBlockDevices 的 return 值为
ao
(对象路径数组),但您使用call!string
调用它,这意味着您将取回一个字符串。将其更改为call!(ObjectPath[])
- (可选)你提出了你的论点
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]