[Информационная безопасность, Программирование, .NET, C#, Разработка под Windows] Как следить (наблюдать) за компьютером. Часть 1 — делаем скриншоты пользователей
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Делаем скриншоты пользователей. Обсудим реализацию на языке программирования C#.Описываемый в данной статье способ является простым, никакого лишнего функционала. Вы можете воспользоваться готовой разработкой или изменить исходный код как захотите. В конце статьи будет ссылка на GitHub.
Необходимый функционал:
- Программа должна делать скриншоты
- Программы не должно быть видно на панели задач
- Возможность задавать интервал в секундах между выполнением скриншота
- Возможность задавать путь к директории хранилища скриншотов
- Возможность задавать максимальный размер хранилища скриншотов
- Очистка самых старых файлов из хранилища скриншотов при достижении максимума в хранилище
- Логирование работы программы
Алгоритм работы программы:
Код работы метода Main программы:
static void Main(string[] args)
{
Log.Instance.Info($"started");
// Скрыть окно программы
var handle = GetConsoleWindow();
ShowWindow(handle, SW_HIDE);
// Чтение конфигурации
ReadSettings();
// Запуск бесконечной работы скриншотов
while (true)
{
// Проверить хранилище
CheckStorage();
// Выполнить скриншот
DoScreen();
// Подождать интервал времени
Thread.Sleep(_interval * 1000);
}
}
Далее необходимо разработать следующие методы:ReadSettings - Чтение конфигурации
CheckStorage - Проверить хранилище
DoScreen - Выполнить скриншотReadSettings (чтение конфигурации)Для создания файла конфигурации необходимо в Visual Studio открыть свойства проекта и перейти в меню Параметры. Здесь необходимо прописать какие переменные будут вынесены в файл конфигурации и задать их типы и значения.
interval - Как часто делать скриншот, в секундах
limit - Размер хранилища скриншотов, в MB
path - Путь к хранилищу скриншотов, пример C:\temp
Для удобства создадим свойства для доступа к настройкам.
/// <summary>
/// Как часто делать скриншот, в секундах
/// </summary>
static int _interval { get; set; }
/// <summary>
/// Размер хранилища скриншотов, в MB
/// </summary>
static int _limit { get; set; }
/// <summary>
/// Путь к хранилищу скриншотов, пример C:\temp
/// </summary>
static string _path { get; set; }
Затем прочитаем настройки программы из файла конфигурации Screenshoter.exe.config который лежит около исполняемого файла приложения Screenshoter.exe. Запишем прочитанные настройки в выше созданные поля.
/// <summary>
/// Чтение настроек из файла конфигурации
/// </summary>
static void ReadSettings()
{
_interval = 10;
if (Properties.Settings.Default.interval > 0) _interval = Properties.Settings.Default.interval;
Log.Instance.Info($"set interval = {_interval} sec");
_limit = 20;
if (Properties.Settings.Default.limit > 0) _limit = Properties.Settings.Default.limit;
Log.Instance.Info($"set storage = {_limit} Mb");
_path = @"C:\temp";
if (!string.IsNullOrEmpty(Properties.Settings.Default.path)) _path = Properties.Settings.Default.path;
Log.Instance.Info($"set path = {_path}");
}
CheckStorage (Проверка хранилища)Алгоритм проверки хранилища: если хранилище заполнено, то необходимо рассчитать насколько хранилище заполнено больше чем установленный лимит в настройках и затем соответственно очистить хранилище.
/// <summary>
/// Проверка доступного места в хранилище
/// </summary>
static void CheckStorage()
{
var currentSize = StorageSize();
if (currentSize > _limit)
{
// Сколько нужно очистить MB
var totalToTrash = currentSize - _limit;
// Очистить необходимое кол-во KB
StorageClear(totalToTrash * 1024);
}
}
Дополнительно приведу методы StorageSize и StorageClear.
StorageSize принимает аргумент насколько нужно очистить в KB. Почему в KB (килобайтах), а не в MB (мегабайтах) ? 1 скриншот занимает в хранилище размер меньший чем 1 Мегабайт, а значит корректнее удалять в Килобайтах чтобы не удалять за 1 раз например 5 скриншотов чтобы после этого в хранилище был записан всего 1 скриншот.
Метод StorageSize подсчитывает размер всех файлов в директории хранилища, без учета вложенных директорий (не сложно добавить если нужно).
/// <summary>
/// Заполненность хранилища, в MB
/// </summary>
/// <returns></returns>
static long StorageSize()
{
long i = 0;
try
{
DirectoryInfo directory = new DirectoryInfo(_path);
FileInfo[] files = directory.GetFiles();
foreach (FileInfo file in files)
{
i += file.Length;
}
}
catch (Exception ex)
{
Log.Instance.Error(3, ex.Message);
return _limit;
}
return i /= (1024 * 1024);
}
StorageClear принимает аргумент сколько нужно в хранилище очистить Килобайт. Метод считывает список файлов в хранилище, отсортировывает полученную коллекцию по времени создания файла, удаляет файлы начиная с самых старых пока размер удаленных файлов не будет больше чем нужно удалить.
/// <summary>
/// Очистка хранилища
/// </summary>
/// <param name="sizeKb"></param>
static void StorageClear(long sizeKb)
{
try
{
Log.Instance.Info($"clear = {sizeKb} Kb");
DirectoryInfo directory = new DirectoryInfo(_path);
FileInfo[] files = directory.GetFiles().OrderBy(f => f.CreationTime).ToArray();
foreach (FileInfo file in files)
{
var size = file.Length / 1024;
File.Delete(file.FullName);
sizeKb -= size;
if (sizeKb <= 0) break;
}
}
catch (Exception ex)
{
Log.Instance.Error(2, ex.Message);
}
}
DoScreen (Создание скриншота)Данный метод пытается создать скриншот в хранилище скриншотов. Формат создаемых файлов - PNG. В файл попадает весь экран основного монитора пользователя. Если создать файл не удалось, то отправка в класс Log сообщения об ошибке.
/// <summary>
/// Создание скриншота
/// </summary>
static void DoScreen()
{
try
{
Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(printscreen as Image);
graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);
printscreen.Save(Path.Combine(_path, GetFileName()), System.Drawing.Imaging.ImageFormat.Png);
}
catch (Exception ex)
{
Log.Instance.Error(1, ex.Message);
}
}
/// <summary>
/// Имя файла создаваемого скриншота
/// </summary>
/// <returns></returns>
static string GetFileName()
{
var time = DateTime.Now;
return $"{time.ToString("yyyy_MM_dd__HH_mm_ss")}.png";
}
Чтобы программы не было видно на панели задач необходимо окно программы спрятать. Вызов данного функционала происходит из метода Main.
#region DllImport
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
const int SW_SHOW = 5;
#endregion
Логирование действий программы состоит в виде статического класса Log сделанного согласно паттерну Singleton (одиночка).
public sealed class Log
{
private static volatile Log _instance;
private static readonly object SyncRoot = new object();
private readonly object _logLocker = new object();
private Log()
{
CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;
LogDirectory = Path.Combine(CurrentDirectory, "log");
}
public string CurrentDirectory { get; set; }
public string LogDirectory { get; set; }
public static Log Instance
{
get
{
if (_instance == null)
{
lock (SyncRoot)
{
if (_instance == null) _instance = new Log();
}
}
return _instance;
}
}
public void Error(int errorNumber, string errorText)
{
Add($"Ошибка {(errorNumber.ToString()).PadLeft(4, '0')}: {errorText}", "[ERROR]");
}
public void Info(string log)
{
Add(log, "[INFO]");
}
private void Add(string log, string logLevel)
{
lock (_logLocker)
{
try
{
if (!Directory.Exists(LogDirectory))
{
// Создание директории log в случае отсутствия
Directory.CreateDirectory(LogDirectory);
}
// Запись в лог файл вместе с датой и уровнем лога.
string newFileName = Path.Combine(LogDirectory, String.Format("{0}.txt", DateTime.Now.ToString("yyyyMMdd")));
File.AppendAllText(newFileName, $"{DateTime.Now} {logLevel} {log} \r\n", Encoding.UTF8);
}
catch { }
}
}
}
Код программы здесь
===========
Источник:
habr.com
===========
Похожие новости:
- [Мессенджеры, Open source, Системное администрирование, PHP, Программирование] Рефакторинг пет проекта: докеризация, метрики, тесты
- [Программирование, C++, Тестирование веб-сервисов, Конференции] Как достичь полной автоматизации в Automotive тестировании и особенности Move конструктора: узнаем 25 февраля
- [Assembler, Программирование микроконтроллеров] Assembler Editor Plus: Установка
- [Программирование, C++, Работа с 3D-графикой, Разработка игр, CGI (графика)] Vulkan. Руководство разработчика. Swap chain (перевод)
- [Информационная безопасность, Законодательство в IT, Удалённая работа] ФСТЭК разработала требования безопасности к оборудованию для удаленной работы
- [Высокая производительность, Ненормальное программирование, C] Быстрое сравнение double
- [Системное администрирование, Системное программирование, DevOps] Первый взгляд на Tekton Pipelines (перевод)
- [Программирование, Математика, Matlab] Реализация моделей динамических систем средствами контроллера
- [Информационная безопасность, WordPress, Open source, Администрирование доменных имен] Новый плагин CrowdSec для защиты сайтов на WordPress
- [Информационная безопасность, Сетевые технологии, IT-компании] От локального ПО до всероссийских инсталляций: как изменился ИКС за 17 лет
Теги для поиска: #_informatsionnaja_bezopasnost (Информационная безопасность), #_programmirovanie (Программирование), #_.net, #_c#, #_razrabotka_pod_windows (Разработка под Windows), #_slezhka_za_polzovateljami (слежка за пользователями), #_.net, #_skrinshot (скриншот), #_skrinshoter (скриншотер), #_razrabotka_prilozhenij (разработка приложений), #_programmirovanie (программирование), #_informatsionnaja_bezopasnost (информационная безопасность), #_informatsionnaja_bezopasnost (
Информационная безопасность
), #_programmirovanie (
Программирование
), #_.net, #_c#, #_razrabotka_pod_windows (
Разработка под Windows
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 09:16
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Делаем скриншоты пользователей. Обсудим реализацию на языке программирования C#.Описываемый в данной статье способ является простым, никакого лишнего функционала. Вы можете воспользоваться готовой разработкой или изменить исходный код как захотите. В конце статьи будет ссылка на GitHub. Необходимый функционал:
Код работы метода Main программы: static void Main(string[] args)
{ Log.Instance.Info($"started"); // Скрыть окно программы var handle = GetConsoleWindow(); ShowWindow(handle, SW_HIDE); // Чтение конфигурации ReadSettings(); // Запуск бесконечной работы скриншотов while (true) { // Проверить хранилище CheckStorage(); // Выполнить скриншот DoScreen(); // Подождать интервал времени Thread.Sleep(_interval * 1000); } } CheckStorage - Проверить хранилище DoScreen - Выполнить скриншотReadSettings (чтение конфигурации)Для создания файла конфигурации необходимо в Visual Studio открыть свойства проекта и перейти в меню Параметры. Здесь необходимо прописать какие переменные будут вынесены в файл конфигурации и задать их типы и значения. interval - Как часто делать скриншот, в секундах limit - Размер хранилища скриншотов, в MB path - Путь к хранилищу скриншотов, пример C:\temp Для удобства создадим свойства для доступа к настройкам. /// <summary>
/// Как часто делать скриншот, в секундах /// </summary> static int _interval { get; set; } /// <summary> /// Размер хранилища скриншотов, в MB /// </summary> static int _limit { get; set; } /// <summary> /// Путь к хранилищу скриншотов, пример C:\temp /// </summary> static string _path { get; set; } /// <summary>
/// Чтение настроек из файла конфигурации /// </summary> static void ReadSettings() { _interval = 10; if (Properties.Settings.Default.interval > 0) _interval = Properties.Settings.Default.interval; Log.Instance.Info($"set interval = {_interval} sec"); _limit = 20; if (Properties.Settings.Default.limit > 0) _limit = Properties.Settings.Default.limit; Log.Instance.Info($"set storage = {_limit} Mb"); _path = @"C:\temp"; if (!string.IsNullOrEmpty(Properties.Settings.Default.path)) _path = Properties.Settings.Default.path; Log.Instance.Info($"set path = {_path}"); } /// <summary>
/// Проверка доступного места в хранилище /// </summary> static void CheckStorage() { var currentSize = StorageSize(); if (currentSize > _limit) { // Сколько нужно очистить MB var totalToTrash = currentSize - _limit; // Очистить необходимое кол-во KB StorageClear(totalToTrash * 1024); } } StorageSize принимает аргумент насколько нужно очистить в KB. Почему в KB (килобайтах), а не в MB (мегабайтах) ? 1 скриншот занимает в хранилище размер меньший чем 1 Мегабайт, а значит корректнее удалять в Килобайтах чтобы не удалять за 1 раз например 5 скриншотов чтобы после этого в хранилище был записан всего 1 скриншот. Метод StorageSize подсчитывает размер всех файлов в директории хранилища, без учета вложенных директорий (не сложно добавить если нужно). /// <summary>
/// Заполненность хранилища, в MB /// </summary> /// <returns></returns> static long StorageSize() { long i = 0; try { DirectoryInfo directory = new DirectoryInfo(_path); FileInfo[] files = directory.GetFiles(); foreach (FileInfo file in files) { i += file.Length; } } catch (Exception ex) { Log.Instance.Error(3, ex.Message); return _limit; } return i /= (1024 * 1024); } /// <summary>
/// Очистка хранилища /// </summary> /// <param name="sizeKb"></param> static void StorageClear(long sizeKb) { try { Log.Instance.Info($"clear = {sizeKb} Kb"); DirectoryInfo directory = new DirectoryInfo(_path); FileInfo[] files = directory.GetFiles().OrderBy(f => f.CreationTime).ToArray(); foreach (FileInfo file in files) { var size = file.Length / 1024; File.Delete(file.FullName); sizeKb -= size; if (sizeKb <= 0) break; } } catch (Exception ex) { Log.Instance.Error(2, ex.Message); } } /// <summary>
/// Создание скриншота /// </summary> static void DoScreen() { try { Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); Graphics graphics = Graphics.FromImage(printscreen as Image); graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size); printscreen.Save(Path.Combine(_path, GetFileName()), System.Drawing.Imaging.ImageFormat.Png); } catch (Exception ex) { Log.Instance.Error(1, ex.Message); } } /// <summary> /// Имя файла создаваемого скриншота /// </summary> /// <returns></returns> static string GetFileName() { var time = DateTime.Now; return $"{time.ToString("yyyy_MM_dd__HH_mm_ss")}.png"; } #region DllImport
[DllImport("kernel32.dll")] static extern IntPtr GetConsoleWindow(); [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); const int SW_HIDE = 0; const int SW_SHOW = 5; #endregion public sealed class Log
{ private static volatile Log _instance; private static readonly object SyncRoot = new object(); private readonly object _logLocker = new object(); private Log() { CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory; LogDirectory = Path.Combine(CurrentDirectory, "log"); } public string CurrentDirectory { get; set; } public string LogDirectory { get; set; } public static Log Instance { get { if (_instance == null) { lock (SyncRoot) { if (_instance == null) _instance = new Log(); } } return _instance; } } public void Error(int errorNumber, string errorText) { Add($"Ошибка {(errorNumber.ToString()).PadLeft(4, '0')}: {errorText}", "[ERROR]"); } public void Info(string log) { Add(log, "[INFO]"); } private void Add(string log, string logLevel) { lock (_logLocker) { try { if (!Directory.Exists(LogDirectory)) { // Создание директории log в случае отсутствия Directory.CreateDirectory(LogDirectory); } // Запись в лог файл вместе с датой и уровнем лога. string newFileName = Path.Combine(LogDirectory, String.Format("{0}.txt", DateTime.Now.ToString("yyyyMMdd"))); File.AppendAllText(newFileName, $"{DateTime.Now} {logLevel} {log} \r\n", Encoding.UTF8); } catch { } } } } Код программы здесь =========== Источник: habr.com =========== Похожие новости:
Информационная безопасность ), #_programmirovanie ( Программирование ), #_.net, #_c#, #_razrabotka_pod_windows ( Разработка под Windows ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 09:16
Часовой пояс: UTC + 5