Как стать автором
Обновить

Комментарии 40

А я думал таким статьям место на какерских форумах а не в приличном сообществе.
Ждём пост как скачать exe и запустить его.

Если рассматривать как самописное бесплатное средство, которое потом можно дальше развивать, прикручивать опции, то что сказать, это хороший проект. Можно в будущем экономить на средствах мониторинга пользователей типа Стахановец/Стафкоп/


Если рассматривать как реально работающий сервис в локальной сети, то это опасная дорога. С грамотным юристом могут штраф впаять если узнают. Такие средства мониторинга не должны быть скрытыми, пользователь должен быть уведомлен об этом, тем или другим способом.

Я не предлагаю пользоваться разработкой в незаконных целях (картинку выбрал несоответсвующую этому высказыванию).
В работе использую создание скриншотов чтобы следить за рдп сессиями на серверах где автоматически работает мое ПО и мне необходимо контролировать процесс работы.

Может открою Америку не знаю. Не думали сделать привязку выполнения скриншота конкретному событию в системе или к приложению? Так место на диске не будет забиваться не нужными скриншотами.

Есть события которые сложно отловить. Но есть система которая анализирует скриншоты и понимает когда что-то идет не так и дает об этом знать.
Спасибо за Вашу статью, очень интересно было ознакомиться с применяемыми принципами.
а зачем тогда это?
Программы не должно быть видно на панели задач
Окно прячется главным образом чтобы не было частью скриншота.
В работе использую создание скриншотов чтобы следить за рдп сессиями на серверах где автоматически работает мое ПО и мне необходимо контролировать процесс работы.
Скажите, а чем вас не устраивает оперативный контроль с помощью стандартного механизма RDP session shadowing, безо всяких скриншотов?
Автоматический контроль делает все без меня, я только в телеграм поглядываю когда бот присылает сообщение что некоторый скрин не соответствует.

Если говорить о подглядывании за юзерами со стороны рабодателя, то работодателю не всегда оперативно нужно смотреть, а «по истории».

А как бот догадается, что скрин не соответствует? Это же самое интересное. Спрятать окно программы и скопировать экран в файл — у некоторых это 5 строчек занимает :D

Проверка по пикселям.
Пример: известно в задаче точно, что пиксель с координатами 100, 200 должен быть в GRB 255, 255, 255. И известно, что если там другой цвет, то это является ошибкой.

При такой проверке важно чтобы разрешение экрана там где берется скриншот не изменялось. Иначе пиксель в другом месте будет.
Странная методика тестирования UI :)
То ли у вас на любом экране в определенном месте должен быть этот волшебный пиксель, то ли приложение состоит из одной формы. Для своего приложения можно придумать и более изячный способ логирования, а следить за чужим по 1 пикселю как-то самонадеянно.
Пример: у меня в системе рдп сессия устанавливается не в момент когда юзер подключается, а заранее. При запуске программы в рдп сессии может произойти сбой, а я не хочу чтобы пользователь увидел засбоившую программу при запуске.
Но зачем? В чем практическая ценность? Контролировать действия подрядчиков? Сорри, не особо тянет. Лучше уже тогда настроить логирование и форвардинг в какую-нибудь ёлку, или, если есть потребность и бюджеты позволяют — поднять настоящий PAM, который сам будет всё записывать, управлять паролями и рвать сессии, если ему что-то не понравится.
Кто знает есть реализация на питоне, или PHP?
Спасибо!
НЛО прилетело и опубликовало эту надпись здесь
Мне нравится Ваша идея )
НЛО прилетело и опубликовало эту надпись здесь
Наверное, перехват WinApi функций, отвечающих за снятие скриншота (BitBlt или что там). Не задумывался о таком никогда, но вообще, идея хорошая.
Таки ромб в алгоритмах — это исполнение условия «да/нет», но никак не круговое замыкание.
Спасибо, поправил )
Когда мне нужно было решить примерно такую же задачу — оказалось достаточно PowerShell-скрипта на 5 строчек.
Сделайте статью, будет бомба!
Заголовок уже есть: «достаточно PowerShell-скрипта на 5 строчек»
$Path = "C:\Temp\Screenshot\"
Add-Type -AssemblyName System.Windows.Forms
$ScreenBounds = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
$Image = New-Object System.Drawing.Bitmap($screenBounds.Width, $ScreenBounds.Height)
$CopyScreen = [System.Drawing.Graphics]::FromImage($Image)
$Point = New-Object System.Drawing.Point(0, 0)
$CopyScreen.CopyFromScreen($Point,[Drawing.Point]::Empty, $Image.Size);
$СursorBounds = New-Object System.Drawing.Rectangle([System.Windows.Forms.Cursor]::Position, [System.Windows.Forms.Cursor]::Current.Size)
[System.Windows.Forms.Cursors]::Default.Draw($CopyScreen, $СursorBounds)
$CopyScreen.Dispose()
if(![System.IO.Directory]::Exists($Path)){ New-Item -ItemType Directory $Path }
$Image.Save( $path+ "$(get-date -f yyyy.MM.dd_h\h_m\m)"+".jpg" )
$Image.Dispose()
Спасибо за код.

