WinRT 概念

参考资料:https://docs.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide

WinRT(Windows Runtime) 和 WinRT APIs 是 Windows API 的进化。之前的 Windows 编程是通过 Win32 C APIs 。

WinRT 设计成可以被不同的编程语言调用,每种语言调用 WinRT APIs 的方式都是非常自然的,符合语言本身的特性。

WinRT APIs 所有的接口文档目录:https://docs.microsoft.com/en-us/uwp/api/?view=winrt-20348

Python/WinRT

pywinrt 是 python 调用 WinRT 的包,要求 Windows >= 1809 , Python >= 3.7

使用 Uri

文档地址:https://docs.microsoft.com/en-us/uwp/api/windows.foundation.uri?view=winrt-18362

1
2
3
4
import winrt.windows.foundation as wf
u = wf.Uri("https://github.com/")
u2 = u.combine_uri("Microsoft/xlang/tree/master/src/tool/python")
print(str(u2))

需要注意的地方是 WinRT 的函数命名都转换成了 Python 下划线风格

开关蓝牙

文档地址:https://docs.microsoft.com/en-us/uwp/api/windows.devices.radios?view=winrt-20348

Radio 相关的 API 涉及到了异步操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import asyncio

from winrt.windows.devices.radios import Radio, RadioKind, RadioState

async def main():
    radios = await Radio.get_radios_async()

    bluetooth_radio = None
    for radio in radios:
        if radio.kind == RadioKind.BLUETOOTH:
            bluetooth_radio = radio
    if not bluetooth_radio:
        return

    print(f"name: {bluetooth_radio.name}, state: {bluetooth_radio.state}")
    await bluetooth_radio.set_state_async(RadioState.ON)
    print(f"name: {bluetooth_radio.name}, state: {bluetooth_radio.state}")

asyncio.get_event_loop().run_until_complete(main())

WinRT 中所有带 Async 的异步接口可以使用 Python 中的 async/await 技术

遇到的问题

COM 初始化冲突

_winrt.init_apartment() RuntimeError: 无法在设置线程模式后对其加以更改。

当 winrt 和 comtypes 同时使用会有这个问题,原因是 winrt 模块载入时会调用 init_apartment , 这个函数会调用 CoInitializeEx 初始化 COM ,参数是 COINIT_MULTITHREADED ,comtypes 加载时也会调用 CoInitializeEx ,但是参数是 COINIT_APARTMENTTHREADED ,两者会冲突从而出现上面的错误。

解决方法:调用 CoUninitialize 将 winrt 的调用取消掉,然后利用 comtypes 初始化 COM

1
2
3
4
5
# fix: Cannot change thread mode after it is set
from winrt.windows.foundation import Uri
windll.ole32.CoUninitialize()
import comtypes

相关 issue: https://github.com/microsoft/xlang/issues/690