Учёт кУмпУтеров в организации.

Итак. Встал недавно вопрос: где у кого какая конфигурация системного блока. Главные критерии: Процессор, память. Не долго думая, сваял базу на MS SQL 2008R2 и нарисовал на коленке клиент, который запускается ежедневно, но заносит данные только по команде.
Почему именно в базе? А чтобы иметь статистические данные за произвольный промежуток времени. К тому же иметь гору разрозненных файлов как-то не комильфо. Или будет 1 файл, но могут появиться проблемы доступа.
Почему именно клиент? Есть же такая утилита, как systeminfo? Окей. Допустим, в автозагрузку я поставил её выполнение. Тогда загрузка либо увеличится на период от 30 секунд до нескольких минут. К тому же в некоторых вариантах отобразится консоль, чем немало напугает пользователя и, скорее всего, он его закроет. А значит, что статистика не уйдёт.
Если кому-нибудь интересна тема, то могу позже выложить и клиент для просмотра результатов.
Системные требования: да никаких. Главное условие - сеть и наличие контроллера домена. Также желательно более-менее упорядочить нахождение компьютеров в отделах. На будущее...
Имя базы: PCBejesus.
Скрипт создания таблиц:
USE [PCBejesus]
GO
/****** Object: Default [dbo].[def_User] Script Date: 01/26/2016 10:36:09 ******/
CREATE DEFAULT [dbo].[def_User] AS SUser_SName()
GO
/****** Object: Default [dbo].[def_Now] Script Date: 01/26/2016 10:36:09 ******/
CREATE DEFAULT [dbo].[def_Now] AS GetDate()
GO
/****** Object: Table [dbo].[PCInfo] Script Date: 01/26/2016 10:36:03 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[PCInfo](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ID_Hostname] [int] NOT NULL,
[ID_Inventory] [int] NOT NULL,
[ProcFrequency] [int] NULL,
[ProcVendor] [nvarchar](256) NULL,
[ProcModel] [nvarchar](256) NULL,
[ProcCount] [int] NULL,
[BIOS] [nvarchar](256) NULL,
[Memory] [bigint] NULL,
[OSName] [nvarchar](32) NULL,
[OSArch] [nvarchar](16) NULL,
[EditDate] [datetime] NULL,
[EditUser] [nvarchar](128) NULL,
CONSTRAINT [PK_PCInfo_ID] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY],
CONSTRAINT [UK_PCInfo_IDHostName_IDInventory] UNIQUE NONCLUSTERED
(
[ID_Hostname] ASC,
[ID_Inventory] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[Inventory] Script Date: 01/26/2016 10:36:03 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Inventory](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Date] [date] NULL,
[Comment] [nvarchar](50) NULL,
[EditDate] [datetime] NULL,
[EditUser] [nvarchar](128) NULL,
CONSTRAINT [PK_Inventory_ID] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[Host] Script Date: 01/26/2016 10:36:03 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Host](
[ID] [int] IDENTITY(1,1) NOT NULL,
[HostName] [nvarchar](128) NULL,
[EditDate] [datetime] NULL,
[EditUser] [nvarchar](128) NULL,
CONSTRAINT [PK_Host_ID] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY],
CONSTRAINT [UK_Host_HostName] UNIQUE NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[HDDInfo] Script Date: 01/26/2016 10:36:03 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[HDDInfo](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ID_HostName] [int] NOT NULL,
[ID_Inventory] [int] NOT NULL,
[Letter] [nvarchar](4) NULL,
[Free] [bigint] NULL,
[Total] [bigint] NULL,
[EditDate] [datetime] NULL,
[EditUser] [nvarchar](128) NULL,
CONSTRAINT [PK_HDDInfo_ID] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: View [dbo].[V_PCInfo_LastInventory] Script Date: 01/26/2016 10:36:06 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE View [dbo].[V_PCInfo_LastInventory]
As
Select Distinct
[ID_HostName],
Max([ID_Inventory]) as "ID_Inventory"
From [PCInfo]
Group by
[ID_HostName]
GO
/****** Object: View [dbo].[V_HDDInfo_LastInventory] Script Date: 01/26/2016 10:36:06 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create View [dbo].[V_HDDInfo_LastInventory]
As
Select Distinct
[ID_HostName],
Max([ID_Inventory]) as "ID_Inventory"
From [HDDInfo]
Group by
[ID_HostName]
GO
/****** Object: UserDefinedFunction [dbo].[UF_GetCurrInventory] Script Date: 01/26/2016 10:36:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create Function [dbo].[UF_GetCurrInventory]()
Returns Int
As
Begin
Declare @Res Int
Select @Res = Max([ID])
From [Inventory]

Return @Res
End
GO
/****** Object: View [dbo].[V_Snapshot] Script Date: 01/26/2016 10:36:07 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE View [dbo].[V_Snapshot]
As
Select
h.[ID],
h.[HostName],
[dbo].[UF_GetCurrInventory]() as "ID_Inventory",
Case IsNull(pl.[ID_Inventory], 0)
When [dbo].[UF_GetCurrInventory]() then 0
Else
1
End as "PCInfo",
Case IsNull(hl.[ID_Inventory], 0)
When [dbo].[UF_GetCurrInventory]() then 0
Else
1
End as "HDDInfo"
From [Host] h
Left Join [V_PCInfo_LastInventory] pl on
pl.[ID_HostName] = h.[ID]
Left Join [V_HDDInfo_LastInventory] hl on
hl.[ID_HostName] = h.[ID]
GO

Логический смысл таблиц:
Host - Список компьютеров. Просто имя хоста. По нему и будем вести учёт.
HDDInfo - Список жёстких дисков, их общий объём и свободное место.
PCInfo - Описание системы.
Inventory - Дата, инвентаризации. Если старше этой даты отчёта нет, то он формируется.
Заодно создаются и значения по умолчанию. Почему-то MSSQL Server Management Studio не умеет подставлять значения по умолчания полям. Прошу проверить, что все поля [EditDate] имеют значение по умолчанию def_Now, а [EditUser] def_User.
Также нужно самостоятельно проследить, что разрешения на изменение выставлены правильно. Я создал пользователя для группы контроллера домена "Пользователи" и дал права datareader/datawriter на базу. А потом запретил удаление на каждею таблицу =).
Вот код программы на Delphi (RAD 2009):
program PCBejesus;
uses
Dialogs,
Forms,
Registry,
Classes,
Windows,
SysUtils,
Types,
ADODB,
Generics.Collections;
type
RProcessor = record
Frequency: Word;
Vendor: string;
Model: string;
ProcCount: Byte;
end;
RHDD = record
Letter: string;
Total: Int64;
Free: Int64;
end;
THDD = TList<RHDD>;
function _GetHostName: string;
var
BufferSize_: Cardinal;
begin
BufferSize_ := MAX_COMPUTERNAME_LENGTH + 1;
SetLength(Result, BufferSize_);
GetComputerName(PChar(Result), BufferSize_);
SetLength(Result, BufferSize_);
end;
function _GetProcInfo: RProcessor;
var
Reg_: TRegistry;
tmp_: TStringList;
begin
Reg_ := TRegistry.Create;
Reg_.RootKey := HKEY_LOCAL_MACHINE;
Reg_.OpenKeyReadOnly('\Hardware\Description\System\CentralProcessor\0');
Result.Frequency := Reg_.ReadInteger('~MHz');
Result.Vendor := Trim(Reg_.ReadString('VendorIdentifier'));
Result.Model := Trim(Reg_.ReadString('ProcessorNameString'));
Reg_.OpenKeyReadOnly('\Hardware\Description\System\CentralProcessor');
tmp_ := TStringList.Create;
Reg_.GetKeyNames(tmp_);
Result.ProcCount := tmp_.Count;
FreeAndNil(tmp_);
FreeAndNil(Reg_);
end;
function _GetBiosInfo: string;
var
Reg_: TRegistry;
Buffer_: PWideChar;
Info_: TRegDataInfo;
begin
Reg_ := TRegistry.Create;
Reg_.RootKey := HKEY_LOCAL_MACHINE;
Reg_.OpenKeyReadOnly('\Hardware\Description\System');
if not Reg_.GetDataInfo('VideoBiosVersion', Info_) then
Exit;
GetMem(Buffer_, Info_.DataSize);
Reg_.ReadBinaryData('SystemBiosVersion', Buffer_^, Info_.DataSize);
Result := Buffer_;
FreeMem(Buffer_);
FreeAndNil(Reg_);
end;
function _GetMemoInfo: Cardinal;
var
Mem_: TMemoryStatus;
begin
Mem_.dwLength := SizeOf(Mem_);
GlobalMemoryStatus(Mem_);
Result := Mem_.dwTotalPhys;
end;
function _GetOSInfo: string;
begin
case Win32MajorVersion of
4: Result := 'Windows NT';
5:
case Win32MinorVersion of
0: Result := 'Windows 2000';
1: Result := 'Windows XP';
else Result := 'Unknown';
end;
6:
case Win32MinorVersion of
0: Result := 'Windows Vista';
1: Result := 'Windows 7';
2: Result := 'Windows 8';
3: Result := 'Windows 8.1';
else Result := 'Unknown';
end;
10: Result := 'Windows 10';
else Result := 'Unknown';
end;
end;
function _GetOSBit: string;
var
IsWow64Process_: function(hProcess__: THandle; out Wow64Process__: BOOL): BOOL; stdcall;
Wow64Process_: BOOL;
begin
{$IF Defined(CPU64)}
Result := 'x64';
{$ELSEIF Defined(CPU16)}
Result := 'Калькулатор';
{$ELSE}
@IsWow64Process_ := GetProcAddress(GetModuleHandle('Kernel32.dll'), PAnsiChar('IsWow64Process'));
Wow64Process_ := False;
if Assigned(IsWow64Process_) then
Wow64Process_ := IsWow64Process_(GetCurrentProcess, Wow64Process_) and Wow64Process_;
if Wow64Process_ then
Result := 'x64'
else
Result := 'x86';
{$IFEND}
end;
function _GetHDDInfo: THDD;
var
Drives_: PWideChar;
Drive_: PWideChar;
Free_, Total_: Int64;
HDD: RHDD;
begin
Result := THDD.Create;
Drives_ := StrAlloc(MAX_PATH);
try
GetLogicalDriveStrings(MAX_PATH, Drives_);
Drive_ := Drives_;
while (Drive_^ <> #0) do

begin
if GetDriveType(Drive_) = DRIVE_FIXED then
begin
GetDiskFreeSpaceEx(Drive_, Free_, Total_, nil);
HDD.Letter := StrPas(Drive_);
HDD.Total := Total_;
HDD.Free := Free_;
Result.Add(HDD);
end;
Inc(Drive_, lstrlen(Drive_) + 1)
end;
finally
StrDispose(Drives_);
end;
end;
{
var
Output: TStringList;
Processor: RProcessor;
HDD: THDD;
i: Integer;
}
const
c_GetSnapshot = 'Select * From [V_Snapshot] Where [HostName] = '#39'%s'#39;
c_SetHostName = 'Insert Into [Host] ([HostName]) Values ('#39'%s'#39')';
var
conMain: TADOConnection;
qryMain: TADOQuery;
tblMain: TADOTable;
ID_HostName: Integer;
ID_Inventory: Integer;
Status: set of (stsNone, stsPCInfo, stsHDDInfo);
Processor: RProcessor;
HDD: THDD;
i: Integer;
begin
{
Output := TStringList.Create;
Processor := _GetProcInfo;
HDD := _GetHDDInfo;
Output.Add('HostName: ' + _GetHostName);
Output.Add('Frequency: ' + IntToStr(Processor.Frequency));
Output.Add('Vendor: ' + Processor.Vendor);
Output.Add('Model: ' + Processor.Model);
Output.Add('Count: ' + IntToStr(Processor.ProcCount));
Output.Add('BIOS: ' + _GetBiosInfo);
Output.Add('Memory: ' + Format('%0.0f Мбайт',[_GetMemoInfo div 1024 / 1024]));
Output.Add('OS: ' + _GetOSInfo);
Output.Add('Bit: ' + _GetOSBit);
for i := 0 to HDD.Count - 1 do
Output.Add('HDD: ' + Format('%s %0.0f Гб %0.0f Гб',[HDD.Items[i].Letter,
HDD.Items[i].Total div 1024 / 1024 / 1024,
HDD.Items[i].Free div 1024 / 1024 / 1024]));
ShowMessage(Output.Text);
FreeAndNil(HDD);
FreeAndNil(Output);
}
conMain := TADOConnection.Create(Application);
conMain.ConnectionString := 'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=PCBejesus;Data Source=<ТУТ должен быть ваш сервер>';
conMain.LoginPrompt := False;
qryMain := TADOQuery.Create(conMain);
qryMain.Connection := conMain;
tblMain := TADOTable.Create(conMain);
tblMain.Connection := conMain;
ID_HostName := -1;
Status := [];
try
repeat
qryMain.Close;
qryMain.SQL.Text := Format(c_GetSnapshot, [_GetHostName]);
qryMain.Open;
if qryMain.RecordCount = 1 then
begin
if qryMain.FieldByName('PCInfo').AsInteger = 1 then
Status := Status + [stsPCInfo];
if qryMain.FieldByName('HDDInfo').AsInteger = 1 then
Status := Status + [stsHDDInfo];
ID_HostName := qryMain.FieldByName('ID').AsInteger;
ID_Inventory := qryMain.FieldByName('ID_Inventory').AsInteger;
end
else
begin
qryMain.Close;
qryMain.SQL.Text := Format(c_SetHostName, [_GetHostName]);
qryMain.ExecSQL;
end;
until ID_HostName <> -1;
if stsPCInfo in Status then
begin
Processor := _GetProcInfo;
tblMain.Close;
tblMain.TableName := 'PCInfo';
tblMain.Open;
tblMain.Insert;
tblMain.FieldByName('ID_HostName').Value := ID_HostName;
tblMain.FieldByName('ID_Inventory').Value := ID_Inventory;
tblMain.FieldByName('ProcFrequency').Value := Processor.Frequency;
tblMain.FieldByName('ProcVendor').Value := Processor.Vendor;
tblMain.FieldByName('ProcModel').Value := Processor.Model;
tblMain.FieldByName('ProcCount').Value := Processor.ProcCount;
tblMain.FieldByName('BIOS').Value := _GetBiosInfo;
tblMain.FieldByName('Memory').Value := _GetMemoInfo;
tblMain.FieldByName('OSName').Value := _GetOSInfo;
tblMain.FieldByName('OSArch').Value := _GetOSBit;
tblMain.Post;
end;
if stsHDDInfo in Status then
begin
HDD := _GetHDDInfo;
tblMain.Close;
tblMain.TableName := 'HDDInfo';
tblMain.Open;
for i := 0 to HDD.Count - 1 do
begin
tblMain.Insert;
tblMain.FieldByName('ID_HostName').Value := ID_HostName;
tblMain.FieldByName('ID_Inventory').Value := ID_Inventory;
tblMain.FieldByName('Letter').Value := HDD.Items[i].Letter;
tblMain.FieldByName('Free').Value := HDD.Items[i].Free;
tblMain.FieldByName('Total').Value := HDD.Items[i].Total;
tblMain.Post;
end;
FreeAndNil(HDD);
end;
finally
tblMain.Close;
FreeAndNil(tblMain);
qryMain.Close;
FreeAndNil(qryMain);
conMain.Close;
FreeAndNil(conMain);
end;
end.


Повторюсь: если кому-нибудь нужна прога для просмотра, обращайтесь в личку.
  • просмотров: ~1636
  • рейтинг: ?

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

Вы - anonymous, войти ?

можно использовать bbcode-теги
[b]жирный текст[/b]
[i]курсив[/i]
[u]underline[/u]
[s]зачеркнутый текст[/s]
[size=20px]размер шрифта[/size]
всякие изменения текста
[left][/left]
[right][/right]
[center][/center]
позиционирование элементов: картинки, текст и т.д
[url][/url]
[email][/email]
внутри тега [url] помещайте ссылки, а внутри [email] адрес электронной почты;
так же [url] можно использовать в виде:
[url=http://example.com]пример[/url],
[url=http://test.ru][img]http://flickr.com/givemeimg.png[/img][/url]
[code][/code]
[quote][/quote]
внутри тега [code] можно помещать программный код (подстветка попытается включиться автоматически); для выделения цитат используйте [quote]
также можно напрямую указать язык [code=cpp]int i;[/code]
[list][/list]
создаем списки, каждый элемент пишется после [*].

Можно указывать маркер - [list=marker].
возможные маркеры 1(decimal), i(lower-roman), I(upper-roman), a(lower-alpha), A(upper-alpha). Примеры:

[list][*]1 элемент[*]2 элемент[*]3 элемент[/list]
[list=1][*]1 элемент[*]2 элемент[*]3 элемент[/list]
[list=A][*]1 элемент[*]2 элемент[*]3 элемент[/list]
[table][/table]
оформляем таблицу, используя внутренние теги [tr] и [td].
[tr] - строка, [td] - поле в строке,
[table=100%] - можно задавать ширину в процентах, по-умолчанию ширина 100%
[td=2] - можно задавать сколько столбцов входит в это поле. Пример:

[table=50%][tr][td]столбец 1[/td][td]столбец 2[/td][/tr][tr][td]значение 1[/td][td]значение 2[/td][/tr][tr][td=2]сразу 2 столбца[/td][/tr][/table]
[img][/img]
тег для вставки фото или картинок, мы любим картинки. Примеры использования:

[img]http://ya.ru/logo.png[/img],
[img=100x100px]http://ya.ru/logo.png[/img]
[img=fullimg.url]thumbimg.url[/img],
Пожалуйста загружайте картинки на наш сайт, либо вставляйте с бекбоновских ресурсов.
[video][/video]
Проигрывает видео, внутрь вставляем ссылки на видео, поддерживается Play.Ykt.Ru(нужно вставить ссылку на страницу с видео) и tv.ykt.ru(нужно вставить ссылку на адрес файла)