Useful Links for Configuring MDT

Enable video resolution auto-detection

To have screen resolution autodetection on, set the screen resolution to a really low value in CustomSettings.ini. This will force Windows setup to autodetect the resolution:



Customizing IT Organization

In the [Default] section of CustomSettings.ini, add _SMSTSOrgName.

Set the Computer Name to the Serial Number

Set OSDComputername=%SerialNumber% in CustomSettings.ini.

Skip “Specify credentials for connecting to network shares”

Set them in Bootstrap.ini:




Useful links for configuring an IBM x3650 M4 (7915 AC1) with RAID 10 for MDT and multicasting

IBM MegaRAID BIOS Config Utility RAID-10 Configuration

MDT – How I build my reference images (User Question)

Multicasting with MDT

Finding the source tables/views used in query-based Collection membership rules

We have workstations consolidating to one domain.  Query based rules that might reference Organization Units and/or Active Directory groups will have to be changed.  I wanted a query that would list out the tables and views used in query-based membership rules.

CREATE TABLE #SourceTables (
, QueryID INT
, SourceTable NVARCHAR(MAX)
, OriginalQuery NVARCHAR(MAX)
 @CollectionID NVARCHAR(MAX)
, @QueryID INT
, @QueryExpression NVARCHAR(MAX)
, @OriginalQuery NVARCHAR(MAX)
, @SourceTable NVARCHAR(MAX)
, @TrimPos INT
DECLARE CollectionRuleQuery CURSOR FOR
SELECT c.CollectionID, c.[Name], RuleName, QueryID, QueryExpression FROM v_CollectionRuleQuery crq
INNER JOIN v_Collection c ON c.CollectionID = crq.CollectionID WHERE c.CollectionID NOT LIKE 'SMS%'
OPEN CollectionRuleQuery
FETCH NEXT FROM CollectionRuleQuery INTO @CollectionID, @Name, @RuleName, @QueryID, @QueryExpression
SELECT @OriginalQuery = @QueryExpression
-- table or view name will be preceded by either " from " or " join "
WHILE CHARINDEX (' from ', @QueryExpression) > 0 OR CHARINDEX (' join ', @QueryExpression) > 0
-- We know at this point either a "from" or "join" exists in the string
-- So move the start of @QueryExpression to first character of the table or view name
-- If there's no "join", it must be "from"
IF CHARINDEX (' join ', @QueryExpression) = 0
SELECT @QueryExpression = SUBSTRING (@QueryExpression, CHARINDEX (' from ', @QueryExpression) + 6, LEN (@QueryExpression));
-- If there's no "from", it must be "join"
ELSE IF CHARINDEX (' from ', @QueryExpression) = 0
SELECT @QueryExpression = SUBSTRING (@QueryExpression, CHARINDEX (' join ', @QueryExpression) + 6, LEN (@QueryExpression));
-- If both exist, find out what one comes first
ELSE IF CHARINDEX (' from ', @QueryExpression) < CHARINDEX (' join ', @QueryExpression)
SELECT @QueryExpression = SUBSTRING (@QueryExpression, CHARINDEX (' from ', @QueryExpression) + 6, LEN (@QueryExpression));
ELSE SELECT @QueryExpression = SUBSTRING (@QueryExpression, CHARINDEX (' join ', @QueryExpression) + 6, LEN (@QueryExpression));
-- To find the end of the table or view name, there are four possibilities,
-- ends with space, open or close parenthesis, or the end of the string
-- also want to start at position 2, since there might be some leading parenthesis to ignore before the name begins
SELECT @TrimPos = PATINDEX ('%[ )(]%', SUBSTRING (@QueryExpression, 2, LEN (@QueryExpression))) + 1
SELECT @SourceTable = SUBSTRING (@QueryExpression, 1, @TrimPos - 1)
-- Eliminate any lingering opening parenthesis that might preceed the table or view name
IF @SourceTable LIKE '(%' SELECT @SourceTable = SUBSTRING (@SourceTable, 2, LEN (@SourceTable))
INSERT INTO #SourceTables SELECT @CollectionID, @Name, @RuleName, @QueryID, @SourceTable, @OriginalQuery;
SELECT @QueryExpression = SUBSTRING (@QueryExpression, @TrimPos, LEN (@QueryExpression));
FETCH NEXT FROM CollectionRuleQuery INTO @CollectionID, @Name, @RuleName, @QueryID, @QueryExpression
CLOSE CollectionRuleQuery;
DEALLOCATE CollectionRuleQuery;
SELECT * FROM #SourceTables
DROP TABLE #SourceTables

This lists the collections, rule names, and the tables/views queried:
20180326 Collection Tables

Export Configuration Manager Status Messages

This uses the script provided at You don’t need to run this on the site server, just copy the *.dll files from the site server:

 Volume in drive C has no label.
 Volume Serial Number is FE80-1E2D

 Directory of C:\Users\Public\smsmsgs

03/23/2018  09:52 AM    <DIR>          .
03/23/2018  09:52 AM    <DIR>          ..
03/23/2018  09:36 AM             4,255 EnumerateStatusMessageStrings.ps1
               1 File(s)          4,255 bytes
               2 Dir(s)  317,884,436,480 bytes free

