Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Help Request] Error { code: -2147417850, message: "无法在设置线程模式后对其加以更改。" } #37

Closed
niuhuan opened this issue Apr 21, 2023 · 7 comments

Comments

@niuhuan
Copy link

niuhuan commented Apr 21, 2023

我是试图捕捉windows最上面的窗口,并得到他的位置,以及他所有的子节点的位置和Name。

最后将这些信息放在一个全屏遮罩上绘制,试图达到窗口上所有文字都高亮的效果。

winit太过复杂我没有办法很好的使用。于是我选择了eframe(egui)或者ggez来渲染我的窗口。两个框架都有尝试。在框架的update方法中调用let ua = UIAutomation::new().unwrap();, 都会提示 Error { code: -2147417850, message: "无法在设置线程模式后对其加以更改。" }

我又尝试将他储存到OnceCell中,但是他并不是线程安全。

@niuhuan
Copy link
Author

niuhuan commented Apr 21, 2023

我想做的程序类似 https://github.com/JeffersonQin/Ayase . 用键盘代替鼠标,并增加一些快捷键。

现在已经实现了捕捉文字和位置,现在没有办法展示窗口,希望您给一些建议。

@leexgone
Copy link
Owner

你在自己的程序代码中,是否也有初始化com环境?
UIAutomation::new()时每次也会执行com初始化操作:CoInitializeEx(None, COINIT_MULTITHREADED)
如果我们指定的初始化模式不同就可能会出这个错误。
如果是这个原因的话,我可以增加一个不执行com初始化的创建方法;或者你把初始化参数改成相同的也可以。

关于展示窗口,你指的是自己创建窗口展示出来吗?

@niuhuan
Copy link
Author

niuhuan commented Apr 21, 2023

窗口并不是我创建出来的。我并没有显式的初始化com。

我使用了 ggez::event::run , eframe::run_native, 他们都是ui框架。我想这些框架可能执行了COM的初始化。 ggez代码大概如下

fn main() {
    let (mut ctx, event_loop) = ContextBuilder::new("my_game", "Cool Game Author")
        .build()
        .expect("aieee, could not create ggez context!");
    let app = Application::new();
    event::run(ctx, event_loop, app);
}

struct Application {
}


impl EventHandler for Application<'_> {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        if something {
                let ua = UIAutomation::new().unwrap();  // panic!
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> Result<(), GameError> {
        let mut canvas = graphics::Canvas::from_frame(ctx, Color::WHITE);
        // Draw code here...
        canvas.finish(ctx)
    }
}

@niuhuan
Copy link
Author

niuhuan commented Apr 21, 2023

十分感谢您的提醒,他已经工作了, 在main方法中增加了let _ = UIAutomation::new().unwrap(); 设置com。

fn main(){
    let _ = UIAutomation::new().unwrap();
    let (mut ctx, event_loop) = ContextBuilder::new("my_game", "Cool Game Author")
        .build()
        .expect("aieee, could not create ggez context!");
    let app = Application::new();
    event::run(ctx, event_loop, app);
}

@leexgone
Copy link
Owner

我在v0.5.1版本上增加了一个UIAutomation::new_direct()方法,忽略COM初始化直接创建自动化对象,你可以自行管理COM环境的初始化,或者使用其它类库的初始化操作。

@lededev
Copy link

lededev commented Dec 16, 2023

我在v0.5.1版本上增加了一个UIAutomation::new_direct()方法,忽略COM初始化直接创建自动化对象,你可以自行管理COM环境的初始化,或者使用其它类库的初始化操作。

这个新增方法对于我在rust生成的.dll中调用很有帮助,因为.exe的C++已经进行过了COM初始化。

@rust-kotlin
Copy link
Contributor

rust-kotlin commented Aug 1, 2024

我在v0.5.1版本上增加了一个UIAutomation::new_direct()方法,忽略COM初始化直接创建自动化对象,你可以自行管理COM环境的初始化,或者使用其它类库的初始化操作。

在Tauri中使用,目的是提供一个自动化操作的Tauri command函数给前端调用,也遇到了这个报错。之前是通过spawn到一个新的线程中解决中

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants