fix: Cyrillic window titles garbled in device list

PowerShell on Russian Windows outputs text in CP1251/CP866 by default.
Node.js reads stdout as UTF-8 → Cyrillic becomes mojibake.

Fix: force UTF-8 output at the start of every PowerShell command:
  [Console]::OutputEncoding = [System.Text.Encoding]::UTF8;
  $OutputEncoding = [System.Text.Encoding]::UTF8;

Receive stdout as raw Buffer (encoding:'buffer'), strip UTF-8 BOM
if present, then decode explicitly with .toString('utf8').

Also fixed runCommand() to collect chunks into Buffer arrays and
decode as UTF-8 (FFmpeg always outputs UTF-8 regardless of locale).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
admin
2026-04-16 01:27:22 +03:00
parent a401680b47
commit 6b0c2ca0ae
+28 -10
View File
@@ -22,21 +22,31 @@ function getFfmpegPath() {
function runCommand(cmd, args, timeoutMs = 10000) {
return new Promise((resolve) => {
const proc = spawn(cmd, args, { stdio: ['pipe', 'pipe', 'pipe'] })
let stdout = '', stderr = ''
proc.stdout.on('data', d => stdout += d)
proc.stderr.on('data', d => stderr += d)
proc.on('close', () => resolve({ stdout, stderr }))
const outBufs = [], errBufs = []
proc.stdout.on('data', d => outBufs.push(d))
proc.stderr.on('data', d => errBufs.push(d))
const finish = () => {
// FFmpeg outputs UTF-8; on Russian Windows system tools may use CP1251,
// but FFmpeg is always UTF-8 — safe to decode as utf8 here.
const stdout = Buffer.concat(outBufs).toString('utf8')
const stderr = Buffer.concat(errBufs).toString('utf8')
resolve({ stdout, stderr })
}
proc.on('close', finish)
proc.on('error', () => resolve({ stdout: '', stderr: '' }))
setTimeout(() => { try { proc.kill() } catch {} ; resolve({ stdout, stderr }) }, timeoutMs)
setTimeout(() => { try { proc.kill() } catch {} }, timeoutMs)
})
}
// ─── Windows — enumerate application windows via PowerShell ───────────────────
// Uses execFile to pass arguments as array → no quoting/escaping issues
// KEY: force UTF-8 output BEFORE any text is written, receive as Buffer,
// then decode as UTF-8 — this fixes Cyrillic/Unicode window titles on Russian Windows.
function getWindowsWindowsList() {
return new Promise((resolve) => {
// Each line: "WindowTitle|||ProcessName"
// Force UTF-8 console output so Node receives proper Unicode
const ps1 = [
'[Console]::OutputEncoding = [System.Text.Encoding]::UTF8;',
'$OutputEncoding = [System.Text.Encoding]::UTF8;',
'Get-Process',
'| Where-Object { $_.MainWindowTitle -ne "" }',
'| Sort-Object MainWindowTitle',
@@ -46,9 +56,17 @@ function getWindowsWindowsList() {
execFile(
'powershell.exe',
['-NonInteractive', '-NoProfile', '-WindowStyle', 'Hidden', '-Command', ps1],
{ timeout: 8000, windowsHide: true },
(err, stdout) => {
if (err || !stdout) { resolve([]); return }
// encoding: 'buffer' — receive raw bytes, we decode manually as UTF-8
{ timeout: 8000, windowsHide: true, encoding: 'buffer' },
(err, stdoutBuf) => {
if (err || !stdoutBuf || !stdoutBuf.length) { resolve([]); return }
// Decode the buffer as UTF-8 (PowerShell wrote UTF-8 BOM-less)
// Strip UTF-8 BOM if present (EF BB BF)
let buf = stdoutBuf
if (buf[0] === 0xEF && buf[1] === 0xBB && buf[2] === 0xBF) buf = buf.slice(3)
const stdout = buf.toString('utf8')
const wins = stdout.trim().split('\n')
.map(l => l.trim().replace(/\r$/, ''))
.filter(Boolean)