По просьбе трудящихся наваял небольшой сервис, выполняет выход из сеанса пользователя (log off) или его отключение (disconnect) в определенное время с временной блокировкой учетной записи, если необходимо. Периодичность проверки попадания в график 1 минута.
Действия по блокировке или отключению учетки применяются только если сессия активна. Учетной запись разблокируется при условиях: учетная запись присутствует в графике, она заблокирована, и в этот момент не попадает в график по отключению. (раз в минуту)
Версия 1.3 — добавлена возможность отключения записи графика. У отключенных текст подкрашен серым.
UPD 09.10.2020 Версия 1.4 — добавлена группировка записей графика и множественное выделение и выключение/включение записей.
chado.zipНеобходимо настроить график отключений, установить и запустить сервис. Данные графика сохраняются в SQLite. После изменения графика необходим перезапуск сервиса, так как сервисом данные считываются только один раз, при запуске. Сервис и GUI-приложение один и тот же бинарный файл, при установке сервиса приложение не копируется, сервис запускается с места нахождения chado.exe
Для disconnect и log off используются WTSDisconnectSession и WTSLogoffSession
for (auto& user : theApp.DBUsers) { if (user.userName.Compare(userName) == 0 && user.dayOfWeek == dayOfWeek && curentSeconds >= user.allowedFrom && curentSeconds <= user.allowedTo ) { if (user.disconnect == 0) { WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE, pInfos[i].SessionId, FALSE); theApp.log.WriteString((date.Format(L"%Y-%m-%d %T") + L" disconnect: " + user.userName + L"\r\n").GetString()); } else { WTSLogoffSession(WTS_CURRENT_SERVER_HANDLE, pInfos[i].SessionId, FALSE); theApp.log.WriteString((date.Format(L"%Y-%m-%d %T") + L" logoff: " + user.userName + L"\r\n").GetString()); } if (user.lock == 0) { theApp.unlockAccount(user.userName.GetString(), 1); } } }
Для блокировки/разблокировки учетной записи: NetUserGetInfo и NetUserSetInfo
if (!lock && (ui4->usri4_flags & UF_ACCOUNTDISABLE) == UF_ACCOUNTDISABLE) { ui.usri1008_flags = ui4->usri4_flags ^ UF_ACCOUNTDISABLE; need = 2; } if (lock && (ui4->usri4_flags & UF_ACCOUNTDISABLE) != UF_ACCOUNTDISABLE) { ui.usri1008_flags = ui4->usri4_flags | UF_ACCOUNTDISABLE; need = 1; } // Call the NetUserSetInfo function // to disable the account, specifying level 1008. if (need) { nStatus = NetUserSetInfo(NULL, username, 1008, (LPBYTE)&ui, NULL); // Display the result of the call. if (nStatus == NERR_Success) { #ifdef _DEBUG theApp.log.WriteString((date.Format(L"%Y-%m-%d %T") + (need == 1 ? L" lock " : L" unlock ") + L"account: " + username + L"\r\n").GetString()); #endif } else { theApp.log.WriteString((date.Format(L"%Y-%m-%d %T") + L" error lock/unlock account: " + username + L"\r\n").GetString()); } }