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

is_border_required = False hard crashes #13

Closed
Avasam opened this issue Jun 16, 2022 · 4 comments
Closed

is_border_required = False hard crashes #13

Avasam opened this issue Jun 16, 2022 · 4 comments
Labels
bug Something isn't working

Comments

@Avasam
Copy link

Avasam commented Jun 16, 2022

This is the error from the Event Viewer:

Faulting application name: python.exe, version: 3.9.6150.1013, time stamp: 0x60d9eb23
Faulting module name: _winrt.pyd, version: 0.0.0.0, time stamp: 0x62a021ac
Exception code: 0xc0000005
Fault offset: 0x00000000005a667b
Faulting process ID: 0x6764
Faulting application start time: 0x01d881b77d70cee9
Faulting application path: C:\Program Files\Python39\python.exe
Faulting module path: C:\Program Files\Python39\lib\site-packages\winsdk\_winrt.pyd
Report ID: d2add601-2895-4e52-a8b7-074c7b3ae78c
Faulting package full name: 
Faulting package-relative application ID: 

Minimal repro:

import asyncio

import win32gui
from winsdk.windows.graphics.capture import (Direct3D11CaptureFramePool,
                                             GraphicsCaptureItem)
from winsdk.windows.graphics.capture.interop import create_for_window
from winsdk.windows.graphics.directx import DirectXPixelFormat
from winsdk.windows.media.capture import MediaCapture


def create_windows_graphics_capture(item: GraphicsCaptureItem):
    media_capture = MediaCapture()

    async def coroutine():
        await (media_capture.initialize_async() or asyncio.sleep(0))
    asyncio.run(coroutine())

    if not media_capture.media_capture_settings:
        raise OSError("Unable to initialize a Direct3D Device.")
    frame_pool = Direct3D11CaptureFramePool.create_free_threaded(
        media_capture.media_capture_settings.direct3_d11_device,
        DirectXPixelFormat.B8_G8_R8_A8_UINT_NORMALIZED,
        1,
        item.size)
    if not frame_pool:
        raise OSError("Unable to create a frame pool for a capture session.")
    session = frame_pool.create_capture_session(item)
    if not session:
        raise OSError("Unable to create a capture session.")
    session.is_cursor_capture_enabled = False
    try:
        # This "crashes" (force closes the program, no python error)
        session.is_border_required = False
    except:
        print("caught")


def print_hwnd(hwnd: int, _):
    window_text = win32gui.GetWindowText(hwnd)
    if (
        window_text
        and window_text not in ("Default IME", "MSCTFIME UI")
        and "Window" not in window_text
    ):
        print(hwnd, window_text)


win32gui.EnumWindows(print_hwnd, '')


while True:
    try:
        hwnd = int(input("^ Enter an HWND from above ^ :"))
    except:
        print("not an int")
        continue

    try:
        print("Selected window:", win32gui.GetWindowText(hwnd))
    except:
        print("not a valid HWND")
        continue

    item = create_for_window(hwnd)
    create_windows_graphics_capture(item)

Microsoft's docs does mentions needing to call the following first GraphicsCaptureAccess.request_access_async(GraphicsCaptureAccessKind.BORDERLESS): https://docs.microsoft.com/en-us/uwp/api/windows.graphics.capture.graphicscapturesession.isborderrequired#remarks

If possible, I would ask for python-winsdk to raise an appropriate exception rather than letting the entire application crash silently.

Sidenote, GraphicsCaptureAccess.request_access_async also throws OSError: [WinError -2147221164] Class not registered, but this may or may not be due to the lack of an application manifest declaring the graphicsCaptureWithoutBorder. Or because it's Win11 only. I'll need to try both. The former I can do when I bundle my app with PyInstaller.

Edit: see coment

@Avasam Avasam changed the title GraphicsCaptureSessionis_border_required = False hard crashes is_border_required = False hard crashes Jun 16, 2022
@Avasam
Copy link
Author

Avasam commented Jun 16, 2022

Update: It does all work on a Windows 11 machine (I didn't even need to call GraphicsCaptureAccess.request_access_async(GraphicsCaptureAccessKind.BORDERLESS) when running from whithin VSCode) I did try with and without border to make sure I was actually capturing the window.

Still I think that raising a proper error in Python will be preferable over letting the whole thing hard crash

@dlech
Copy link
Contributor

dlech commented Jun 16, 2022

So the crash only happens on older versions of Windows? Which version specifically?

@dlech dlech added the bug Something isn't working label Jun 16, 2022
@Avasam
Copy link
Author

Avasam commented Jun 16, 2022

Version 10.0.19044 Build 19044 (latest Windows 10)
Python 3.9.6
winsdk 1.0.0b5

For now I've resorted to checking the version using platform.version since I can't try-catch

dlech added a commit to pywinrt/pywinrt that referenced this issue Jul 24, 2022
The generated code can include APIs for any version of windows but be
run on older versions of windows. This causes crashes when trying to
call these apis from older versions of windows.

We can avoid the crash by doing a runtime check to see if a property/
event/method actually exists before attempting to call it.

Issue:  pywinrt/python-winsdk#13
@dlech
Copy link
Contributor

dlech commented Sep 9, 2022

This should be fixed in v1.0.0b7.

@dlech dlech closed this as completed Sep 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

2 participants