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

---------------------------------------------------------------------------------------------------

Comments

  1. FYI, SQL 2016 has STRING_SPLIT, so if you're using that, here's a fast query that avoids all this cursor business:

    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 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


    ReplyDelete
  2. 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:

    ;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

    ReplyDelete
    Replies
    1. 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.

      Delete
  3. This comment has been removed by a blog administrator.

    ReplyDelete

Post a Comment

Popular posts from this blog

Intune Hybrid - NDES Cert Issue

Stuck @ "Waiting for user logon"

Triggering a software update install via Powershell