Да, всё верно, запускать службу на экране входа. Только что попробовал двигать и менять положение окна логина - не поддаётся, к сожалению. А вот скрыть или свернуть/развернуть его вполне можно. Очевидно, что позиция и размер окна прибиты гвоздями к основному экрану и обновляются приложением логина в реальном времени. Так что тут остаётся только несколько вариантов:
- Попробовать изменить настройки экрана на дублирование
- Реализовать своё окно логина - с дублированием ввода в оригинальное или возможно через даже через Credential Provider (не щупал - как оно работает не знаю)
- Попробовать хакнуть процесс логина через редактирование его памяти и вписать нужные значения в переменные позиции и размера окна - вот тут тоже может не сработать из-за ограничений безопасности
Такую службу я уже как-то давно запилил:
https://github.com/VoidVolker/Windows-logon-service - она умеет запускать любые приложения в любом количестве на экране входа. А вот пример приложения, которое её использует:
https://github.com/VoidVolker/LockScreen - показывает обои на всех дополнительных экранах логина. Там же легко найдёте код для работы со списком экранов - можете спокойно использовать (только ссылку укажите на репозиторий). А если сделаете с открытым исходным кодом - вообще отлично будет. Только WPF не используйте - там жуткий маразм из-за DPI с размещением окон на нескольких мониторах. Лучше WinForms или С/С++/WinAPI на любом ЯП. Для ковыряния в окнах есть великолепнейшая утилита InqSoft Window Scanner (древний раритет, но сравнимых по функционалу аналогов нет).
UPD: проверил возможность переключения основного экрана в сессии логона - работает! Итак, решение следующее:
- Качаем nircmd: https://www.nirsoft.net/utils/nircmd.html
Команда для переключения монитора следующая: https://nircmd.nirsoft.net/setprimarydisplay.html
❯ ./nircmd.exe setprimarydisplay 1
❯ ./nircmd.exe setprimarydisplay 2
❯ ./nircmd.exe setprimarydisplay \\.\DISPLAY3
- Пишем простейшее приложение, которое при старте переключает монитор на нужный через nircmd, а при получении команды остановки - переключает монитор обратно. Вот на счёт события остановки не уверен - т.к. у меня в сервисе используется стандартный Process.Kill() без ожидания, при этом ещё и сессия логона закрывается и отработает ли событие - не знаю, не проверял. Возможно, добавлю в сервис опцию для выполнения команды перед закрытием сессии.