Computer Monitor Inventory Data Query
Greetings Folks!
Today's post is going to talk about computer monitor inventory data.
While I have found a good post from a Technet blog to get you started, I've had to modify the query referenced in that blog. As I found their query to be a bit on the broken side. So naturally I fixed it.
Also you don't have to go through the whole modifying the mof file to collect the monitor data. There is actually already a WMI class in windows so you just have to go into the default client settings for hardware inventory and add/select the class. The class you need is WMIMONITORID
The neat thing about this WMI class is that the monitor model is stored in ASCI numeric comma separated values. So you get to convert it letter by letter (or should I say two numbers by two numbers).
In order to do the conversion, we are using a cursor. While some of you SQL experts out there may say that this is not the most elegant method. It gets the job done, be it a bit slowly.
Anyways now to get to the query you have all been waiting for. This particular gem will let you select by AD Site but you can modify it to whatever criteria you would like.
---------------------------------------------------------------------
set nocount on
declare @ADSite varchar(56)
set @ADSite = 'AD Site'
-- split and conversion logic
declare @convCode nvarchar(1023)
set @convCode = N'declare @indx int; declare @valToConvert varchar(4);'
+ CHAR(13) + N'set @result='''''
+ CHAR(13) + N'while LEN(@input) > 0 begin'
+ CHAR(13) + N'select @indx = CHARINDEX('','', @input)'
+ CHAR(13) + N'select @valToConvert = SUBSTRING(@input, 0, @indx)'
+ CHAR(13) + N'if (@valToConvert = ''0'') OR (@valToConvert = '''') break'
+ CHAR(13) + N'select @result = @result + CHAR(@valToConvert)'
+ CHAR(13) + N'select @input = SUBSTRING(@input, @indx+2, LEN(@input) - @indx) end'
declare @params nvarchar(500)
set @params = N'@input varchar(255), @result varchar(255) OUTPUT'
-- table variable
declare @convertTab table (
ResourceID int,
UserFriendlyName0 nvarchar(255),
UserFriendlyNameLength0 int,
UserFriendlyNameConv varchar(255),
ManufacturerName0 nvarchar(255),
ProductCodeID0 nvarchar(255),
SerialNumberID0 nvarchar(255),
WeekOfManufacture0 int,
YearOfManufacture0 int
)
-- select data to report on, into the table variable
insert @convertTab
(ResourceID, ManufacturerName0, ProductCodeID0, SerialNumberID0, WeekOfManufacture0, YearOfManufacture0,
UserFriendlyName0, UserFriendlyNameLength0)
select
ResourceID, ManufacturerName0, ProductCodeID0, SerialNumberID0, WeekOfManufacture0, YearOfManufacture0,
UserFriendlyName0, UserFriendlyNameLength0
from v_GS_WMIMONITORID
where ResourceID in
(select ResourceID from v_r_system where AD_Site_Name0 = @ADSite)
-- cursor to iterate through table variable and convert
declare convert_cursor cursor for
select UserFriendlyName0 from @convertTab
declare @resId varchar(255), @fname varchar(255)
declare @out varchar(255)
open convert_cursor
fetch next from convert_cursor into @fname
while @@FETCH_STATUS = 0
begin
exec sp_executesql @convCode, @params, @input=@fname, @result=@out OUTPUT
update @convertTab set UserFriendlyNameConv = @out where UserFriendlyName0 = @fname
fetch next from convert_cursor into @fname
end
close convert_cursor
deallocate convert_cursor
set nocount off
--return converted data
select
syst.Name0, syst.AD_Site_Name0, cnvt.UserFriendlyNameConv, cnvt.UserFriendlyNameLength0,
cnvt.ManufacturerName0, cnvt.ProductCodeID0, cnvt.SerialNumberID0,
cnvt.YearOfManufacture0, cnvt.WeekOfManufacture0,
CurrentHorizontalResolution0, CurrentVerticalResolution0,VideoModeDescription0
from @convertTab cnvt join v_R_System syst
right join v_GS_VIDEO_CONTROLLER on syst.ResourceID = v_GS_VIDEO_CONTROLLER.ResourceID
on cnvt.ResourceID = syst.ResourceID
---------------------------------------------------------------------------------------------------
Today's post is going to talk about computer monitor inventory data.
While I have found a good post from a Technet blog to get you started, I've had to modify the query referenced in that blog. As I found their query to be a bit on the broken side. So naturally I fixed it.
Also you don't have to go through the whole modifying the mof file to collect the monitor data. There is actually already a WMI class in windows so you just have to go into the default client settings for hardware inventory and add/select the class. The class you need is WMIMONITORID
The neat thing about this WMI class is that the monitor model is stored in ASCI numeric comma separated values. So you get to convert it letter by letter (or should I say two numbers by two numbers).
In order to do the conversion, we are using a cursor. While some of you SQL experts out there may say that this is not the most elegant method. It gets the job done, be it a bit slowly.
Anyways now to get to the query you have all been waiting for. This particular gem will let you select by AD Site but you can modify it to whatever criteria you would like.
---------------------------------------------------------------------
set nocount on
declare @ADSite varchar(56)
set @ADSite = 'AD Site'
-- split and conversion logic
declare @convCode nvarchar(1023)
set @convCode = N'declare @indx int; declare @valToConvert varchar(4);'
+ CHAR(13) + N'set @result='''''
+ CHAR(13) + N'while LEN(@input) > 0 begin'
+ CHAR(13) + N'select @indx = CHARINDEX('','', @input)'
+ CHAR(13) + N'select @valToConvert = SUBSTRING(@input, 0, @indx)'
+ CHAR(13) + N'if (@valToConvert = ''0'') OR (@valToConvert = '''') break'
+ CHAR(13) + N'select @result = @result + CHAR(@valToConvert)'
+ CHAR(13) + N'select @input = SUBSTRING(@input, @indx+2, LEN(@input) - @indx) end'
declare @params nvarchar(500)
set @params = N'@input varchar(255), @result varchar(255) OUTPUT'
-- table variable
declare @convertTab table (
ResourceID int,
UserFriendlyName0 nvarchar(255),
UserFriendlyNameLength0 int,
UserFriendlyNameConv varchar(255),
ManufacturerName0 nvarchar(255),
ProductCodeID0 nvarchar(255),
SerialNumberID0 nvarchar(255),
WeekOfManufacture0 int,
YearOfManufacture0 int
)
-- select data to report on, into the table variable
insert @convertTab
(ResourceID, ManufacturerName0, ProductCodeID0, SerialNumberID0, WeekOfManufacture0, YearOfManufacture0,
UserFriendlyName0, UserFriendlyNameLength0)
select
ResourceID, ManufacturerName0, ProductCodeID0, SerialNumberID0, WeekOfManufacture0, YearOfManufacture0,
UserFriendlyName0, UserFriendlyNameLength0
from v_GS_WMIMONITORID
where ResourceID in
(select ResourceID from v_r_system where AD_Site_Name0 = @ADSite)
-- cursor to iterate through table variable and convert
declare convert_cursor cursor for
select UserFriendlyName0 from @convertTab
declare @resId varchar(255), @fname varchar(255)
declare @out varchar(255)
open convert_cursor
fetch next from convert_cursor into @fname
while @@FETCH_STATUS = 0
begin
exec sp_executesql @convCode, @params, @input=@fname, @result=@out OUTPUT
update @convertTab set UserFriendlyNameConv = @out where UserFriendlyName0 = @fname
fetch next from convert_cursor into @fname
end
close convert_cursor
deallocate convert_cursor
set nocount off
--return converted data
select
syst.Name0, syst.AD_Site_Name0, cnvt.UserFriendlyNameConv, cnvt.UserFriendlyNameLength0,
cnvt.ManufacturerName0, cnvt.ProductCodeID0, cnvt.SerialNumberID0,
cnvt.YearOfManufacture0, cnvt.WeekOfManufacture0,
CurrentHorizontalResolution0, CurrentVerticalResolution0,VideoModeDescription0
from @convertTab cnvt join v_R_System syst
right join v_GS_VIDEO_CONTROLLER on syst.ResourceID = v_GS_VIDEO_CONTROLLER.ResourceID
on cnvt.ResourceID = syst.ResourceID
---------------------------------------------------------------------------------------------------
FYI, SQL 2016 has STRING_SPLIT, so if you're using that, here's a fast query that avoids all this cursor business:
ReplyDeleteSELECT
MON.ResourceID,
MON.UserFriendlyName0,
CONV_FN.VAL AS UserFriendlyNameConverted,
MON.ManufacturerName0 AS [Make],
CONV_MAKE.VAL AS MakeConverted,
MON.ProductCodeID0 AS [ProductCode],
MON.SerialNumberID0 AS [SerNum],
CONV_SN.VAL AS SerNumConverted,
MON.YearOfManufacture0 AS [YearOfManufacture],
MON.WeekOfManufacture0 AS [WeekOfManufacture]
FROM v_GS_WMIMONITORID MON
CROSS APPLY ( SELECT
CASE
WHEN UserFriendlyName0 LIKE '%,%'
THEN (SELECT CHAR([value]) FROM STRING_SPLIT(UserFriendlyName0,',') SPLT WHERE [value] > 20 FOR XML PATH(''),TYPE).value('.','varchar(max)')
ELSE UserFriendlyName0
END AS VAL) CONV_FN
CROSS APPLY ( SELECT
CASE
WHEN MON.ManufacturerName0 LIKE '%,%'
THEN (SELECT CHAR([value]) FROM STRING_SPLIT(MON.ManufacturerName0,',') SPLT WHERE [value] > 20 FOR XML PATH(''),TYPE).value('.','varchar(max)')
ELSE MON.ManufacturerName0
END AS VAL) CONV_MAKE
CROSS APPLY ( SELECT
CASE
WHEN MON.SerialNumberID0 LIKE '%,%'
THEN (SELECT CHAR([value]) FROM STRING_SPLIT(MON.SerialNumberID0,',') SPLT WHERE [value] > 20 FOR XML PATH(''),TYPE).value('.','varchar(max)')
ELSE MON.SerialNumberID0
END AS VAL) CONV_SN
And, if you don't have SQL 2016 yet...get it!!! Or this query will use a kind of fake numbers/tally table to split the character values and FOR XML to re-aggregate the characters:
ReplyDelete;WITH n AS
(
SELECT
NUMBER = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM sys.all_objects AS s1, sys.all_objects AS s2
)
SELECT
MON.ResourceID,
MON.UserFriendlyName0,
CONV_FN.VAL AS UserFriendlyNameConverted,
MON.ManufacturerName0 AS [Make],
CONV_MAKE.VAL AS MakeConverted,
MON.ProductCodeID0 AS [ProductCode],
MON.SerialNumberID0 AS [SerNum],
CONV_SN.VAL AS SerNumConverted,
MON.YearOfManufacture0 AS [YearOfManufacture],
MON.WeekOfManufacture0 AS [WeekOfManufacture]
FROM v_GS_WMIMONITORID MON
CROSS APPLY ( SELECT
CASE
WHEN UserFriendlyName0 LIKE '%,%'
THEN (SELECT CHAR([value]) FROM (SELECT [Value] = SUBSTRING(MON.UserFriendlyName0, [Number],CHARINDEX(',', MON.UserFriendlyName0 + ',', [Number]) - [Number]) FROM n WHERE Number <= LEN(MON.UserFriendlyName0) AND SUBSTRING(',' + MON.UserFriendlyName0, [Number], 1) = ',') SPLT WHERE [value] > 20 FOR XML PATH(''),TYPE).value('.','varchar(max)')
ELSE UserFriendlyName0
END AS VAL) CONV_FN
CROSS APPLY ( SELECT
CASE
WHEN MON.ManufacturerName0 LIKE '%,%'
THEN (SELECT CHAR([value]) FROM (SELECT [Value] = SUBSTRING(MON.ManufacturerName0, [Number],CHARINDEX(',', MON.ManufacturerName0 + ',', [Number]) - [Number]) FROM n WHERE Number <= LEN(MON.ManufacturerName0) AND SUBSTRING(',' + MON.ManufacturerName0, [Number], 1) = ',') SPLT WHERE [value] > 20 FOR XML PATH(''),TYPE).value('.','varchar(max)')
ELSE MON.ManufacturerName0
END AS VAL) CONV_MAKE
CROSS APPLY ( SELECT
CASE
WHEN MON.SerialNumberID0 LIKE '%,%'
THEN (SELECT CHAR([value]) FROM (SELECT [Value] = SUBSTRING(MON.SerialNumberID0, [Number],CHARINDEX(',', MON.SerialNumberID0 + ',', [Number]) - [Number]) FROM n WHERE Number <= LEN(MON.SerialNumberID0) AND SUBSTRING(',' + MON.SerialNumberID0, [Number], 1) = ',') SPLT WHERE [value] > 20 FOR XML PATH(''),TYPE).value('.','varchar(max)')
ELSE MON.SerialNumberID0
END AS VAL) CONV_SN
That's pretty nifty, I would try your one for SQL 2016 but we aren't on that one yet. Though I did read about that function when I was researching and found the query I used in this post.
DeleteThis comment has been removed by a blog administrator.
ReplyDelete