Задача: Инвентаризация программного обеспечения на компьютерах пользователей домена. По возможности быстро и бесплатно.
Реализация: сделано через самописный модуль инвентаризации написанный на Autoit который распространяется через GPO. Модуль срабатывает раз в неделю при входе КОМПЬЮТЕРА в систему с небольшой задержкой (запускаем под учетной записью system). Данные модуль записывает в MSSQL базу (требуется какой то сервер с базой и созданной таблицей в которой будут хранится данные). Управление модулем и все параметры модуля берем из реестра. Параметры реестра задаем конечно же через GPO.
Работало на MSSQL 2012, инвентаризировало все что находило на Windows 7,8,10,2008R2,2012,2012R2.
Просмотр данных осуществлялся через создание подключения у БД через Excel 2013. С помощью фильтров Excel показывал практически весь софт установленный у любого пользователя. Что не было реализовано: со временем база сильно разрасталась, очистку делаю вручную раз 0,5-1 год.
Собственно ниже сам луна-парк с игральными картами и девушками легкого поведения )
Модуль:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | #NoTrayIcon #Include <Array.au3> $myRegX86 = 'HKEY_LOCAL_MACHINE\SOFTWARE\msbro\SoftwareInventory' $myRegX64 = 'HKEY_LOCAL_MACHINE64\SOFTWARE\msbro\SoftwareInventory' $myRegPath ='' If Not StringInStr(@OSArch, "X86") Then    $myRegPath = $myRegX64    Else    $myRegPath = $myRegX86 EndIf $Install = RegRead($myRegPath, "InventoryFilesInstallKey") If Not StringInStr($Install, "yes") Then    ConsoleWrite('NOT FOUND INSTALL KEY' & @CRLF)    exit Else Dim  $aSoftwareInfo LOCAL $my_ComputerName = @ComputerName LOCAL $my_UserName = @UserName LOCAL $my_Date = @YEAR&'-'&@MON&'-'&@MDAY LOCAL $my_Time = @HOUR&'-'&@MIN&'-'&@SEC LOCAL $my_Delay LOCAL $Connect_SQL_String EndIf $Connect_SQL_String = RegRead($myRegPath, "Connect_SQL_String") $my_Delay = RegRead($myRegPath, "Delay") Sleep($my_Delay) _ComputerGetSoftware($aSoftwareInfo) ;_ArrayDisplay($aSoftwareInfo) Func _ComputerGetSoftware(ByRef $aSoftwareInfo)    $ConnObj = ObjCreate("ADODB.Connection")    $RezObj = ObjCreate("ADODB.Recordset")    $ConnObj.Open($Connect_SQL_String)    $RezObj.ActiveConnection = $ConnObj     Local Const $UnInstKey  = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" 	Local Const $UnInstKey_User  = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall"     Local $i = 1     Dim $aSoftwareInfo[1][10]     While 1         $AppKey = RegEnumKey($UnInstKey, $i)         If @error <> 0 Then ExitLoop         ReDim $aSoftwareInfo[UBound($aSoftwareInfo) + 1][10]         $aSoftwareInfo[$i][0]   = StringStripWS(StringReplace(RegRead($UnInstKey & "\" & $AppKey, "DisplayName"), " (remove only)", ""), 3)         $aSoftwareInfo[$i][1]   = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "DisplayVersion"), 3)         $aSoftwareInfo[$i][2]   = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "Publisher"), 3)         $aSoftwareInfo[$i][3]   = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "UninstallString"), 3) 		$aSoftwareInfo[$i][4]   = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "InstallDate"), 3) 		$aSoftwareInfo[$i][5]   = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "InstallSource"), 3) 		$aSoftwareInfo[$i][6]   = $my_ComputerName 		$aSoftwareInfo[$i][7]   = $my_UserName 		$aSoftwareInfo[$i][8]   = $my_Date 		$aSoftwareInfo[$i][9]   = $my_Time 		$sqlString = "INSERT INTO SoftwareInventory (DisplayName, DisplayVersion, Publisher,UninstallString,InstallDate,InstallSource,ComputerName,UserName,CheckDate,CheckTime) VALUES (N'"&$aSoftwareInfo[$i][0]&"', N'"&$aSoftwareInfo[$i][1]&"', N'"&$aSoftwareInfo[$i][2]&"',N'"&$aSoftwareInfo[$i][3]&"',N'"&$aSoftwareInfo[$i][4]&"',N'"&$aSoftwareInfo[$i][5]&"',N'"&$aSoftwareInfo[$i][6]&"',N'"&$aSoftwareInfo[$i][7]&"',N'"&$aSoftwareInfo[$i][8]&"',N'"&$aSoftwareInfo[$i][9]&"')" 		;ConsoleWrite('+++: ' & $aSoftwareInfo[$i][0] & '#####' &$aSoftwareInfo[$i][1] & '#####' &$aSoftwareInfo[$i][2] & '#####' &$aSoftwareInfo[$i][3] & @CRLF) 		$QueryRez = $RezObj.Open($sqlString) 		$i += 1 	 WEnd     While 1         $AppKey = RegEnumKey($UnInstKey_User, $i)         If @error <> 0 Then ExitLoop         ReDim $aSoftwareInfo[UBound($aSoftwareInfo) + 1][10]         $aSoftwareInfo[$i][0]   = StringStripWS(StringReplace(RegRead($UnInstKey_User & "\" & $AppKey, "DisplayName"), " (remove only)", ""), 3)         $aSoftwareInfo[$i][1]   = StringStripWS(RegRead($UnInstKey_User & "\" & $AppKey, "DisplayVersion"), 3)         $aSoftwareInfo[$i][2]   = StringStripWS(RegRead($UnInstKey_User & "\" & $AppKey, "Publisher"), 3)         $aSoftwareInfo[$i][3]   = StringStripWS(RegRead($UnInstKey_User & "\" & $AppKey, "UninstallString"), 3) 		$aSoftwareInfo[$i][4]   = StringStripWS(RegRead($UnInstKey_User & "\" & $AppKey, "InstallDate"), 3) 		$aSoftwareInfo[$i][5]   = StringStripWS(RegRead($UnInstKey_User & "\" & $AppKey, "InstallSource"), 3) 		$aSoftwareInfo[$i][6]   = $my_ComputerName 		$aSoftwareInfo[$i][7]   = $my_UserName 		$aSoftwareInfo[$i][8]   = $my_Date 		$aSoftwareInfo[$i][9]   = $my_Time 		$sqlString = "INSERT INTO SoftwareInventory (DisplayName, DisplayVersion, Publisher,UninstallString,InstallDate,InstallSource,ComputerName,UserName,CheckDate,CheckTime) VALUES (N'"&$aSoftwareInfo[$i][0]&"', N'"&$aSoftwareInfo[$i][1]&"', N'"&$aSoftwareInfo[$i][2]&"',N'"&$aSoftwareInfo[$i][3]&"',N'"&$aSoftwareInfo[$i][4]&"',N'"&$aSoftwareInfo[$i][5]&"',N'"&$aSoftwareInfo[$i][6]&"',N'"&$aSoftwareInfo[$i][7]&"',N'"&$aSoftwareInfo[$i][8]&"',N'"&$aSoftwareInfo[$i][9]&"')" 		;ConsoleWrite('+++: ' & $aSoftwareInfo[$i][0] & '#####' &$aSoftwareInfo[$i][1] & '#####' &$aSoftwareInfo[$i][2] & '#####' &$aSoftwareInfo[$i][3] & @CRLF) 		$QueryRez = $RezObj.Open($sqlString) 		$i += 1 	 WEnd Sleep (500) ;удаляем пустые строки $sqlString2 = "DELETE FROM SoftwareInventory WHERE DisplayName not like '%[a-z]%' and DisplayName not like '%[а-я]%' and CheckDate like '"&$my_Date&"' and ComputerName like '"&$my_ComputerName&"'" $QueryRez2 = $RezObj.Open($sqlString2)     $ConnObj.Close     ConsoleWrite('END !!!' & @CRLF)     $aSoftwareInfo[0][0] = UBound($aSoftwareInfo, 1) - 1     If $aSoftwareInfo[0][0] < 1 Then         SetError(1, 1, 0)     EndIf EndFunc | 
Скрипт SQL для создания таблицы:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | CREATE TABLE Soft_1 (     ID int IDENTITY(1,1) PRIMARY KEY,     DisplayName varchar(255), 	DisplayVersion varchar(255), 	Publisher varchar(255), 	UninstallString varchar(255) 	InstallDate varchar(255) 	InstallSource varchar(255) 	ComputerName varchar(255) 	UserName varchar(255) 	CheckDate varchar(255) 	CheckTime varchar(255) ); | 
Файл реестра в качестве примера (если не хотите использовать GPO):
| 1 2 3 4 5 6 | Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\MSBRO\SoftwareInventory] "Delay"=hex(b):10,27,00,00,00,00,00,00 "Connect_SQL_String"="Provider=SQLOLEDB.1;Password=p@ssword1;Persist Security Info=True;User ID=DB-INVENTORY-USER;Initial Catalog=TABLE-INVENTORY;Data Source=SRV-SQL-01" "InventoryFilesInstallKey"="yes" | 
User ID – пользователь БД MSSQL (создаете сами)
Password – пароль этого пользователя
Initial Catalog – это имя БД, в которую складываются данные
Data Source – сервер на котором у вас работает MSSQL
“InventoryFilesInstallKey”=”yes” – говорит что запуск разрешен. Проверяя при запуске реестр и не найдя магического слова “yes” модуль завершает работу. Сделано для “мягкого” выключения из работы там где он не нужен.
///
Все это в виде архива можно ВЗЯТЬ ТУТ Autoit-Inventory.
Просьба не пинать ногами, все написано на коленке.