Удобный поиск компьютера пользователя в домене Windows

в 11:57, , рубрики: php+mssql, поддержка пользователей, Программирование, системное администрирование

Привет всем!
Работаю в компании. 1500+ активных пользователей.
Организован ХелпДеск, сотрудники регистрируют тикеты в системе, но, как-то так получается, что часть из юзеров забывают указывать имя пк, за которым они находятся.

Для выяснения этой информации (по телефону/email/экстрасенсорные способности) девочки из поддержки тратят драгоценное время, которое они могли бы уделить свежей чашке кофе или разговорам о новом платье (шутка). Наши сотрудники постоянно заняты своей непосредственной работой.

Идея (не инновация конечно) — писать данные о логонах пользователя в единую базу, а потом через веб оперативно искать нужную информацию.

image

Что у нас есть?

Windows среда (ХР/7/2003/2008), учетные записи хранятся в AD, все устройства работаю в локальной сети в качестве СУБД используем MSSQL 2005/2008R2.

Что мы хотим?

Поиск информации через веб интерфейс:

  1. Где логинился сотрудник с фамилией, например, "Иванов";
  2. Кто логинился на устройстве, например, "PC34";
  3. Где были совершены логоны под учетной записью, например, "hr.ivanov".

Должна отображаться информация:

  • имя пк;
  • login;
  • фио;
  • ip адрес;
  • дата логона.

Название?

Так как «решением» будут пользоваться несколько человек (от 5 до 35 человек), надо как-то его обозвать для удобства. Нарекли мы его «SuperVisor».

Приступим к реализации

Как будем писать в БД?

Первое, что пришло в голову — это создать bat файл с sqlcmd, но для каждой версии Windows нужна своя версия утилиты sqlcmd. Неудобно, и мы не стали копать глубже.

Вторым решением было создать небольшой exe клиент, который при запуске будет собирать данные об имени доменной учетной записи, имени пк, ip адресе пк и после получения этой информации будет выполняться вставка данных в БД. Программу размещаем, например, в папке NETLOGON на контроллере домена и групповыми политиками распространяем на ПК/Сервера в локальной сети компании.

Программа на Delphi

unit Unit1;
interface
uses
  Windows,SysUtils, Variants, Classes, Forms,WinSock,
  Dialogs, DB, ADODB,StdCtrls,Messages, ExtCtrls;
type
  TForm1 = class(TForm)
    boston: TADOConnection;
    qryinsert: TADOQuery;
    timer: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure timerTimer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;

implementation

{$R *.dfm}
// версия 0.0.4
// дата 27-02-2014

function GetCurrentUserName: string;
 const
   cnMaxUserNameLen = 254;
 var
   sUserName: string;
   dwUserNameLen: DWORD;
 begin
   dwUserNameLen := cnMaxUserNameLen - 1;
   SetLength(sUserName, cnMaxUserNameLen);
   GetUserName(PChar(sUserName), dwUserNameLen);
   SetLength(sUserName, dwUserNameLen);
   Result := string(sUserName);
 end;

 function GetCurrentComputerName: string;
 const
   cnMaxComputerNameLen = 254;
 var
   sComputerName: string;
   dwComputerNameLen: DWORD;
 begin
   dwComputerNameLen := cnMaxComputerNameLen - 1;
   SetLength(sComputerName, cnMaxComputerNameLen);
   GetComputerName(PChar(sComputerName), dwComputerNameLen);
   SetLength(sComputerName, dwComputerNameLen);
   Result := string(sComputerName);
 end;

  function GetLocalIP: String;
  const WSVer = $101;
  var
    wsaData: TWSAData;
    P: PHostEnt;
    Buf: array [0..127] of Char;
  begin
    Result := '';
    if WSAStartup(WSVer, wsaData) = 0 then begin
      if GetHostName(@Buf, 128) = 0 then begin
        P := GetHostByName(@Buf);
        if P <> nil then Result := iNet_ntoa(PInAddr(p^.h_addr_list^)^);
      end;
      WSACleanup;
    end;
  end;


  procedure TForm1.FormCreate(Sender: TObject);
  begin
  try
    qryinsert.SQL.Text := 'begin TRANSACTION insertdata' +#13#10 +
    'insert into [supervisor].[user].[info_host](host,login,last_ip) values (:host,:login,:ip)'+#13#10 +
    'COMMIT TRANSACTION insertdata';
    qryinsert.Parameters.ParamByname('login').Value:= GetCurrentUserName ;
    qryinsert.Parameters.ParamByname('host').Value:= GetCurrentComputerName ;
    qryinsert.Parameters.ParamByname('ip').Value:= GetLocalIP ;
    qryinsert.ExecSQL;    
    timer.Enabled:=True;
    form1.timer.Interval:=1500;
  except    
    Application.Terminate;
  end
  end;

  procedure TForm1.timerTimer(Sender: TObject);
  begin
    ExitProcess(0);
  end;
end.

