Watchdog: schtasks /Run после установки; DEPLOY/README про задачи и UNC; версия 1.3.4

This commit is contained in:
2026-04-29 16:07:35 +10:00
parent 80f57c5351
commit e0b0fa3d7e
4 changed files with 62 additions and 10 deletions
+28
View File
@@ -34,6 +34,34 @@
Лог установки: **`C:\ProgramData\RDP-login-monitor\Logs\deploy.log`**. Лог установки: **`C:\ProgramData\RDP-login-monitor\Logs\deploy.log`**.
## Задачи планировщика после `-InstallTasks`
Параметр **`Login_Monitor.ps1 -InstallTasks`** создаёт две задачи:
| Имя | Назначение |
|-----|------------|
| **`RDP-Login-Monitor`** | Запуск основного монитора при старте ОС (`Register-ScheduledTask`, триггер «При запуске компьютера»). |
| **`RDP-Login-Monitor-Watchdog`** | Тот же файл **`Login_Monitor.ps1`** с аргументом **`-Watchdog`**: короткая проверка «жив ли монитор», при необходимости поднимает процесс. |
Watchdog регистрируется через **`schtasks.exe /Create /SC MINUTE /MO 5`** (а не через CIM-триггеры PowerShell): на части ОС у объектов триггера нет настраиваемых **`RepetitionInterval`** / длительность «раз и навсегда» режется планировщиком — из‑за этого раньше вторая задача могла не создаваться.
Перед созданием выполняется **`schtasks /Delete … /F`** (если задачи ещё не было, сообщение об ошибке подавляется — это нормально).
Сразу после успешного **`/Create`** вызывается **`schtasks /Run`** для watchdog: первый прогон не ждёт следующего 5‑минутного окна расписания.
Проверка:
```powershell
Get-ScheduledTask -TaskName 'RDP-Login-Monitor','RDP-Login-Monitor-Watchdog' -ErrorAction SilentlyContinue
schtasks /Query /TN "RDP-Login-Monitor-Watchdog"
```
Логи: **`...\Logs\login_monitor.log`**, **`...\Logs\watchdog.log`**.
## Запуск Deploy и политики с файловой шары
Если при запуске **`Deploy-LoginMonitor.ps1`** или **`Login_Monitor.ps1`** с UNC по **FQDN** (`\\dc.domain.local\...`) PowerShell сообщает про **цифровую подпись** / политику выполнения, чаще всего помогает путь по **короткому имени** контроллера: **`\\DC01\NETLOGON\...`** (клиент относит UNC к интрасети иначе). Параллельно убедитесь, что команда реально с **`powershell.exe -ExecutionPolicy Bypass -File "..."`**.
## Версии: `version.txt` и `$ScriptVersion` ## Версии: `version.txt` и `$ScriptVersion`
| Что | Роль | | Что | Роль |
+32 -8
View File
@@ -69,7 +69,7 @@ $script:RdpInstanceMutex = $null
# строки ниже, если правки «мелкие» и вы не хотите менять отображаемую версию в логах). # строки ниже, если правки «мелкие» и вы не хотите менять отображаемую версию в логах).
# Рекомендация: при значимых релизах меняйте и $ScriptVersion, и version.txt одинаково; при только # Рекомендация: при значимых релизах меняйте и $ScriptVersion, и version.txt одинаково; при только
# исправлениях на шаре — достаточно поднять patch в version.txt (например 1.3.0.1). # исправлениях на шаре — достаточно поднять patch в version.txt (например 1.3.0.1).
$ScriptVersion = "1.3.0" $ScriptVersion = "1.3.4"
# Логи (все под InstallRoot) # Логи (все под InstallRoot)
$LogFile = Join-Path $script:InstallRoot "Logs\login_monitor.log" $LogFile = Join-Path $script:InstallRoot "Logs\login_monitor.log"
@@ -304,6 +304,7 @@ function Test-RdpMonitorScheduledTaskMatches {
} }
function Register-RdpMonitorScheduledTasksCore { function Register-RdpMonitorScheduledTasksCore {
Write-Log "Register-RdpMonitorScheduledTasksCore: ветка v$ScriptVersion (watchdog через schtasks /SC MINUTE, без CIM RepetitionInterval)."
$psExe = Get-RdpMonitorPowerShellExe $psExe = Get-RdpMonitorPowerShellExe
$canonicalScript = [System.IO.Path]::GetFullPath((Join-Path $script:InstallRoot $script:CanonicalScriptName)) $canonicalScript = [System.IO.Path]::GetFullPath((Join-Path $script:InstallRoot $script:CanonicalScriptName))
if (-not (Test-Path -LiteralPath $canonicalScript)) { if (-not (Test-Path -LiteralPath $canonicalScript)) {
@@ -323,14 +324,37 @@ function Register-RdpMonitorScheduledTasksCore {
-Principal $principal -Settings $settings -Force | Out-Null -Principal $principal -Settings $settings -Force | Out-Null
Write-Log "Задача планировщика: $($script:ScheduledTaskNameMain) (запуск при старте ОС)." Write-Log "Задача планировщика: $($script:ScheduledTaskNameMain) (запуск при старте ОС)."
$actionWd = New-ScheduledTaskAction -Execute $psExe -Argument $argWd # Watchdog только через schtasks. /Delete при отсутствии задачи пишет в stderr — при $ErrorActionPreference Stop раньше рвал скрипт.
$trigger2 = New-ScheduledTaskTrigger -Once -At (Get-Date) $schtasksExe = Join-Path $env:SystemRoot 'System32\schtasks.exe'
$trigger2.RepetitionInterval = New-TimeSpan -Minutes 5 $delErrAction = $ErrorActionPreference
$trigger2.RepetitionDuration = New-TimeSpan -Days 36500 try {
$ErrorActionPreference = 'SilentlyContinue'
& $schtasksExe /Delete /TN $script:ScheduledTaskNameWatchdog /F 2>$null | Out-Null
} finally {
$ErrorActionPreference = $delErrAction
}
Register-ScheduledTask -TaskName $script:ScheduledTaskNameWatchdog -Action $actionWd -Trigger $trigger2 ` $trForSch = "`"$psExe`" $argWd"
-Principal $principal -Settings $settings -Force | Out-Null $schOut = & $schtasksExe /Create /F /RU SYSTEM /RL HIGHEST /SC MINUTE /MO 5 /TN $script:ScheduledTaskNameWatchdog /TR $trForSch 2>&1
Write-Log "Задача планировщика: $($script:ScheduledTaskNameWatchdog) (каждые 5 минут, контроль процесса)." foreach ($line in @($schOut)) {
Write-Log "schtasks watchdog: $line"
}
Write-Log "Задача планировщика: $($script:ScheduledTaskNameWatchdog) (schtasks, каждые 5 минут, контроль процесса)."
# Первый запуск по расписанию может быть почти через 5 мин — сразу ставим одноразовый прогон в очередь.
$runEa = $ErrorActionPreference
try {
$ErrorActionPreference = 'SilentlyContinue'
$runOut = & $schtasksExe /Run /TN $script:ScheduledTaskNameWatchdog 2>&1
foreach ($line in @($runOut)) {
if ($null -ne $line -and "$line".Trim().Length -gt 0) {
Write-Log "schtasks watchdog /Run: $line"
}
}
} finally {
$ErrorActionPreference = $runEa
}
Write-Log "Немедленный прогон watchdog запрошен (schtasks /Run)."
} }
function Ensure-RdpMonitorScheduledTasks { function Ensure-RdpMonitorScheduledTasks {
+1 -1
View File
@@ -4,7 +4,7 @@ PowerShell-набор для мониторинга входов в Windows с
## Актуальная схема (рекомендуется) ## Актуальная схема (рекомендуется)
- **`Login_Monitor.ps1`** — единый монитор: журнал Security (`4624`/`4625`), при необходимости RD Gateway (`302`/`303`), рабочие станции и серверы, ротация логов, heartbeat, отчёты. Устанавливается в **`C:\ProgramData\RDP-login-monitor\`**, задачи **`RDP-Login-Monitor`** и **`RDP-Login-Monitor-Watchdog`** создаются параметром **`-InstallTasks`** (встроено в скрипт). - **`Login_Monitor.ps1`** — единый монитор: журнал Security (`4624`/`4625`), при необходимости RD Gateway (`302`/`303`), рабочие станции и серверы, ротация логов, heartbeat, отчёты. Устанавливается в **`C:\ProgramData\RDP-login-monitor\`**, задачи **`RDP-Login-Monitor`** и **`RDP-Login-Monitor-Watchdog`** создаются параметром **`-InstallTasks`** (watchdog через **`schtasks`**, см. **DEPLOY.md**).
- **`Deploy-LoginMonitor.ps1`** + **`version.txt`** — доставка с файловой шары по версии (домен, GPO «автозагрузка» компьютера). Подробности, структура шары и правила версий: **[DEPLOY.md](DEPLOY.md)**. - **`Deploy-LoginMonitor.ps1`** + **`version.txt`** — доставка с файловой шары по версии (домен, GPO «автозагрузка» компьютера). Подробности, структура шары и правила версий: **[DEPLOY.md](DEPLOY.md)**.
- **`Encrypt-DpapiForRdpMonitor.ps1`** — опционально, для DPAPI-строк токена/chat id на конкретном ПК. - **`Encrypt-DpapiForRdpMonitor.ps1`** — опционально, для DPAPI-строк токена/chat id на конкретном ПК.
+1 -1
View File
@@ -1 +1 @@
1.3.0 1.3.4