The Settings within the MDT Database cover already a wide area of possibilities during a Deployment. But sooner or later you will probably reach a point, where you are in the need of adding or processing additional information. Think about Static IP Address assignment or prestaging a specific CollectionID for Deployment via SCCM, etc. There are probably a lot of things you might want to have. At least I reached this point quite soon during our deployments and started adding a new table for this and a new table for that and it was getting chaotic. Sure this is a way to secure your job but it could hit yourself if you try to understand or change this half a year later :-)
In this post, I would like to point out a more generic way how to add any kind of setting and explain how you can set and get these during your deployments.
One of the first guidelines which applies probably to everything which comes from somebody else: Don't change anything which might get updated in the future. So it's generally a bad idea to change any of the existing tables or views within your MDT Installation as you might run into problems on your next update. And even if I think the current Database design could have been done a bit different for easier consistency we will also stick to this schema.
So, one possible solution for this is a new table which will contain new settings, generic stored procedures, which will read and write any value, no matter what it contains and a view which will simply show all values. I will demonstrate this on a couple of custom settings I had to implement in our deployments. One requirement was the possibility to choose from a list of different deployment Task Sequences on-the-fly during Boot up but also being able to specify this in advance as a part of the prestaging process of computers. We solved this by simply adding two settings. One "CollectionID" which could contain a CollectionID (each OS Task Sequence is advertised to one Collection as mandatory) and a "Prestaged" value. If the CollectionID contains a value the Computer would be added automatically to the specified Collection. If not it would prompt a wizard where you then would get a list to choose from. And if the Prestaged Setting was set to YES we empty both Settings after the process. This was giving us the possibility to prestage a computer with a specific image without limiting future deployments, setting some computers fix to a specific image (e.g. Training computers) and still stay flexible enough to choose from a list if necessary (testing, etc). OK, enough wasted time on things you are not interested in :-) Let's get to the implementation.
First thing we need is a new table to store this information. We simply call this "CustomSettings" according to the Original "Settings" table. And while we are at it we also add a couple of views like "ComputerCustomSettings", "LocationCustomSettings", etc. Find an example sql script for this at the end of the post. I will skip the sql code for this as creating a table or view really doesn't look sexy.
However, we need an easy method to change/set and read these custom settings. And actually we have something similar already. You might remember the post about Set or Get a single Setting from MDT Database. We just take and change them accordingly and I hope you don't mind if I don't repeat this again. Find the necessary code attached. In the mentioned post I also showed how to create a webservice which could run this stored procedure. So this time we now concentrate a bit on how to use this (as the webservice for this CustomSettings is already part of the quite large webservice from my last post). I will do this with a simple example which you could use in the preexection hook. We want to check the MDT Database if a SCCM collection has been configured for the actual computer. If so, the computer shall be added to the collection. It's not a complete example. It will work but miss some parts like what do you want to do if no collection has been prestaged. So take it as a start for further testing.
What you need is a quite simple CustomSettings.ini
[Settings]
Priority= SetValues, ExecUserExit, AddToCollection
Properties=Type
[SetValues]
Type=Computer
[ExecUserExit]
UserExit=userExit.vbs
[GetMDTID]
WebService=http://YourServer/DeploymentWebservice/mdt.asmx/GetComputerID
Parameters=SerialNumber, AssetTag, MacAddress, UUID
[GetCustomSetting]
WebService=http://YourServer/DeploymentWebservice/mdt.asmx/GetCustomSetting
Parameters=MDTID, Type, Setting
[GetAssignedSite]
WebService=http://YourServer/DeploymentWebservice/SCCM.asmx/GetAssignedSite
Parameters=SiteIP,SiteSubnet
SiteIP=ipAddress
SiteSubnet=ipSubnet
[DoAddToCollection]
WebService=http://YourServer/DeploymentWebservice/SCCM.asmx/AddComputerToCollection
Parameters=MacAddress, UUID, CollectionID, ComputerName, AssignedSite
AssignedSite=siteCode
What does it do? It will first run a UserExit.vbs script. A UserExit script can be used to have custom code/rule processing within the standard gather step of MDT. (Please read Understanding BDD rule processing from Ben Hunter as one of the best sources about Rule Processing in general. It applies to BDD but almost everything is still valid in MDT.) The UserExit.vbs will call a couple of webservices and process the results to set some Environment variables. You probably wonder why we have an entry "AddToCollection" in Priority but no corresponding section. This is to show you a different way of dynamic Rule Processing. If we have a custom setting "CollectionID" configured with a value, the UserExit script will simply set the value of "AddToCollection" to "DoAddToCollection". So if it doesn't has a value it can't process anything as the section "AddToCollection" doesn't exist and if it has changed it will match the "DoAddToCollection" section and execute this webservice. Yes, this is not the best way to do it but I hope you are interested to see different ways to achieve the same result.
Here a snippet from the UserExit.vbs. Find the complete script attached:
Function UserExit(sType, sWhen, sDetail, bSkip)
' Get the necessary values for further processing
oLogging.CreateEntry "Setting values for UserExit processing.", LogTypeInfo
' Get Computer ID
oEnvironment.Item("MDTID") = GetComputerID
' Get collectionID
oEnvironment.Item("CollectionID") = GetCustomSetting ("CollectionID")
' Check if computer has been prestaged
sPrestaged = GetCustomSetting("Prestaged")
If sPrestaged = "YES" Then
oEnvironment.Item("Prestaged") = GetPrestagedStatus
End If
' If CollectionID has been configured, add computer to collection
If oEnvironment.Item("CollectionID") <> "" Then
' Get the SiteCode
sAssignedSite = GetAssignedSite
oEnvironment.Item("AssignedSite") = sAssignedSite
' Cameron specific. All MDT Collections are in CCC
oEnvironment.Item("siteCode") = "CCC"
If sAssignedSite = "" then
oLogging.CreateEntry "Unable to determine assigned site using any available IP addresses", LogTypeWarning
Else
oLogging.CreateEntry "Client is assigned to site " & sAssignedSite, LogTypeInfo
oLogging.CreateEntry "Will add Computer to Collection " & oEnvironment.Item("CollectionID"), LogTypeInfo
oEnvironment.Item("AddToCollection") = "DoAddToCollection"
End if
End If
UserExit = Success
End Function
Function GetComputerID
Dim oService
Dim oXML
Dim iMDTID
' Set Default Value
iMDTID = 0
' Create the web service instance
Set oService = new WebService
' oService.IniFile = "SCCM_Bootstrap.ini"
oService.SectionName = "GetMDTID"
' Make the web service call
Set oXML = oService.Query
If oXML is Nothing Then
oLogging.CreateEntry "Unable to call GetMDTID web service.", LogTypeWarning
Else
iMDTID = oXML.SelectSingleNode("int").Text
oLogging.CreateEntry "MDTID is " & iMDTID, LogTypeInfo
'GetComputerID = iMDTID
End If
GetComputerID = iMDTID
End Function
Function GetCustomSetting (Setting)
Dim oService
Dim oXML
Dim sResult
' Set necessary setting for Webservice Call
oEnvironment.Item("Setting") = sSetting
' Create the web service instance
Set oService = new WebService
' oService.IniFile = "SCCM_Bootstrap.ini"
oService.SectionName = "GetCustomSetting"
' Make the web service call
Set oXML = oService.Query
If oXML is Nothing then
oLogging.CreateEntry "Unable to call GetCustomSetting web service.", LogTypeWarning
Else
sResult = UCase(oXML.SelectSingleNode("string").Text)
oLogging.CreateEntry "value for " & Setting & " is " & sResult, LogTypeInfo
End if
GetCustomSetting = sResult
End Function
If you are using this within the MediaHook and would like to use it with a SCCM_Bootstrap.ini just uncomment the ' oService.IniFile = "SCCM_Bootstrap.ini" lines.
Find attached the necessary sql scripts to create a sample CustomSettings table (with the CollectionID and Prestaged column as example) some corresponding views (which you need to update if you change the CustomSettings Table) and the Stored Procedures. And for sure all this will also be added to my past two posts Get access to the MDT Database and A Webservice for OSD and MDT Deployments. on the next update. (Don't want to publish new versions daily :-) )
And as always, use it at your own risk.
Download all files used in this post.