Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python, Windows 10: launching an application on a specific virtual desktop environment (work-spaces)

I have 3 different Windows 10 virtual desktops. When the computer starts up, I want python to load all of my applications in the different virtual desktops.

Right now I can only start things in Desktop 1. How do I tell python to launch an app but in Desktop 2 and 3?

I'm using python 3.6.

like image 993
jason Avatar asked Mar 27 '20 02:03

jason


People also ask

How do I open a program on virtual desktop?

To open a file or program in a new virtual desktop, right-click on the file, program .exe file, or program shortcut and select “Open in new virtual desktop” from the popup menu. A new virtual desktop is created and the selected file or program is opened on that virtual desktop.

How do you switch between several open windows in the desktop environment?

Flip. You can use Flip to switch between open windows. To do this, press and hold the Alt key on your keyboard, then press the Tab key. Continue pressing the Tab key until the desired window is selected.


2 Answers

How do I tell python to launch an app but in Desktop 2 and 3?

This can be achieved by launching your applications with subprocess.Popen(), then changing virtual desktop by calling GoToDesktopNumber() from VirtualDesktopAccessor.dll with the help of ctypes, and launching your applications again. Tested with 64-bit Windows 10 Version 10.0.18363.720.

VirtualDesktopAccessor.dll by Jari Pennanen exports the functions a part of the mostly undocumented (by Microsoft) Virtual Desktop API. Put the dll in the current working directory.

import ctypes, time, shlex, subprocess

def launch_apps_to_virtual_desktops(command_lines, desktops=3):
    virtual_desktop_accessor = ctypes.WinDLL("VirtualDesktopAccessor.dll")
    for i in range(desktops):
        virtual_desktop_accessor.GoToDesktopNumber(i)
        time.sleep(0.25) # Wait for the desktop to switch
        for command_line in command_lines:
            if command_line:
                subprocess.Popen(shlex.split(command_line))
        time.sleep(2) # Wait for apps to open their windows
    virtual_desktop_accessor.GoToDesktopNumber(0) # Go back to the 1st desktop

command_lines = r"""
"C:\Program Files (x86)\Google\Chrome Beta\Application\chrome.exe"
"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" "C:\StudyGuide.pdf"
"C:\Program Files\Mozilla Firefox\firefox.exe"
"C:\Program Files\VideoLAN\VLC\vlc.exe"
""".splitlines()

launch_apps_to_virtual_desktops(command_lines)

The time.sleep() calls are needed because Windows doesn't change virtual desktops instantly (presumably because of animations), and to give the processes time to create windows. You might need to tweak the timings.

Note that some applications only allow one instance/process, so you can't get multiple separate windows for each virtual desktop (e.g. Adobe Reader with default settings).


Another strategy I tried was launching the applications, sleeping for a bit to allow the windows to be created, then calling MoveWindowToDesktopNumber() to move every window created by the new processes to different virtual desktops. The problem with that is, for applications like Chrome or Firefox, the new process is immediately closed if an existing process already exists, so it doesn't move the new windows (which actually belong to another, older process) to another desktop.

import ctypes, time, shlex, subprocess
from ctypes.wintypes import *
from ctypes import windll, byref

def get_windows(pid):
    current_window = 0
    pid_local = DWORD()
    while True:
        current_window = windll.User32.FindWindowExA(0, current_window, 0, 0)
        windll.user32.GetWindowThreadProcessId(current_window, byref(pid_local))
        if pid == pid_local.value:
            yield current_window

        if current_window == 0:
            return

def launch_apps_to_virtual_desktops_by_moving(command_lines, desktops=3):
    virtual_desktop_accessor = ctypes.WinDLL("VirtualDesktopAccessor.dll")
    for i in range(desktops):
        pids = []
        for command_line in command_lines:
            if command_line:
                args = shlex.split(command_line)
                pids.append(subprocess.Popen(args).pid)

        time.sleep(3)
        for pid in pids:
            for window in get_windows(pid):
                window = HWND(window)
                virtual_desktop_accessor.MoveWindowToDesktopNumber(window, i)

command_lines = r"""
"C:\Program Files (x86)\Google\Chrome Beta\Application\chrome.exe"
"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" "C:\StudyGuide.pdf"
"C:\Program Files\Mozilla Firefox\firefox.exe"
"C:\Program Files\VideoLAN\VLC\vlc.exe"
""".splitlines()

launch_apps_to_virtual_desktops_by_moving(command_lines)
like image 131
GordonAitchJay Avatar answered Sep 22 '22 08:09

GordonAitchJay


TL; DR: use VDesk?


It appears that in-built support for this in Windows was lacking a few years back:

"Are you referring to task view feature "Multiple desktops" in Windows 10?

If yes, please be informed that you cannot have apps/programs automatically startup in different desktops.

-- A. User

I don't know of a python-native approach, but there's a couple of answers on the topic more generally that suggest VDesk -- https://github.com/eksime/VDesk

VDesk is a free, open source, program for the Windows 10 operating system that extends a system's virtual desktop functionality.

-- MSPO

This plus the usual methods to invoke external programs from python (i.e. the subprocess module) should hopefully get the effect you want. Good luck.

like image 31
Dragon Avatar answered Sep 25 '22 08:09

Dragon