ConfigMgr 2007: How to inventory mapped drives

I was asked a few days ago if ConfigMgr or SMS could inventory mapped drives, and while the answer is yes we don't do it by default. In effect we report the logical disk but not mapped drives.

In order to inventory mapped drives we first need to extend the sms_def.mof.  Mapped drives are in the user context so we need to gather this information from every user.  We also need a repository to collect this information; this would be a class in WMI.

So here is how we accomplish this. Add the following lines to the end of the SMS_def.mof:

//======================================================================================

// Mapped Drives Reporting

//

// Note: The class is created using a advertised vbscript (mapdrives.vbs)

//======================================================================================

#pragma namespace("\\\\.\\root\\CIMV2\\SMS")

#pragma deleteclass("CX_mappeddrives", NOFAIL)

[

SMS_Report(TRUE),

SMS_Group_Name("CX Mapped Drives"),

SMS_Class_ID("CX_mappeddrives"),

Namespace("\\\\\\\\.\\\\root\\\\cimv2")]

class CX_mappeddrives : SMS_Class_Template

{

[SMS_Report(TRUE), Key]

string user;

[SMS_Report(TRUE), key]

string Letter;

[SMS_Report(TRUE), Key]

string Path;

};

// <:[-<>>>>>>>>>>>>>>>>>>>>>>>>>>END>>-Mapped drives Reporting-<<END<<<<<<<<<<<<<<<<<<<<<<<>-]:>

This will extend the mof and create the necessary stored procedures and tables in the SMS database. After compiling the mof on the site server restart the SMS_executive and the component manager. We will need to compile this sms_def.mof on the clients as well to extend WMI and create the repository to store the mapped drive information. You can do this by a logon script or advertisement.

We now need to gather the mapped drive information. Here is the script to do so. I named it mapdrives.vbs

' This code is provided "as-is" and not supported by Microsoft

'

'

option explicit

on error resume next

Dim wbemCimtypeSint16

Dim wbemCimtypeSint32

Dim wbemCimtypeReal32

Dim wbemCimtypeReal64

Dim wbemCimtypeString

Dim wbemCimtypeBoolean

Dim wbemCimtypeObject

Dim wbemCimtypeSint8

Dim wbemCimtypeUint8

Dim wbemCimtypeUint16

Dim wbemCimtypeUint32

Dim wbemCimtypeSint64

Dim wbemCimtypeUint64

Dim wbemCimtypeDateTime

Dim wbemCimtypeReference

Dim wbemCimtypeChar16

wbemCimtypeSint16 = 2

wbemCimtypeSint32 = 3

wbemCimtypeReal32 = 4

wbemCimtypeReal64 = 5

wbemCimtypeString = 8

wbemCimtypeBoolean = 11

wbemCimtypeObject = 13

wbemCimtypeSint8 = 16

wbemCimtypeUint8 = 17

wbemCimtypeUint16 = 18

wbemCimtypeUint32 = 19

wbemCimtypeSint64 = 20

wbemCimtypeUint64 = 21

wbemCimtypeDateTime = 101

wbemCimtypeReference = 102

wbemCimtypeChar16 = 103

Dim oLocation, oServices, oInstances, oObject, oDataObject, oNewObject, oRptObject

Set oLocation = CreateObject("WbemScripting.SWbemLocator")

'Remove class

Set oServices = oLocation.ConnectServer(, "root\cimv2")

set oNewObject = oServices.Get("CX_mappeddrives")

oNewObject.Delete_

'Create data class structure

Set oServices = oLocation.ConnectServer(, "root\cimv2")

Set oDataObject = oServices.Get

oDataObject.Path_.Class = "CX_mappeddrives"

oDataObject.Properties_.add "Letter", wbemCimtypeString

oDataObject.Properties_.add "Path", wbemCimtypeString

oDataObject.Properties_.add "user", wbemCimtypeString

oDataObject.Properties_("Letter").Qualifiers_.add "key", True

oDataObject.Properties_("Path").Qualifiers_.add "key", True

oDataObject.Properties_("user").Qualifiers_.add "key", True

oDataObject.Put_

'Add Instances to data class

Set oServices = oLocation.ConnectServer(, "root\cimv2")

Dim sComputerName, sUsername, sQuery

Set oInstances = oServices.ExecQuery("SELECT UserName FROM Win32_ComputerSystem")

for each oObject in oInstances

sUserName = oObject.UserName

next

sQuery = "select * from win32_MappedLogicalDisk"

Set oInstances = oServices.ExecQuery(sQuery)

for each oObject in oInstances

Set oNewObject = oServices.Get("CX_mappeddrives").SpawnInstance_

oNewObject.Letter = oObject.DeviceID

oNewObject.Path = oObject.ProviderName

oNewObject.user = sUserName

oNewObject.Put_

next

'--------------------------------- FUNCTIONS -----------------------------------

Function ParseComp(Stg,Pat)

Dim tmpCS, p, q

tmpCS = ""

p = 1

Do while p < len(Stg)

if mid(Stg,p,len(Pat)) = Pat Then

q = p + len(Pat) + 1

Do while mid(Stg,q,1) <> chr(34) and q < len(Stg)

tmpCS = tmpCS + mid(Stg,q,1)

q = q + 1

Loop

Exit do

Else

p = p + 1

end if

Loop

ParseComp = tmpCS

End Function

Now this script can be executed through a logon script.

A few gotchas on the whole process is that the user has to have write access to root/CIMV2 class.  We can over come this by explicitly adding the domain user group to CIMV2 using the MMC or you can use a free tool called wmisecurity.exe(https://www.codeproject.com/KB/system/WmiSecurity.aspx )

Once the script is run the class would get populated with the letter and path and user who ran the script.

clip_image002

Then when hardware inventory is run it will populate information in the database that can be used later to create reports. To verify that it worked fine verify Resource explorer for one machine. It will have a new class named cx_mappeddrives:

clip_image004

Here is a sample report you can use to view the data:

select v_R_System.Name0,v_GS_Cx_Mapped_Drives0.Letter0, v_GS_Cx_Mapped_Drives0.Path0, v_GS_Cx_Mapped_Drives0.user0 from v_R_System inner join v_GS_Cx_Mapped_Drives0 on v_GS_Cx_Mapped_Drives0.ResourceId = v_R_System.ResourceId where v_GS_Cx_Mapped_Drives0.Letter0 like '%' and v_GS_Cx_Mapped_Drives0.Path0 like '%' and v_GS_Cx_Mapped_Drives0.user0 like '%'

The report will look like this:

clip_image006

A good use of this script is to determine a valid drive letter for a new server share or what are your clients mapping to. 

I hope these steps help to gather information and special thanks to Jason Alanis for creating the vbs script.

Alvin Morales - Senior Support Engineer