Простой сервис родительского контроля (simple service parental control)

По просьбе трудящихся наваял небольшой сервис, выполняет выход из сеанса пользователя (log off) или его отключение (disconnect) в определенное время с временной блокировкой учетной записи, если необходимо. Периодичность проверки попадания в график 1 минута.

Действия по блокировке или отключению учетки применяются только если сессия активна. Учетной запись разблокируется при условиях: учетная запись присутствует в графике, она заблокирована, и в этот момент не попадает в график по отключению. (раз в минуту)

Версия 1.3 — добавлена возможность отключения записи графика. У отключенных текст подкрашен серым.

UPD 09.10.2020 Версия 1.4 — добавлена группировка записей графика и множественное выделение и выключение/включение записей.

chado.zip

chado

Необходимо настроить график отключений, установить и запустить сервис. Данные графика сохраняются в 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());
		}
	}

Get list of AD groups a user is a member of

Нужно получить список групп пользователя домена. Самое простое
net user userxxx /domain
но наименование группы обрезается до 21 символа, печалька Воспользуется повершелом
Для текущего пользователя:
(New-Object System.DirectoryServices.DirectorySearcher("(&(objectCategory=User)(samAccountName=$($env:username)))")).FindOne().GetDirectoryEntry().memberOf
Для указанного:
$env:username="userxxx";(New-Object System.DirectoryServices.DirectorySearcher("(&(objectCategory=User)(samAccountName=$($env:username)))")).FindOne().GetDirectoryEntry().memberOf

Portproxy windows

Из серии, век живи, век учись. Форвардинг пакетов штатными средствами виндовс.
netsh interface portproxy add v4tov4 listenport=2222 listenaddress=192.168.0.101 connectport=2222 connectaddress=192.168.11.13
#ну и посмотреть, удалить все правила, или выборочно
netsh interface portproxy show all
netsh interface portproxy reset
netsh interface portproxy delete v4tov4 listenport=2222 listenaddress=192.168.0.101
Для чего понадобилось, в моем случае, с помощью «виртуального сервера» роутера (тплинк), нужно было пробросить порт, но сеть не директ коннект (маршруты прописаны, пинга ходит), соответственно пришлось перенаправлять дважды, от тплинка до маршрутизатора этой сети и с него уже дальше.

Служба «Служба профилей пользователей» препятствует входу в систему. Невозможно загрузить профиль пользователя.

Усложнение уровня, имеем удаленного пользователя, у пользователя одна учетная запись, попасть на рабочий стол он не может получает сообщение
Служба «Служба профилей пользователей» препятствует входу в систему. Невозможно загрузить профиль пользователя.
01_sm[1] Перезагрузка, жмет F8 (часто) 02_sm[1] И «Последняя удачная конфигурация» не помогла, совсем плохо.
  1. Опять Ф8
  2. заходим в безопасный режим
  3. создаем пользователя с правами администратора
  4. перезагрузка
  5. заходим в систему этим пользователем
  6. скачиваем и запускаем TeamViewer
  7. заходим удаленно и проделываем операцию по восстановления профиля HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList
    • Если есть папки вида S-1-5-21-*… и S-1-5-21-*….bak Нужную папку S-1-5-21-*… определяем по имени параметра «ProfileImagePath», который указывает путь к профилю. Правильная папка с именем вида S-1-5-21-*….bak Не правильная папка с именем вида S-1-5-21-*…. Переименуйте папку с именем вида S-1-5-21-*… в S-1-5-21-*….bk Переименуйте папку с именем вида S-1-5-21-*….bak в S-1-5-21-*…. удалив в имени .bak
    • Если папка с именем вида S-1-5-21-*… одна или нет папки с именем вида S-1-5-21-*….bak В таком случаи измените значения на «0» в имени параметра «RefCount» и «State», которые находятся в папке S-1-5-21-*…
    • И еще вариант, в независимости от того, была одна папка или мы восстановили данные из «.bak» значения параметров «RefCount» и «State» сбрасываем в 0
  8. перезагрузка
  9. клиент заходит в систему старым пользователем

Windows 8.1 + RDP, пропадает звук после переподключения

Замечена особенность передачи звука через RDP на Windows 8.1, если отключился от сервера (сессия в статусе «Отключен»), а затем снова подключился, то звука нет. Если завершить сеанс и заново подключится, то звук начинает работать. Лечится перезапуском службы «Windows Audio», иногда, помогает не с первого раза.