У каждого (ну почти каждого) программиста наступает момент, когда он больше не хочет быть наёмным сотрудником, а хочет быть владычицей морскою (со)владельцем пусть маленького, но бизнеса.

Некоторым везёт и из под их пера клавиатуры выходит нечто очень востребованное типа MASQRD. Но прикольных идей и возможностей для их реализации на всех, увы, не хватает.

Поэтому я решил поделиться опытом последних лет и рассказать как можно написать систему учёта рабочего времени. Нет, не полноценную систему контроля сотрудников, которая собирает всю информацию о поведении человека за ПК, а более простую систему, типа описанных в этом обзоре.

На мой взгляд, создать свою систему учета — весьма неплохой бизнес потому что:
  1. создать систему быстро — ориентировочные затраты два-три человеко-месяца;
  2. создать систему просто — как вы дальше увидите, никак высшей математики тут нет, справятся даже начинающие программисты
  3. неплохие рыночные перспективы — потенциальные покупатели знают что такое системы учета рабочего времени, рынок более-менее готов к их широкому распространению. При этом явного лидера на рынке не наблюдается, а функционал и качество существующих систем, на мой взгляд, весьма посредственное. Про продвижение скажу отдельно.

Предвижу следующие возражения...
  • «Да я лучше всю жизнь наёмным программером буду работать, чем сделаю систему, которая людей контролирует». Работайте, лично я не против :) Сам такой. А есть люди, которые очень хотят свой бизнес, пусть маленький, но свой. И учет рабочего времени — не самый плохой рынок.
  • «Контролировать сотрудников непорядочно».Хочу напомнить, что системы учета контролем не занимаются. Они больше дают лишь базовую информацию о поведении сотрудников. Поэтому служба безопасности купить себе что-то более функциональное.
  • «Этих систем на рынке уже так много, что моя не будет продаваться». Народ, вы представляете себе бабку, которая пришла продавать яблоки на рынке, увидела, что там уже 10 бабок стоят, развернулась и пошла домой? Всё может продаваться, даже Офисметрика продаётся, а она уж совсем непонятно из чего и как сделана, интерфейс образца 2000, нормальной поддержки нет. И всё равно кто-то да покупает!
  • «У меня нет опыта продвижения и продажи софта». Угу, а когда-то не было опыта программирования. И ничего, пришел опыт. Про само продвижение напишу кратко чуть ниже, а если будет интерес, то опрошу наших продвижение и сделаю отдельный пост.


Очень кратко (и спорно) о продвижении
  • Делаете сайт. Посмотрите на сайт существующих систем — они все похожи как братья близнецы. Понятно почему — функционала почти нет, остается только рассказывать о пользе для клиента. Разве вы (или недорогой копирайтер) такое же не сможет написать?
  • Поддержку осуществляете по электронной почте и форуме без отрыва от основной работы время.
  • Появятся свободные деньги — вложите их в рекламу (лучше Adwords)


Для начала немного теории


Система учета рабочего времени (далее СУРВ) решает следующие задачи:
  1. определяет в каких сайтах и программах работал пользователь на ПК;
  2. категоризует затраченное на эти активности время как продуктивное или непродуктивное;
  3. предоставляет собранную информацию в виде отчетов сотруднику или его руководителю.

СУРВ состоит из следующих компонентов:
  • Агент — компактный код, устанавливается на каждый компьютер в организации. Занимается сбором информации и отправкой её на сервер. Обычно скрыт для пользователя, но в некоторых случаях выполняет активные действия, такие как запрет на открытие определенный web-сайтов или просьбу указать чем сотрудник занимался во время простоя ПК.
  • Сервер — выполняет две основные функции: получает данные от агентов и формирует web-интерфейс для отображения отчётов. Сервер может быть расположен в облаке или внутри организации. Облачный сервер обслуживает большое количество клиентов.
  • База данных — хранит собранные сервером данные и предоставляет из серверу же для генерации отчетов. Для ускорения формирования отчётов данные периодически пресуммируются. Обычно используются классические SQL RDBMS, но в редких случаях разработчики экспериментируют с NoSQL (обычно MongoDB).
  • Административная консоль

Время сотрудника делится на активное и неактивное. В неактивное время компьютер находится в состоянии простоя, в активном пользователь работает с программой или сайтом.

