Search
Write a publication
Pull to refresh

Comments 40

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

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


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

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

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

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

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

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

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

При такой проверке важно чтобы разрешение экрана там где берется скриншот не изменялось. Иначе пиксель в другом месте будет.
Странная методика тестирования UI :)
То ли у вас на любом экране в определенном месте должен быть этот волшебный пиксель, то ли приложение состоит из одной формы. Для своего приложения можно придумать и более изячный способ логирования, а следить за чужим по 1 пикселю как-то самонадеянно.
Пример: у меня в системе рдп сессия устанавливается не в момент когда юзер подключается, а заранее. При запуске программы в рдп сессии может произойти сбой, а я не хочу чтобы пользователь увидел засбоившую программу при запуске.
Но зачем? В чем практическая ценность? Контролировать действия подрядчиков? Сорри, не особо тянет. Лучше уже тогда настроить логирование и форвардинг в какую-нибудь ёлку, или, если есть потребность и бюджеты позволяют — поднять настоящий PAM, который сам будет всё записывать, управлять паролями и рвать сессии, если ему что-то не понравится.
Кто знает есть реализация на питоне, или PHP?
UFO landed and left these words here
UFO landed and left these words here
Наверное, перехват 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() потенциально дважды сканирует директорию(ии) — плохо :(
С Праздником!

Sign up to leave a comment.

Articles