robmikh / Win32CaptureSample

A simple sample using the Windows.Graphics.Capture APIs in a Win32 application.
MIT License
293 stars 88 forks source link

Graphics Capture doesn't work when running as different user? #54

Open elvissteinjr opened 1 year ago

elvissteinjr commented 1 year ago

Been a while, but it's me again. Hopefully I didn't miss anything obvious this time.

The scenario is the following: A user of my application is using a standard user account for daily use, but needs to run my application as administrator sometimes. They are launching the application from their standard account, but as the separate admin account (as opposed to straight elevating from an admin account).

In this scenario, Graphics Capture appears to be unavailable. Win32CaptureSample crashes, but this is recoverable by catching exceptions when calling GraphicsCaptureSession::IsSupported(). From what I've observed, it throws winrt::hresult_error (0x80070424, "Service does not exist" afaik) on Windows 11 and std::bad_alloc on Windows 10 (haven't gone through all major versions though). The latter threw me off as I was only catching winrt::hresult_error in my app, which seemed to be good enough on older versions of Windows that didn't support Graphics Capture.

I suppose I can at least not crash with this, but I've been wondering if this is intentional. Guess the desktop and windows of another user may be inaccessible here? The way it fails is a bit unexpected though, and Desktop Duplication still works fine.

I don't disagree if the answer is just "don't do that". Their case here is that they have things in the chain that need admin (Steam with some launchers apparently) and my application is affected down the line (SteamVR as another user won't connect to my app). Admin account just elevating when necessary works fine, of course.

This more of an API question again, I suppose (unless you want to catch this in the sample), but I'm thankful that you can be reached through this project.

robmikh commented 1 year ago

Hello again!

robmikh commented 1 year ago

Sorry, keyboard went rogue.

Hello again!

The main requirement for Windows.Graphics.Capture is that it is run by a user in an interactive session. It should work as a separate user in the same session. Can you confirm that the method used to launch as a different user isn't running it in session 0 or a non-interactive session? What's the method being used here?

elvissteinjr commented 1 year ago

The session ID of the process matches the one used by other processes of the original active user (so not 0 or a wildly different one). The method of launching, at least for my testing, is simply running the executable as adminstrator from Explorer (admin has to be a different account here, as said), or using "Run as different user" from Explorer. For debugging, doing the same to Visual Studio and launching from there gave the same results. Admin or not makes no difference here, actually. It can also just be two standard accounts.

rogerou commented 1 year ago

@elvissteinjr I have same problem here, have you solved this?

elvissteinjr commented 1 year ago

I only worked around it by additionally catching std::bad_alloc to not crash. My application also supports Desktop Duplication and already deals with Graphics Capture not being available, meaning there's still some functionality left in this case. I left it that at (I don't know if my affected user even wanted to capture windows, but no complaints followed).

I'm not sure if this is solvable from the application side anyways. Best thing I could come up with is to perhaps run Graphics Capture in a separate process under the user that owns the session, then share the texture with the main process perhaps. Not something I've explored myself yet though, so no idea if this is viable.

robmikh commented 1 year ago

Sorry for the delay. This is clearly something I need to spend some more time to investigate. In some cases this works and in others it doesn't. For now, developers should consider using capture with a different user as something that may not work.