如何使用 dbus 在 Rust 中检测应用程序的唯一性

How to detect application uniqueness in Rust using dbus

如何使用 Rust 中的 dbus crate(https://crates.io/crates/dbus) 检测应用程序的唯一性?

到目前为止,我已经尝试了以下方法,但函数总是 returns false。

pub fn detect_uniqueness() -> Result<bool, Box<dyn std::error::Error>> {
    let conn = dbus::blocking::Connection::new_session()?;
    match conn.request_name("com.localserver.myapp", false, false, false) {
        Err(e) => Err(Box::new(e)),
        Ok(dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply::Exists) => Ok(true),
        _ => Ok(false)
    }
}

将函数改成下面表示函数一直到RequestReply::PrimaryOwner

pub fn detect_uniqueness() -> Result<bool, Box<dyn std::error::Error>> {
    let conn = dbus::blocking::Connection::new_session()?;
    match conn.request_name("com.localserver.myapp", false, false, false) {
        Err(e) => Err(Box::new(e)),
        Ok(dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply::PrimaryOwner) => {
            log::info!("PrimaryOwner");
            Ok(true)
        },
        Ok(dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply::InQueue) => {
            log::info!("InQueue");
            Ok(false)
        },
        Ok(dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply::Exists) => {
            log::info!("Exists");
            Ok(false)
        },
        Ok(dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply::AlreadyOwner) => {
            log::info!("AlreadyOwner");
            Ok(false)
        },
    }
}

我不确定 these 中的哪一个暗示了应用程序的唯一性。

我曾尝试在函数达到 PrimaryOwner 时推迟程序的第一个实例并启动另一个实例,但即使是第二个实例似乎也达到了 PrimaryOwner

// main.rs
fn main() {
    aux::logger::init();

    if app::manually_invoked() {
        match app::unique_instance() {
            Ok(unique) => {
                if unique {
                    log::info!("Unique instance detected.");
                    loop {
                        std::thread::sleep_ms(999999);
                    }
                } else {
                    log::info!("Duplicate instance detected.")
                }
            },
            Err(e) => {
                log::error!("Error detecting uniqueness: {}.", e);
                app::exit();
            }
        }
    } else {
        // 
    }
}
// app.rs
pub fn manually_invoked() -> bool {
    std::env::args().len() == 1
}

pub fn unique_instance() -> Result<bool, Box<dyn std::error::Error>> {
    crate::aux::ipc::detect_uniqueness()
}

pub fn exit() {
    std::process::exit(1);
}

导致程序认为它始终是独一无二的。

dbus::blocking::Connection 超出范围时,它将被删除并导致 the underlying dbus connection 也被删除。

为了对连接做任何有意义的事情,您需要保持它的活动。一种方法是创建一次连接并传递引用:

//# dbus = "0.7.1"

use dbus;
use dbus::blocking::Connection;
use dbus::blocking::stdintf::org_freedesktop_dbus::RequestNameReply;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let conn = Connection::new_session()?;
    match is_unique(&conn) {
        Ok(true) => loop {},
        _ => Ok(()),
    }
}

pub fn is_unique(conn: &Connection) -> Result<bool, dbus::Error> {
    match conn.request_name("com.localserver.myapp", false, false, false) {
        Ok(RequestNameReply::PrimaryOwner) => Ok(true),
        Ok(_) => Ok(false),
        Err(e) => Err(e),
    }
}

尝试运行程序两次,第二次实例将立即终止。