Дальше алгоритм такой:

  1. Пользователь логинится за пк;
  2. Скрытно запускается SuperVisor.exe;
  3. Делается попытка INSERT в указанную бд, если успешно, то программа завершает свою работу;
  4. Если выполнить INSERT не получается (ноутбук не в локальной сети, сервер бд недоступен и т.д), таймаут 15 секунд и процесс «убивается», не пугая пользователя страшными сообщениями и окнами.
Отлично, теперь создадим таблицы, в которых будут храниться данные

/* 

Главная таблица, в которую пишутся логоны
-----------------------------------------------------------
host - имя пк
login - имя доменной учетной записи
last_ip - ip адрес пк
createdate - дата создания записи
createdate_unix - unix время, дата создания записи
------------------------------------------------------------

*/

CREATE TABLE [user].[info_host](
	[id] [int] IDENTITY(1,1) NOT NULL,
	[host] [nvarchar](128) NULL,
	[login] [nvarchar](128) NULL,
	[createdate] [datetime] NOT NULL,
	[createdate_unix] [int] NOT NULL,
	[last_ip] [nvarchar](20) NULL
) ON [supervisor]

GO

ALTER TABLE [user].[info_host] ADD  DEFAULT (getdate()) FOR [createdate]
GO

ALTER TABLE [user].[info_host] ADD  DEFAULT (datediff(second,'1970-01-01 00:00:00',getutcdate())) FOR [createdate_unix]

/*

Таблица справочник с ФИО учетных записей, наполняется из АД. Синхронизация происходит один раз в сутки
------------------------------------------------------------
login - имя доменной учетной записи
displayName - поле displayname из АД для учетной записи 
createdate - дата создания записи
createdate_unix - unix время, дата создания записи
------------------------------------------------------------

*/

CREATE TABLE [user].[info_login_card](
	[id] [int] IDENTITY(1,1) NOT NULL,
	[login] [nvarchar](128) NULL,
	[createdate] [datetime] NOT NULL,
	[createdate_unix] [int] NOT NULL,
	[displayName] [nvarchar](256) NULL
) ON [supervisor]

GO

ALTER TABLE [user].[info_login_card] ADD  DEFAULT (getdate()) FOR [createdate]
GO

ALTER TABLE [user].[info_login_card] ADD  DEFAULT (datediff(second,'1970-01-01 00:00:00',getutcdate())) FOR [createdate_unix]
GO

Таблицы созданы и наполняются данными. Забыл написать, что сервер БД у нас виртуальный и работает под Windows Server 2003R2, СУБД MSSQL 2008R2. Сервер приложения виртуальный, Windows 2003R2, Apache 2.2 + PHP 5.2

Следующий шаг — создание веб интерфейса для того, чтобы системные администраторы и сотрудники хелпдеска могли комфортно работать с сервисом. Во внутренних разработках, для экономии времени, я использую фреймфорк Bootstrap. Главная страница, до того как начинают вводить данные в поисковую строку, выглядит так:

image

В строку поиска можно ввести фамилию сотрудника/учетную запись(логин) или имя компьютера:

image

Причем, не обязательно вводить полностью фамилию и имя сотрудника/логин/имя пк, поиск совпадений в БД осуществляется с помощью оператора LIKE ( пример ...LIKE 'ива%'), запросы выполняются асинхронно, результат поиска обновляется перед глазами сотрудника без перезагрузки страницы после ввода нового символа в строку поиска.

запрос к бд для поиска по ФИО

               set rowcount $limit
                      SELECT
                           a.[id]
                          ,a.[host]
                          ,a.[login]
                          ,a.[createdate]
                          ,a.[createdate_unix]
                          ,a.[last_ip]
                          ,b.[displayName]
                      FROM [user].[info_host] a
                     left join [user].[info_login_card] b on a.login = b.login
                      where b.displayName like ('$ihostlogin')
                      order by a.[createdate_unix] desc
                        set rowcount 0

запрос к бд для поиска по имени пк

                      set rowcount $limit
                      SELECT
                           a.[id]
                          ,a.[host]
                          ,a.[login]
                          ,a.[createdate]
                          ,a.[createdate_unix]
                          ,a.[last_ip]
                          ,b.[displayName]
                      FROM [user].[info_host] a
                     left join [user].[info_login_card] b on a.login = b.login
                      where a.host like ('$hostlogin')
                      order by a.[createdate_unix] desc
                        set rowcount 0

поиск по логину

set rowcount $limit
                      SELECT
                           a.[id]
                          ,a.[host]
                          ,a.[login]
                          ,a.[createdate]
                          ,a.[createdate_unix]
                          ,a.[last_ip]
                          ,b.[displayName]
                      FROM [user].[info_host] a
                     left join [user].[info_login_card] b on a.login = b.login
                      where a.login like ('$hostlogin')
                      order by a.[createdate_unix] desc
                        set rowcount 0

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

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

Успехов в работе!

Полезные ссылки

Установка Apache2.2 и PHP-5;
Подключение MS SQL к PHP 5.3 и выше.

Автор: rus74

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js