我试着写一个使用Windows.Web.UI.Interop.WebViewControl
一定的防锈代码(这是一个进程外,通用的Windows平台包装特意设计使Win32的应用程序可以使用EdgeHTML),这一切都编译,但不会在运行时正常工作。
相关的代码归结到这一点,使用winit,WINAPI和WinRT的包装箱:
use winit::os::windows::WindowExt;
use winit::{EventsLoop, WindowBuilder};
use winapi::winrt::roapi::{RoInitialize, RO_INIT_SINGLETHREADED};
use winapi::shared::winerror::S_OK;
use winrt::{RtDefaultConstructible, RtAsyncOperation};
use winrt::windows::foundation::Rect;
use winrt::windows::web::ui::interop::WebViewControlProcess;
fn main() {
assert!(unsafe { RoInitialize(RO_INIT_SINGLETHREADED) } == S_OK);
let mut events_loop = EventsLoop::new();
let window = WindowBuilder::new()
.build(&events_loop)
.unwrap();
WebViewControlProcess::new()
.create_web_view_control_async(
window.get_hwnd() as usize as i64,
Rect {
X: 0.0,
Y: 0.0,
Width: 800.0,
Height: 600.0,
},
)
.expect("Creation call failed")
.blocking_get()
.expect("Creation async task failed")
.expect("Creation produced None");
}
该WebViewControlProcess
实例化的工作,并且CreateWebViewControlAsync
功能似乎去关心它收到host_window_handle
值(它传递0,或一次性从实际HWND
值,它抱怨)。然而,在IAsyncOperation
AsyncStatus.Started
(0)坚决保持,所以blocking_get()
呼叫无限期挂起。
A full, runnable demonstration of the issue (with a bit more instrumentation)。
我得到了WebViewControlProcess
是有过错的感觉:它ProcessId
是停留在0,它不看已经催生了任何子。该ProcessExited
事件似乎并没有被被解雇(我重视的东西给它实例化后,有没有为它之前被解雇的机会呢?)。调用如想象中在这种情况下,Terminate()
E_FAIL
失败。
我错过了某种初始化使用Windows.Web.UI.Interop
?或者是有,为什么它不工作的一些其他原因?
原来,问题是线程相关的:在winit箱子是做事件循环在不同的线程,我并没有意识到这一点;我曾错误地认为winit是一种无害的抽象,它竟然不是很要。
我发现这一点,当我试图尽量减少和移植一个C运行已知++例子,这次做的所有的Win32 API调用手动而不是使用winit,使翻译是正确的。我得到它的工作,并发现了这一点:
该IAsyncOperation
满足在事件循环,深一DispatchMessageW
调用中。也就是说,当Completion
处理程序被调用。因此,操作完成,你必须运行在同一个线程事件循环。 (在另一个线程的事件循环没有做任何事情。)否则,它停留在Started
状态。
幸运的是,winit is already moving to a new event loop which operates in the same thread,与Windows实现有一个前几天登陆;当我迁移我的代码使用事件循环,分支2.0的winit,并使用Completed
处理不是blocking_get()
,这一切都开始工作。
我要澄清有关WinRT的板条箱的blocking_get()
调用,它通常会同时原型明显的解决方案:你不能在这种情况下使用它,因为它会导致死锁,因为它会阻止,直到IAsyncOperation
完成,但IAsyncOperation
将无法完成,直到你处理在事件循环(DispatchMessageW
),因为你阻塞线程,这将永远不会发生的消息。
尝试初始化WebViewProcessControl
与winrt::init_apartment();
,它可能需要一个单线程单元(根据本answer)。
在Microsoft Edge Developer Guide更多的关注:
最后,电力用户可能会注意到的桌面应用程序的Web浏览器(以前称为Win32WebViewHost),相当于在Win32的WebView,在以下场所内部系统应用程序的外观:
●在Windows 10行动中心。这些通知的源应被理解为从一个Win32应用程序托管的网页视图。
●在设备访问设置UI(设置 - >与隐私>相机/地点/麦克风)。禁用任何这些设置拒绝从Win32中的应用程序托管的所有网页视图访问。