Активная программа / сайт — означает, что в данный промежуток времени именно это окно программы / браузера было активным на рабочем столе сотрудника и человек в указанный промежуток выполнял какие-либо действия: нажимал на клавиши или двигал мышкой.
То есть мы не считаем рабочим время, когда человек открыл программу и ушёл гулять.

Активность определяется очень просто. После действия пользователя (мышь или клавиатура) в течении ХХ секунд (обычно 60-300), считается что он был активен. если по истечении этого времени других действий не было произведено, то устанавливается состояние неактивности.

Как передавать собранные данных


Агент периодически пересылает на сервер собранную информацию. Для этих целей обычно используется либо REST, либо собственный протокол.

Плюсы REST заключаются в простоте реализации. С помощью того же Swagger можно без лишних усилий и интерфейс спроектировать и скелет кода получить. Учитывая, что с агента на сервер передаются небольшие объемы данных (учет рабочего времени не контроль сотрудников, файлы не перехватывает и видео не передаёт), то JSON для этой цели замечательно подходит. К тому же https как транспорт для REST пройдёт через файрволы и прокси к облачному серверу.

Тем не менее, большинство разработчиков СУРВ предпочитает тратить силы и время изобретая собственные протоколы, прикручивая к ним шифрование и аутентификацию. Ну да ладно, каждому своё.

Какие данные должны передаваться с агента на сервер?


Поскольку вся категоризация рабочего времени и агрегация промежуточных результатов происходят на сервере, то агент достаточно передавать информацию об одном-единственном типе события: с ХХ часов ХХ минут по с ХХ часов ХХ минут для пользователя NNN активной была программа YYY / сайт ZZZ.

И это всё. Нет, правда всё. Остальное считается на сервере. Мне кажется, ровно с этого момента должно придти понимание, что весь этот учет времени — это очень просто. Что если все ваши будущие «конкуренты», перечисленные в обзоре в самом начале статьи (как и три десятка не перечисленных), сделали свои системы «на коленке», то и вы сможете. Что тут нет никаких секретов и тайных практик.

Как работает агент


Переходим к самому интересному. Можно создать мощный сервер с карамельно-ванильным интерфейсом отчётов, но если агент тормозит и вешает компьютеры сотрудников, то продукт пойдёт единственно возможным путём — в топку. (Лично знаю несколько таких систем на данном рынке, которые бодро начали и в корчах померли именно по этой причине).

Итак, агент должен определять четыре вещи:
  1. Системное имя текущего пользователя.
  2. Активен ли сейчас пользователь.
  3. В какой программе работает пользователь (имя запускаемого файла и заголовок). Если это браузер, то...
  4. На каком сайте сейчас пользователь.


Имя пользователя передаётся потому что на одном ПК может работать несколько человек, а нам нужно учитывать активность конкретного сотрудника, а не компьютера.
Делаем так:
#include <windows.h>
#include <Lmcons.h>

char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);


Активность выясняется просто. На мышь и клавиатуру вешается глобальный хук (неплохой пример использования, например, здесь).
После срабатывания хука флаг активности устанавливается в true и запускается таймер на ХХ секунд. По срабатыванию таймера флаг активности сбрасывается в false.

Теперь получаем информацию о заголовке активного окна и exe-файле его породившем.
Заголовок можно получить так (пример полностью здесь):
#include <windows.h>
#include <string>
using std::string;

string GetActiveWindowTitle()
{
 char wnd_title[256];
 HWND hwnd=GetForegroundWindow(); // get handle of currently active window
 GetWindowText(hwnd,wnd_title,sizeof(wnd_title));
 return wnd_title;
}


А наименование процесса получаем так (пример полностью здесь):
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>
 
BOOL GetProcessName( DWORD processID, TCHAR* szProcessName)
{
    BOOL bRC = FALSE;
    // Get a handle to the process. 
    HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
    // Get the process name.
    if (NULL != hProcess )
    {
        HMODULE hMod;
        DWORD cbNeeded;
        if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
             &cbNeeded) )
        {
            GetModuleBaseName( hProcess, hMod, szProcessName, MAX_PATH );
            bRC = TRUE;
        }
    }
    CloseHandle( hProcess ); 
    return bRC;
}


Сложнее всего получить информацию о текущей активной странице в браузере. И вот почему.

