@erica-s/ai-agent-notify 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.published +1 -0
- package/README.md +100 -0
- package/assets/icons/info.png +0 -0
- package/assets/icons/permission.png +0 -0
- package/assets/icons/stop.png +0 -0
- package/bin/cli.js +3104 -0
- package/lib/codex-sidecar-state.js +314 -0
- package/lib/notification-sources.js +411 -0
- package/package.json +41 -0
- package/postinstall.js +54 -0
- package/scripts/activate-window.ps1 +26 -0
- package/scripts/activate-window.vbs +13 -0
- package/scripts/codex-notify-wrapper.vbs +29 -0
- package/scripts/find-hwnd.ps1 +144 -0
- package/scripts/get-shell-pid.ps1 +69 -0
- package/scripts/notify.ps1 +193 -0
- package/scripts/register-protocol.ps1 +18 -0
- package/scripts/start-hidden.vbs +24 -0
- package/scripts/start-tab-color-watcher.ps1 +41 -0
- package/scripts/tab-color-watcher.ps1 +391 -0
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
# Tab 颜色 watcher:先附着到目标 shell 的 console,保证 hook 场景也能命中目标 tab;
|
|
2
|
+
# 用户回到目标窗口后,再通过标准流和附着 console 双通道写 reset OSC 恢复默认颜色。
|
|
3
|
+
# 作为独立进程运行。
|
|
4
|
+
param(
|
|
5
|
+
[Parameter(Mandatory)][int]$TargetPid,
|
|
6
|
+
[string]$HookEvent = '',
|
|
7
|
+
[long]$TerminalHwnd = 0
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
$ErrorActionPreference = 'Stop'
|
|
11
|
+
|
|
12
|
+
# --- 日志 ---
|
|
13
|
+
function Write-Log($msg) {
|
|
14
|
+
$line = "[$(Get-Date -Format 'yyyy-MM-ddTHH:mm:ss.fffZ')] [watcher pid=$PID] $msg"
|
|
15
|
+
if ($env:TOAST_NOTIFY_LOG_FILE) {
|
|
16
|
+
try { [System.IO.File]::AppendAllText($env:TOAST_NOTIFY_LOG_FILE, "$line`n") } catch {}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
Write-Log "started TargetPid=$TargetPid HookEvent=$HookEvent TerminalHwnd=$TerminalHwnd"
|
|
21
|
+
|
|
22
|
+
# --- 颜色映射 ---
|
|
23
|
+
$colorMap = @{
|
|
24
|
+
'Stop' = 'rgb:33/cc/33'
|
|
25
|
+
'PermissionRequest' = 'rgb:ff/99/00'
|
|
26
|
+
}
|
|
27
|
+
$color = if ($colorMap.ContainsKey($HookEvent)) { $colorMap[$HookEvent] } else { 'rgb:33/99/ff' }
|
|
28
|
+
|
|
29
|
+
$ESC = [char]0x1B
|
|
30
|
+
$ST = "$ESC\"
|
|
31
|
+
|
|
32
|
+
# --- P/Invoke 定义 ---
|
|
33
|
+
Add-Type -TypeDefinition @'
|
|
34
|
+
using System;
|
|
35
|
+
using System.Runtime.InteropServices;
|
|
36
|
+
using System.Threading;
|
|
37
|
+
|
|
38
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
39
|
+
public struct LASTINPUTINFO {
|
|
40
|
+
public uint cbSize;
|
|
41
|
+
public uint dwTime;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public class TabWatcher {
|
|
45
|
+
[DllImport("kernel32.dll", SetLastError=true)]
|
|
46
|
+
public static extern bool FreeConsole();
|
|
47
|
+
|
|
48
|
+
[DllImport("kernel32.dll", SetLastError=true)]
|
|
49
|
+
public static extern bool AttachConsole(uint dwProcessId);
|
|
50
|
+
|
|
51
|
+
[DllImport("kernel32.dll", SetLastError=true)]
|
|
52
|
+
public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
|
|
53
|
+
|
|
54
|
+
[DllImport("kernel32.dll", SetLastError=true)]
|
|
55
|
+
public static extern bool CloseHandle(IntPtr hObject);
|
|
56
|
+
|
|
57
|
+
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
58
|
+
public static extern IntPtr CreateFileW(
|
|
59
|
+
string lpFileName, uint dwDesiredAccess, uint dwShareMode,
|
|
60
|
+
IntPtr lpSecurityAttributes, uint dwCreationDisposition,
|
|
61
|
+
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
|
|
62
|
+
|
|
63
|
+
[DllImport("kernel32.dll", SetLastError=true)]
|
|
64
|
+
public static extern bool WriteFile(
|
|
65
|
+
IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite,
|
|
66
|
+
out uint lpNumberOfBytesWritten, IntPtr lpOverlapped);
|
|
67
|
+
|
|
68
|
+
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
69
|
+
public static extern bool WriteConsoleW(
|
|
70
|
+
IntPtr hConsoleOutput, string lpBuffer, uint nNumberOfCharsToWrite,
|
|
71
|
+
out uint lpNumberOfCharsWritten, IntPtr lpReserved);
|
|
72
|
+
|
|
73
|
+
[DllImport("kernel32.dll", SetLastError=true)]
|
|
74
|
+
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
|
75
|
+
|
|
76
|
+
[DllImport("kernel32.dll", SetLastError=true)]
|
|
77
|
+
public static extern uint WaitForMultipleObjects(uint nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds);
|
|
78
|
+
|
|
79
|
+
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
80
|
+
public static extern IntPtr CreateMutexW(IntPtr lpMutexAttributes, bool bInitialOwner, string lpName);
|
|
81
|
+
|
|
82
|
+
[DllImport("kernel32.dll", SetLastError=true)]
|
|
83
|
+
public static extern bool ReleaseMutex(IntPtr hMutex);
|
|
84
|
+
|
|
85
|
+
[DllImport("user32.dll", SetLastError=true)]
|
|
86
|
+
public static extern IntPtr GetForegroundWindow();
|
|
87
|
+
|
|
88
|
+
[DllImport("user32.dll", SetLastError=true)]
|
|
89
|
+
public static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
|
|
90
|
+
|
|
91
|
+
[DllImport("kernel32.dll", SetLastError=true)]
|
|
92
|
+
public static extern bool GetNumberOfConsoleInputEvents(IntPtr hConsoleInput, out uint lpcNumberOfEvents);
|
|
93
|
+
|
|
94
|
+
public const uint SYNCHRONIZE = 0x00100000;
|
|
95
|
+
public const uint GENERIC_READ = 0x80000000;
|
|
96
|
+
public const uint GENERIC_WRITE = 0x40000000;
|
|
97
|
+
public const uint FILE_SHARE_READ = 0x00000001;
|
|
98
|
+
public const uint FILE_SHARE_WRITE = 0x00000002;
|
|
99
|
+
public const uint OPEN_EXISTING = 3;
|
|
100
|
+
public const uint WAIT_OBJECT_0 = 0;
|
|
101
|
+
public const uint WAIT_ABANDONED_0 = 0x00000080;
|
|
102
|
+
public const uint WAIT_TIMEOUT = 0x00000102;
|
|
103
|
+
public const uint WAIT_FAILED = 0xFFFFFFFF;
|
|
104
|
+
public const int ERROR_ALREADY_EXISTS = 183;
|
|
105
|
+
public static void SleepMs(int milliseconds) {
|
|
106
|
+
Thread.Sleep(milliseconds);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public static uint GetLastInputTick() {
|
|
110
|
+
LASTINPUTINFO info = new LASTINPUTINFO();
|
|
111
|
+
info.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
|
|
112
|
+
if (!GetLastInputInfo(ref info)) {
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
return info.dwTime;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
'@
|
|
119
|
+
|
|
120
|
+
function Write-OscToInheritedStreams([string]$seq, [string]$label) {
|
|
121
|
+
$data = [System.Text.Encoding]::ASCII.GetBytes($seq)
|
|
122
|
+
$stdoutOk = $false
|
|
123
|
+
$stderrOk = $false
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
$stdout = [Console]::OpenStandardOutput()
|
|
127
|
+
$stdout.Write($data, 0, $data.Length)
|
|
128
|
+
$stdout.Flush()
|
|
129
|
+
$stdoutOk = $true
|
|
130
|
+
} catch {
|
|
131
|
+
Write-Log "$label via inherited stdout failed: $_"
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
$stderr = [Console]::OpenStandardError()
|
|
136
|
+
$stderr.Write($data, 0, $data.Length)
|
|
137
|
+
$stderr.Flush()
|
|
138
|
+
$stderrOk = $true
|
|
139
|
+
} catch {
|
|
140
|
+
Write-Log "$label via inherited stderr failed: $_"
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if ($stdoutOk -or $stderrOk) {
|
|
144
|
+
Write-Log "$label via inherited streams stdout=$stdoutOk stderr=$stderrOk"
|
|
145
|
+
return $true
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
Write-Log "$label failed on both inherited streams"
|
|
149
|
+
return $false
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function Attach-TargetConsole {
|
|
153
|
+
[TabWatcher]::FreeConsole() | Out-Null
|
|
154
|
+
$attached = [TabWatcher]::AttachConsole([uint32]$TargetPid)
|
|
155
|
+
if (-not $attached) {
|
|
156
|
+
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
|
157
|
+
Write-Log "AttachConsole failed err=$err"
|
|
158
|
+
return [IntPtr]::Zero
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
Write-Log "attached to console of pid=$TargetPid"
|
|
162
|
+
$hIn = [TabWatcher]::CreateFileW(
|
|
163
|
+
"CONIN$",
|
|
164
|
+
[TabWatcher]::GENERIC_READ -bor [TabWatcher]::GENERIC_WRITE,
|
|
165
|
+
[TabWatcher]::FILE_SHARE_READ -bor [TabWatcher]::FILE_SHARE_WRITE,
|
|
166
|
+
[IntPtr]::Zero,
|
|
167
|
+
[TabWatcher]::OPEN_EXISTING,
|
|
168
|
+
0,
|
|
169
|
+
[IntPtr]::Zero
|
|
170
|
+
)
|
|
171
|
+
$invalidHandle = [IntPtr](-1)
|
|
172
|
+
if ($hIn -eq $invalidHandle) {
|
|
173
|
+
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
|
174
|
+
Write-Log "CreateFileW CONIN$ failed err=$err"
|
|
175
|
+
$hIn = [IntPtr]::Zero
|
|
176
|
+
} else {
|
|
177
|
+
Write-Log "opened CONIN$ handle=$hIn"
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
$hOut = [TabWatcher]::CreateFileW(
|
|
181
|
+
"CONOUT$",
|
|
182
|
+
[TabWatcher]::GENERIC_READ -bor [TabWatcher]::GENERIC_WRITE,
|
|
183
|
+
[TabWatcher]::FILE_SHARE_READ -bor [TabWatcher]::FILE_SHARE_WRITE,
|
|
184
|
+
[IntPtr]::Zero,
|
|
185
|
+
[TabWatcher]::OPEN_EXISTING,
|
|
186
|
+
0,
|
|
187
|
+
[IntPtr]::Zero
|
|
188
|
+
)
|
|
189
|
+
if ($hOut -eq $invalidHandle) {
|
|
190
|
+
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
|
191
|
+
Write-Log "CreateFileW CONOUT$ failed err=$err"
|
|
192
|
+
$hOut = [IntPtr]::Zero
|
|
193
|
+
} else {
|
|
194
|
+
Write-Log "opened CONOUT$ handle=$hOut"
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return @{
|
|
198
|
+
InputHandle = $hIn
|
|
199
|
+
OutputHandle = $hOut
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function Write-OscToAttachedConsole([IntPtr]$hOut, [string]$seq, [string]$label) {
|
|
204
|
+
if ($hOut -eq [IntPtr]::Zero) {
|
|
205
|
+
Write-Log "$label via attached console skipped: no handle"
|
|
206
|
+
return $false
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
$consoleOk = $false
|
|
210
|
+
try {
|
|
211
|
+
$charsWritten = 0
|
|
212
|
+
$consoleOk = [TabWatcher]::WriteConsoleW($hOut, $seq, [uint32]$seq.Length, [ref]$charsWritten, [IntPtr]::Zero)
|
|
213
|
+
if ($consoleOk -and $charsWritten -eq $seq.Length) {
|
|
214
|
+
Write-Log "$label via attached console WriteConsoleW chars=$charsWritten"
|
|
215
|
+
return $true
|
|
216
|
+
}
|
|
217
|
+
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
|
218
|
+
Write-Log "$label via attached console WriteConsoleW failed err=$err chars=$charsWritten"
|
|
219
|
+
} catch {
|
|
220
|
+
Write-Log "$label via attached console WriteConsoleW exception: $_"
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
$data = [System.Text.Encoding]::ASCII.GetBytes($seq)
|
|
225
|
+
$bytesWritten = 0
|
|
226
|
+
$fileOk = [TabWatcher]::WriteFile($hOut, $data, [uint32]$data.Length, [ref]$bytesWritten, [IntPtr]::Zero)
|
|
227
|
+
if ($fileOk -and $bytesWritten -eq $data.Length) {
|
|
228
|
+
Write-Log "$label via attached console WriteFile bytes=$bytesWritten"
|
|
229
|
+
return $true
|
|
230
|
+
}
|
|
231
|
+
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
|
232
|
+
Write-Log "$label via attached console WriteFile failed err=$err bytes=$bytesWritten"
|
|
233
|
+
} catch {
|
|
234
|
+
Write-Log "$label via attached console WriteFile exception: $_"
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return $false
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function Get-ConsoleInputEventCount([IntPtr]$hIn) {
|
|
241
|
+
if ($hIn -eq [IntPtr]::Zero) {
|
|
242
|
+
return $null
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
$count = 0
|
|
246
|
+
$ok = [TabWatcher]::GetNumberOfConsoleInputEvents($hIn, [ref]$count)
|
|
247
|
+
if (-not $ok) {
|
|
248
|
+
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
|
249
|
+
Write-Log "GetNumberOfConsoleInputEvents failed err=$err"
|
|
250
|
+
return $null
|
|
251
|
+
}
|
|
252
|
+
return [uint32]$count
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
# --- Named Mutex 防重复 ---
|
|
256
|
+
$mutexName = "Global\claude-notify-tab-$TargetPid"
|
|
257
|
+
$hMutex = [TabWatcher]::CreateMutexW([IntPtr]::Zero, $true, $mutexName)
|
|
258
|
+
if ($hMutex -eq [IntPtr]::Zero) {
|
|
259
|
+
Write-Log "CreateMutex failed, exiting"
|
|
260
|
+
exit 1
|
|
261
|
+
}
|
|
262
|
+
$lastErr = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
|
263
|
+
if ($lastErr -eq [TabWatcher]::ERROR_ALREADY_EXISTS) {
|
|
264
|
+
Write-Log "mutex already exists, waiting for old watcher to release"
|
|
265
|
+
$waitResult = [TabWatcher]::WaitForSingleObject($hMutex, 5000)
|
|
266
|
+
if ($waitResult -eq [TabWatcher]::WAIT_FAILED) {
|
|
267
|
+
Write-Log "failed to acquire mutex, exiting"
|
|
268
|
+
[TabWatcher]::CloseHandle($hMutex)
|
|
269
|
+
exit 1
|
|
270
|
+
}
|
|
271
|
+
Write-Log "acquired mutex from old watcher"
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
$exitCode = 0
|
|
275
|
+
$hIn = [IntPtr]::Zero
|
|
276
|
+
$hOut = [IntPtr]::Zero
|
|
277
|
+
$hProcess = [IntPtr]::Zero
|
|
278
|
+
try {
|
|
279
|
+
$consoleHandles = Attach-TargetConsole
|
|
280
|
+
if ($consoleHandles) {
|
|
281
|
+
$hIn = $consoleHandles.InputHandle
|
|
282
|
+
$hOut = $consoleHandles.OutputHandle
|
|
283
|
+
}
|
|
284
|
+
$setColor = "$ESC]4;264;$color$ST"
|
|
285
|
+
$setViaAttached = Write-OscToAttachedConsole $hOut $setColor "set tab color=$color"
|
|
286
|
+
$setViaStreams = Write-OscToInheritedStreams $setColor "set tab color=$color"
|
|
287
|
+
Write-Log "set color summary attached=$setViaAttached streams=$setViaStreams"
|
|
288
|
+
|
|
289
|
+
$hProcess = [TabWatcher]::OpenProcess([TabWatcher]::SYNCHRONIZE, $false, [uint32]$TargetPid)
|
|
290
|
+
if ($hProcess -eq [IntPtr]::Zero) {
|
|
291
|
+
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
|
292
|
+
throw "OpenProcess failed err=$err"
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
$baselineForeground = [TabWatcher]::GetForegroundWindow()
|
|
296
|
+
$baselineInputTick = [TabWatcher]::GetLastInputTick()
|
|
297
|
+
$baselineConsoleInputCount = Get-ConsoleInputEventCount $hIn
|
|
298
|
+
$consoleInputArmed = ($null -eq $baselineConsoleInputCount) -or ($baselineConsoleInputCount -eq 0)
|
|
299
|
+
$sawTargetConsoleInput = $false
|
|
300
|
+
$lastDrainCount = $baselineConsoleInputCount
|
|
301
|
+
Write-Log "waiting for target console input + foreground return baselineForeground=$baselineForeground baselineInputTick=$baselineInputTick baselineConsoleInputCount=$baselineConsoleInputCount armed=$consoleInputArmed"
|
|
302
|
+
if ($TerminalHwnd -le 0) {
|
|
303
|
+
Write-Log "no terminal hwnd provided; reset will only stop when target process exits"
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
$waitHandles = if ($hIn -ne [IntPtr]::Zero) { @($hProcess, $hIn) } else { @($hProcess) }
|
|
307
|
+
|
|
308
|
+
while ($true) {
|
|
309
|
+
$result = if ($waitHandles.Count -gt 1) {
|
|
310
|
+
[TabWatcher]::WaitForMultipleObjects([uint32]$waitHandles.Count, $waitHandles, $false, 150)
|
|
311
|
+
} else {
|
|
312
|
+
[TabWatcher]::WaitForSingleObject($hProcess, 150)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if ($result -eq [TabWatcher]::WAIT_OBJECT_0) {
|
|
316
|
+
Write-Log "target process exited"
|
|
317
|
+
break
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if ($waitHandles.Count -gt 1 -and $result -eq ([TabWatcher]::WAIT_OBJECT_0 + 1)) {
|
|
321
|
+
if (-not $consoleInputArmed) {
|
|
322
|
+
$currentConsoleInputCount = Get-ConsoleInputEventCount $hIn
|
|
323
|
+
if ($currentConsoleInputCount -eq 0) {
|
|
324
|
+
$consoleInputArmed = $true
|
|
325
|
+
Write-Log "target console input armed after drain"
|
|
326
|
+
} else {
|
|
327
|
+
if ($currentConsoleInputCount -ne $lastDrainCount) {
|
|
328
|
+
Write-Log "target console still draining baselineInputCount=$baselineConsoleInputCount currentInputCount=$currentConsoleInputCount"
|
|
329
|
+
$lastDrainCount = $currentConsoleInputCount
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
} else {
|
|
333
|
+
$sawTargetConsoleInput = $true
|
|
334
|
+
Write-Log "target console input signaled"
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
$isExpectedWaitResult =
|
|
339
|
+
($result -eq [TabWatcher]::WAIT_TIMEOUT) -or
|
|
340
|
+
($waitHandles.Count -gt 1 -and $result -eq ([TabWatcher]::WAIT_OBJECT_0 + 1))
|
|
341
|
+
if (-not $isExpectedWaitResult) {
|
|
342
|
+
$wmErr = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
|
343
|
+
Write-Log "wait returned unexpected result=$result err=$wmErr"
|
|
344
|
+
break
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (-not $consoleInputArmed -and $hIn -ne [IntPtr]::Zero) {
|
|
348
|
+
$currentConsoleInputCount = Get-ConsoleInputEventCount $hIn
|
|
349
|
+
if ($currentConsoleInputCount -eq 0) {
|
|
350
|
+
$consoleInputArmed = $true
|
|
351
|
+
Write-Log "target console input armed after timeout drain"
|
|
352
|
+
} elseif ($currentConsoleInputCount -ne $lastDrainCount) {
|
|
353
|
+
Write-Log "target console still draining baselineInputCount=$baselineConsoleInputCount currentInputCount=$currentConsoleInputCount"
|
|
354
|
+
$lastDrainCount = $currentConsoleInputCount
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
$currentForeground = [TabWatcher]::GetForegroundWindow()
|
|
359
|
+
$currentInputTick = [TabWatcher]::GetLastInputTick()
|
|
360
|
+
if ($TerminalHwnd -gt 0 -and $currentForeground -eq [IntPtr]$TerminalHwnd -and $currentInputTick -ne 0 -and $currentInputTick -ne $baselineInputTick -and $sawTargetConsoleInput) {
|
|
361
|
+
Write-Log "foreground returned with target console input foreground=$currentForeground inputTick=$currentInputTick"
|
|
362
|
+
[TabWatcher]::SleepMs(100)
|
|
363
|
+
$resetColor = "$ESC]104;264$ST"
|
|
364
|
+
$resetViaStreams = Write-OscToInheritedStreams $resetColor "reset tab color"
|
|
365
|
+
$resetViaAttached = Write-OscToAttachedConsole $hOut $resetColor "reset tab color"
|
|
366
|
+
Write-Log "reset color summary attached=$resetViaAttached streams=$resetViaStreams"
|
|
367
|
+
break
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
Write-Log "error: $_"
|
|
374
|
+
$exitCode = 1
|
|
375
|
+
}
|
|
376
|
+
finally {
|
|
377
|
+
if ($hProcess -ne [IntPtr]::Zero) {
|
|
378
|
+
[TabWatcher]::CloseHandle($hProcess) | Out-Null
|
|
379
|
+
}
|
|
380
|
+
if ($hOut -ne [IntPtr]::Zero) {
|
|
381
|
+
[TabWatcher]::CloseHandle($hOut) | Out-Null
|
|
382
|
+
}
|
|
383
|
+
if ($hIn -ne [IntPtr]::Zero) {
|
|
384
|
+
[TabWatcher]::CloseHandle($hIn) | Out-Null
|
|
385
|
+
}
|
|
386
|
+
[TabWatcher]::ReleaseMutex($hMutex) | Out-Null
|
|
387
|
+
[TabWatcher]::CloseHandle($hMutex) | Out-Null
|
|
388
|
+
Write-Log "exiting code=$exitCode"
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
exit $exitCode
|