Этот пост относится к категории «функционал ради функционала», чем к решению отдельно взятой проблемы. Но про проблему нужно рассказать отдельно.
Есть общественный компьютер, который после перезапуска возвращается к состоянию, бережно упакованному в образ с помощью вот этой штуковины. И вот именно в этой среде нужно было обеспечить скринкастинг. Затевать установку привычного инструмента не хотелось, так как стоит машине уйти в перезапуск — установку придётся повторять снова.
Остановившись на функционале встроенного в операционную систему скринкаст-рекордера под капотом Xbox Game Bar, я решил работать именно с ним, а уже получившееся видео скормить прожорливому ffmpeg. Здесь-то и поджидала первая неожиданность…
Мне приходилось работать с компьютером удалённо через это невероятное чудо, а это означало, что по какой-то причине я никак не мог передать на удалённый хост сочетание Win+G. Да и вызвать Xbox Game Bar простой и односложной командой, как оказалось, нельзя.
Конечно, после долгих поисков я всё-таки нашёл команду для вызова Xbox Game Bar:
shell:AppsFolder\Microsoft.XboxGamingOverlay_8wekyb3d8bbwe!App
Согласитесь, что эта конструкция лаконичностью не отличается. Правда на данном этапе вызов Xbox Game Bar мне совершенно ничем не помог. Всё дело в том, что Xbox Game Bar подхватывает активное окно и вызвать запись можно только с него. В этом заключалась вторая крайне неприятная неожиданность.
Пришлось шаманить скрипт, который бы активировал нужное окно и уже потом запускал бы Xbox Game Bar. Мне бы оставалось только нажать на запись.
Код скрипта:
# Заголовок окна #
[System.Console]::Title = "Поиск окна и запуск Xbox Game Bar"
# Добавляем код .Net #
Add-Type @"
using System;
using System.Runtime.InteropServices;
using System.Text;
public class WindowHelper
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool EnumWindows(EnumWindowProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr lParam);
public static IntPtr FindWindowByPartialTitle(string partialTitle)
{
IntPtr foundWindow = IntPtr.Zero;
EnumWindows((hWnd, lParam) =>
{
StringBuilder windowText = new StringBuilder(256);
GetWindowText(hWnd, windowText, windowText.Capacity);
if (windowText.ToString().Contains(partialTitle))
{
foundWindow = hWnd;
return false;
}
return true;
}, IntPtr.Zero);
return foundWindow;
}
}
"@
# Указываем часть названия окна #
$PartialTitle = "Chromium"
# Обращемся к методу FindWindowByPartialTitle класса WindowHelper #
$FindWindow = [WindowHelper]::FindWindowByPartialTitle($PartialTitle)
# Если окно найдено, активируем его и запускаем Xbox Game Bar #
if ($FindWindow -ne [IntPtr]::Zero)
{
# Обращемся к методу SetForegroundWindow класса WindowHelper #
[WindowHelper]::SetForegroundWindow($FindWindow) | Out-Null
# Запускаем Xbox Game Bar #
Start-Process shell:AppsFolder\Microsoft.XboxGamingOverlay_8wekyb3d8bbwe!App
}
else
{
Write-Host -ForegroundColor Red "Окно с частью названия $PartialTitle не найдено."
Sleep(10)
}
Сразу после запуска скрипт попробует отыскать окно с названием, упомянутым в переменной $PartialTitle. Если окно найдено — оно становится активным и запускается Xbox Game Bar. Теперь, как и планировалось, нужно только нажать на кнопку записи.