Изо все браузеров, только Internet Explorer / Edge имеет API, показывающее информацию о текущем URL. Так что в случае с осликом всё было легко и просто — только функцию вызвать.
Но давно ушли времена, когда IE был главным браузером на ПК, теперь на большинстве компьютеров властвует Google Chrome вместе с Firefox / Opera / много кто ещё. А у них API отсутсвует, вызывать нечего… Как быть?

Самые простые программы обратили свой взор к браузерному файлу истории. Парсили его и сопоставляли время и URL. Работало так себе…

Потом создатели более продвинутых систем учета времени пытались обращаться напрямую к элементам управления окна браузера, находить там поле ввода URL и извлекать оттуда информацию. Всё шло хорошо, пока Google не переписал движок Chrome (на котором помимо самого Хрома, основан ряд других браузеров). Теперь никаких системных полей ввода не используется, все элементы управления реализует сам движок. Снова тупик…

И тут на помощь самым продвинутым пришла подсистема помощи людям с ограниченными возможностями. Стандартная подсистема Windows умеет моделировать голос и прочитывать слабовидящим содержимое различных полей на экране. В том числе… да, поля ввода URL. А значит информацию из этого поля можно получить с помощью Accesibility API.

Лучший из существующих примеров реализации этого подхода написан на AutoHotKey, но портировать его на C++ сможет каждый.

Как работает сервер


Стоп… У нас с вами получился уже достаточно объемный текст. Поэтому про сервер мы поговорим в следующий раз (начнём именно с этого места ;) )
Поделиться с друзьями
-->