В данной разработке сделано следующее:
1. Программа должна делать скриншоты
2. Программы не должно быть видно на панели задач
3. Возможность задавать интервал в секундах между выполнением скриншота
4. Возможность задавать путь к директории хранилища скриншотов
5. Возможность задавать максимальный размер хранилища скриншотов
6. Очистка самых старых файлов из хранилища скриншотов при достижении максимума в хранилище
7. Логирование работы программы

В Вашем коде п.1 выполнен. Сложно сравнивать.
2. Выполнен
3. Планировщик
4. Переменная
5. Файловая система
6. Ещё пара строчек?
7. Еще строчка и в файл или в журнал Windows
Вам ещё надо добавить ресайз скриншотов, чтобы меньше места занимало.
png не должен занимать слишком много места.
Смотря сколько цветов и градиентов на картинке будет.
Зачем каждый раз суммировать размер файлов? не проще ли при записи скриншота брать его размер и делать оценку занятого места? Для валидации можно раз в сутки, месяц прогонять полное суммирование.
Согласен, при большом (нет, БОЛЬШОМ) количестве файлов, будут тормоза.
Разработка рассчитана на относительно небольшое хранилище.
Из плюсов данного решения — если в хранилище попадут другим файлы (а их размер будет другой чем у скриншота), то программа приведет хранилище к необходимому размеру.

А откуда возьмутся другие файлы?

Создалось впечатление, что ПО собрано из кусочков, утянутых их разных мест. Класс логирования использует lock(), но в Main вызываются функции, которые внутри сделаны плохо, считывание/удаление реально будет вешать ПК, я уж не говорю про Thread.Speep() — ну используйте Tasks(), что ли. Пока тянет на поделку для журнала «Молодой Хакер»
P.S. Прячьте портянки кода под спойлеры, пожалуйста. Успехов!
«ПО собрано из кусочков, утянутых их разных мест» — разъясните плиз в каких местах сделано плохо, Вы это упустили.

считывание/удаление реально будет вешать ПК — если хранилище сделать на медленный диск и хранить там данные за год. в этом случае да, будет тормозить.

использование Thread.Sleep — нет тут GUI, тормозить нечему. Как и нет большого количества создаваемых потоков.

«тянет на поделку для журнала «Молодой Хакер»» — спасибо за оценку, пусть так )

«Прячьте портянки кода под спойлеры» — спасибо, учту.
Неважно на каких дисках, сама концепция одного потока на приложение + сервисные функции, наверно, не очень хорошо. И вы в StorageClear() используете лямбды, а отчего в StorageSize() их нет? return new DirectoryInfo(_path).GetFiles("*.*", SearchOption.AllDirectories).Sum(file => file.Length); Я бы в StorageSize() как параметр все же передавал _path, так более универсально
Про лямбды полностью согласен.
А вот передавать в метод _path, который никогда не меняется, не очень )

"StorageSize принимает аргумент насколько нужно очистить в KB." — исправьте опечатку, пожалуйста. Исторически сложилась "традиция" писать код функций, максимально независимый от другого кода. Цель StorageSize () в приложении всего лишь посчитать размер директории, дефолтной функции в CLR нет, напишем свою


/// <summary>
/// Размер директории в байтах
/// </summary>
/// <param name="location">путь к директории</param>
/// <param name="subDir"></param>
/// <returns></returns>
public long  GetDirectorySize(string location, bool subDir = false)
{
    if (subDir)
    {
        return new DirectoryInfo(location).GetFiles("*.*", SearchOption.AllDirectories).Sum(file => file.Length);
    }
    else
    {
         return new DirectoryInfo(location).GetFiles("*.*", SearchOption.TopDirectoryOnly).Sum(file => file.Length);
    }
}

и ее уже будем использовать в StorageSize () с блоками проверки, и, при необходимости, с параметрами не по умолчанию. Замечу, bool subDir = false не просто так, по дефолту не лезть в поддиректории безопасней. Ну и CheckStorage() потенциально дважды сканирует директорию(ии) — плохо :(
С Праздником!

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.