C:\Users\Public\smsmsgs>copy "\\server.domain\C$\Program Files\Microsoft Configuration Manager\bin\X64\system32\smsmsgs\*.dll"
\\server.domain\C$\Program Files\Microsoft Configuration Manager\bin\X64\system32\smsmsgs\climsgs.dll
\\server.domain\C$\Program Files\Microsoft Configuration Manager\bin\X64\system32\smsmsgs\provmsgs.dll
\\server.domain\C$\Program Files\Microsoft Configuration Manager\bin\X64\system32\smsmsgs\srvmsgs.dll
        3 file(s) copied.

C:\Users\Public\smsmsgs>powershell .\EnumerateStatusMessageStrings.ps1 .\climsgs.dll .\climsgs.csv

C:\Users\Public\smsmsgs>powershell .\EnumerateStatusMessageStrings.ps1 .\provmsgs.dll .\provmsgs.csv

C:\Users\Public\smsmsgs>powershell .\EnumerateStatusMessageStrings.ps1 .\srvmsgs.dll .\srvmsgs.csv

C:\Users\Public\smsmsgs>dir *.csv
 Volume in drive C has no label.
 Volume Serial Number is FE80-1E2D

 Directory of C:\Users\Public\smsmsgs

03/23/2018  09:53 AM            98,735 climsgs.csv
03/23/2018  09:53 AM            69,075 provmsgs.csv
03/23/2018  09:54 AM           467,264 srvmsgs.csv
               3 File(s)        635,074 bytes
               0 Dir(s)  317,884,821,504 bytes free


Then use Excel to import each csv to a new sheet.
Configuration Manager 1702 Status Messages

Tracking Software Inventory Flow in Configuration Manager

We’ve got clients that haven’t returned software inventory and I’ve been troubleshooting it; however, the logs on some of the clients look good, so I was wondering if there was an issue with the management points and/or the site server.
There’s an excellent article by Garth Jones about troubleshooting hardware inventory ( that I’ve used as a blueprint on tracking down software inventory.

More difficulties:
1 – Software inventory is so slow
2 – Some of the clients are NATed so it’s not always straightforward when looking at the IIS logs on the management point if the client actually uploaded the inventory (since we can’t search for IP Address)
3 – With 100,000 clients, mp_sinv.log rolls over so fast

First thing to look at after kicking off Software Inventory (I used Client Center to kick off a Full Inventory) is the InventoryAgent.log on the client. You can see that the software inventory successfully finished:
20180321 1 InventoryAgent

Additionally, you can also see the queries in the FileSystemFile.log (this log if from a different workstation, the first one went off line by the time I remembered to grab this log):
20180321 2 FileSystemFile

The last log to check on the client is the CCMMessaging.log. This one will show the management point to which the client uploaded the inventory. It should also show MESSAGE PAYLOAD TRANSFER COMPLETE with a Status of SUCCESS:
20180321 3 CCMMessaging

The next place to look is the IIS logs on the management point. Jones’ article uses the client’s IP Address to find the information in the log, we can’t do that due to NAT. I used the Msg ID from the CCMMessaging.log:
20180321 4 u_ex180320

This shows that the management point successfully received the file. The next file to check is the MP_Sinv.log file, also on the management point. This shows that the management point successfully processed the inventory, created a SIC file, and put it into it’s outbox for the management point file dispatch manager to pick up:
20180321 5 mp_sinv

Next, the mpfdm.log (also on the management point) shows the file was moved from the outbox to the site server’s inbox (once again, not the same client, but you get the idea):
20180322 MPFDM

The last file is the dataldr.log file on the site server. This will show that the inventory was processed for the client:
20180321 6 dataldr

If all goes well, you should be able to see this information in Resource Explorer:
20180321 7 Resource Explorer

Querying data with different XML Namespaces

Data looks like:
20180319 xml data

The default namespace is, but for the “File” element, it is

Give the namespace an alias (like desconfig) and then for each element in the tree, prefix it with the alias and a colon (i.e., “desconfig:”):

WITH XMLNAMESPACES ('' as desconfig,
, app.Description
, dt.CI_ID
, dt.SDMPackageDigest.value ('(/AppMgmtDigest/DeploymentType/Title)[1]', 'nvarchar(max)') [Title]
, dt.SDMPackageDigest.value ('(/AppMgmtDigest/DeploymentType/Installer/CustomData/EnhancedDetectionMethod/Settings/desconfig:File/desconfig:Path)[1]', 'nvarchar(max)') [FilePath]
from v_ConfigurationItems dt
INNER JOIN vSMS_CIRelation AS rel ON dt.CI_ID = rel.ToCIID
INNER JOIN fn_ListApplicationCIs_List(1033) AS app ON app.CI_ID = rel.FromCIID
dt.CIType_ID = 21 and
dt.IsLatest = 1 and
dt.SDMPackageDigest.value ('(/AppMgmtDigest/DeploymentType/Installer/CustomData/EnhancedDetectionMethod/Settings/desconfig:File/desconfig:Path)[1]', 'nvarchar(max)') is not null
order by [Title]