Комментарии (19)


  1. AllexIn
    22.03.2017 12:15
    +2

    https://habrahabr.ru/post/275447/
    Кроссплатформа, OpenSource и(благодаря сообществу) умеет все основные браузеры парсить.


    1. Andrew_I
      22.03.2017 12:41
      -5

      Продолжение можно не писать? ))


      1. AllexIn
        22.03.2017 12:43

        Вы меня не совсем правильно поняли.
        Я к тому — что там есть большая масса решений, которые могут быть использованы в вашем проекте.


        1. Andrew_I
          22.03.2017 12:50
          -4

          Да нет, я пошутил. Я ответил ниже.
          Попозже посмотрю ваш проект. Если вынесениям против, то в следующих частях может быть что-то использую (со ссылкой на вас, конечно же)


    1. Andrew_I
      22.03.2017 12:49
      -4

      А если серьезно, то как я понял, в вашей программе работа с браузерами идет через плагины.
      Мы этот вариант уже проходили и от него отказались. Поэтому я в тексте его даже не затрагивал.
      1. В случае коммерческого софта будет очень тяжело спрятать эти расширения и не дать пользователи удалить.
      2. Вместо кода в агенте вы распыляете его между браузерами.
      3. Вы завязаны на магазин расширений, при любых проблемах с ним ваш софт перестанет работать.
      Но мои слова не умаляют вашу работу по создании вашего трекера.
      Просто я считаю, что этот подход не для рынка корпоративных систем учета рабочего времени.


      1. AllexIn
        22.03.2017 12:57

        1. В случае коммерческого софта будет очень тяжело спрятать эти расширения и не дать пользователи удалить.

        А вы тайком чтоли работаете?
        Если прописано, что расширение должно быть включено — то оно должно быть включено.
        Отключение его равносильно завершению процесса трекера в приложении. ЛОвится без проблем — капать время начнет не на конкретные сайты, а на само приложение, чего не должно происходить в случае включенного расширения.

        2. Вместо кода в агенте вы распыляете его между браузерами.

        Это плохо, потому что…?

        3. Вы завязаны на магазин расширений, при любых проблемах с ним ваш софт перестанет работать.

        Нет, конечно. Все расширения ставятся из папочки с приложением. Ни одно расширение в магазинах не зарегистрировано. :) Там вообще много других проблем. Но выхлоп гораздо универсальней, чем accessabilty виндовое. Хотя, вариант интересный, конечно. Стоит разобраться, есть ли такое под Win/Lin


        1. Andrew_I
          22.03.2017 13:32
          -6

          А вы тайком чтоли работаете?

          Любая коммерческая система имеет вариант со скрытым использованием агента. Обязана иметь, если хочет продаваться.

          Это плохо, потому что…?

          Потому что слишком много мест, где может возникнуть проблема. Слишком сложно устанавливать и обновлять многокомпонентный продукт.

          Нет, конечно. Все расширения ставятся из папочки с приложением. Ни одно расширение в магазинах не зарегистрировано. :) Там вообще много других проблем. Но выхлоп гораздо универсальней, чем accessabilty виндовое. Хотя, вариант интересный, конечно. Стоит разобраться, есть ли такое под Win/Lin

          Возвращаясь к коммерческим системам — установка всех компонентов должна быть автоматизированная и, по возможности скрытая.
          Кстати, на Маках все гораздо проще. У Сафари и Хрома есть интерфейсы для AppleScript. Так что всё выполняется за одну команду.


          1. shifttstas
            22.03.2017 15:57
            +3

            Любая коммерческая система имеет вариант со скрытым использованием агента. Обязана иметь, если хочет продаваться.

            И если в трудовом договоре с работником это не было оговорено — это статья.


            1. Andrew_I
              22.03.2017 18:03
              -4

              Хотите дам контакты директора по развитию? С ним и поспорите. Со мной бесполезно.
              Я привел рыночные требования к продукту. Нравятся они вам или нет- но без них не купят.


  1. Zlobro
    22.03.2017 13:32
    -1

    Хорошая обзорная статья. Как давно вы занимаетесь разработкой подобного рода софта, учитывая что у вас есть многолетний опыт?
    Хотелось бы увидеть продолжение.


    1. Andrew_I
      22.03.2017 13:33
      -1

      Подобного софта — года три. Эта статья — своего рода возврат долга обществу )))


  1. Idot
    22.03.2017 17:11
    +7

    Всегда считал козлами тех кто подобный контроль пиарит, а мерилом работы считает усталость.


    1. Andrew_I
      22.03.2017 18:02
      -7

      Дорогой Idot, оставьте эту патетику для моих менеджеров. Спорьте с теми, кто ставит задачи, кто продает и кто покупает.
      Я пишу код, а тут рассказываю как людям обрести свой бизнес.
      Вы — против?


      1. Idot
        22.03.2017 18:07
        +3

        Спорьте с теми, кто ставит задачи, кто продает

        Вы это продаёте? Или за бесплатно раздаёте?


    1. AllexIn
      22.03.2017 18:26
      -4

      Козлы — те, кто это на работе использует.
      А ребята просто делают софт.
      Все таки, ИМХО, категорически неправильно судить кого-то за факт написания софта только потому, что софт может быть использован во зло.


      1. Idot
        22.03.2017 18:30
        +4

        А ребята просто делают софт.

        По Вашей логике:
        "… а ребята просто выращивают травку и грибочки, козлы — те, кто этим барыжит".


        PS Я могу поверить, что и травку и грибочки могут выращивать и для себя.
        Расскажите как такой софт можно использовать для собственного употребления?


        1. AllexIn
          22.03.2017 18:32
          -3

          Если выращивание травки не является незаконным — то почему бы и нет? Я вот не испытываю никакого негатива к людям, которые в Амстердаме травку выращивает.
          Производитель оружия — не злодей. Злодеи те, кто это оружие использует.


          1. Idot
            22.03.2017 18:37
            +2

            Если выращивание травки не является незаконным — то почему бы и нет?

            По Вашей логике: "если пытки и гулаги не являются незаконными — то почему бы и нет?"


            PS Вы не ответили на вопрос про собственное употребление такого софта — для собственных нужд (по аналогии с травкой и грибочками).


  1. AllexIn
    22.03.2017 18:53
    -1

    По Вашей логике: «если пытки и гулаги не являются незаконными — то почему бы и нет?»

    Разработка дыбы и других инструментов для пыток не является ничем предосудительным.

    Вы не ответили на вопрос про собственное употребление такого софта — для собственных нужд

    Вот здесь ответ:https://habrahabr.ru/post/275447/
    А вообще, разработка оружия не является предосудительной, даже если ничего кроме убийства оно делать не может. Как минимум это может быть полезно для собственного развития.
    Я именно поэтому считаю что любое ПО можно свободно разрабатывать. АДже вирусы и всякую другую вредоносину. Потому что иначе мы придем к тому, что сажать начнут людей, которые просто изучают материалы и дома для себя пишут вирусы. Разработка любого ПО —
    то ок.
    Использование — под вопросом. Также как и использование любого другого инструмента.