1

I'm primarily using Windows, where I run WSL2. So from a python script running in the subsystem, I would like to screenshot whatever is on windows monitor, as simple as such:

v1

import mss
import os

os.environ['DISPLAY'] = ':0'

with mss.mss() as sct:
    sct.shot()

This gives only gives "Segmentation fault" error and no image. So I tried to setup vcxsrv in Windows and I'm able to open stuff from my subsystem in Windows through the server, however I cant get it the other way around..

I just want access to the windows screen so I can screenshot it. Any help about how to access the monitor through wsl would be greatly appreciated, I can't find much on google..

robinmanz
  • 361
  • 1
  • 5
  • 17
  • Isn't the whole idea that it's a "subsystem" in that it really should be sandboxed from the host...? Doesn't the idea of this violate that principle? – esqew Feb 11 '22 at 22:28
  • I'm planning to use certain python packages thats not very compatible with Windows, but on a day to day basis I use windows, so therefor working in the subsystem for these purposes. I just need access to the screen. – robinmanz Feb 11 '22 at 22:38
  • 2
    @esqew I would have to say that no, WSL definitely isn't a "sandboxed" environment. One of its primary benefits are its great interop features that allow it to connect to Windows drives (through 9P), executables (through `binfmt_misc`, and more. That said, there's no direct interop feature that I can think of that will accomplish this. It will need *some* additional effort. I'll give it a shot and answer if I can come up with something. – NotTheDr01ds Feb 11 '22 at 22:58

2 Answers2

1

The problem with your attempted solution is that the WSL/Linux Python's mss, as you've found, isn't able to capture the Windows desktop. Being the Linux version of MSS, it will only be able to communicate with Linux processes and protocols like X. Starting up VcXsrv might get you part of the way there, in that you might be able to capture X output, but you may need to be running the Python app from inside a terminal that is running in a X window.

Regardless, you've said that your goal is to capture the entire Windows desktop, not just the X output in VcXsrv. To do that, you'll need to use a Windows process of some sort.

But don't worry; using WSL's interop, you can still do that from inside WSL/Linux Python. We just need to call out to a Windows .exe of some sort.

There are literally dozens of third-party apps that you could use in Windows to create a screenshot. But I prefer to use a solution that doesn't require any additional installation.

So I resorted to PowerShell for this, since you can easily call powershell.exe and pass in a script from WSL. There are a number of examples here on Stack Overflow, but I ended up going slightly "lower tech" to try to simplify a bit. The code here is most similar to this solution, so refer to that if you want to expand on this.

From WSL/Linux Python:

import os
os.system("""
    powershell.exe \"
        Add-Type -AssemblyName System.Windows.Forms
        [Windows.Forms.Sendkeys]::SendWait('+{Prtsc}')
        \$img = [Windows.Forms.Clipboard]::GetImage()
        \$img.Save(\\\"\$env:USERPROFILE\\Pictures\\Screenshots\\screenshot.jpg\\\", [Drawing.Imaging.ImageFormat]::Jpeg)\"
""")

That essentially sends the ShiftPrintScreen key chord to capture the current desktop to the clipboard, then saves the clipboard. It can get slightly hairy with the quoting, since you are essentially wrapping PowerShell inside a /bin/sh inside a Python script.

Note that, even though you are in Linux Python, since it's the Windows PowerShell that we are calling, it takes the Windows path format (C:\Users\Username\Pictures...) rather than the Linux version (/mnt/c/Users/...).

While I didn't have any timing issues with this, you may need to insert small delays. Again, refer to the existing answer for that. This solution is primarily to explain how to do it through WSL's Python using PowerShell.

NotTheDr01ds
  • 15,620
  • 5
  • 44
  • 70
  • Thank you for taking the time for experimenting and finding a solution. I gave you the check mark for that. However it was not exactly the solution I was needing.. I ended up just dropping WSL alltogether and running barebone on windows supplementet by anaconda for managing the enviornment. Thanks again – robinmanz Feb 12 '22 at 17:36
-1

if you are on a laptop you could hit the windows button and prtsc to take a screenshot and if you are on PC you could use OBS its recording software that can do pretty much anything.

DJDimsa
  • 3
  • 1
  • 2
    This does not adequately answer the question. The OP is quite clearly looking for ways to *programmatically* capture a screenshot. – esqew Feb 11 '22 at 22:40