CCMSetup: CcmSetup failed with error code 0x80070666

Getting a few computers failing to upgrade the client with the following in ccmsetup.log:

Installing file 'C:\WINDOWS\ccmsetup\vcredist_x64.exe' with options '/norestart /install /quiet /log %windir%\ccmsetup\logs\VCRedist_x64_Install.log'.
File 'C:\WINDOWS\ccmsetup\vcredist_x64.exe' returned failure exit code 1638. Fail the installation.
InstallFromManifest failed 0x80070666
Sending state '311'...
Updating MDM_ConfigSetting.ClientDeploymentErrorCode with value 2147944038
[5.00.9068.1012] Params to send '5.0.9068.1026 Deployment Error 0x80070666. Pre-req: vcredist_x64.exe'
<ClientDeploymentMessage ErrorCode="-2147023258"><Client Baseline="1" BaselineCookie="" Platform="2" Langs=""/><Packages><Package ID="{696F1234-7673-4E99-A0A6-511DB03A85A4}"/></Packages><Additional><SourceType Value="DP"/></Additional></ClientDeploymentMessage>
Raised pending client deployment state message.
UpgradeStatus: updating error code to 0x80070666
Sending state '301'...
Updating MDM_ConfigSetting.ClientDeploymentErrorCode with value 2147944038
Deleted file C:\WINDOWS\ccmsetup\ccmsetup.exe.download
Deleted file C:\WINDOWS\ccmsetup\ccmsetup.xml
Deleted file C:\WINDOWS\ccmsetup\client.msi
CcmSetup failed with error code 0x80070666

Checking VCRedist_x64_Install.log, is shows:

Error 0x80070666: Cannot install a product when a newer version is installed.

The version that ccmsetup is attempting to install is 14.28.29914 and when I check the client is shows a later version:

Microsoft Visual C++ 2015-2019 Redistributable (x64) - 14.29.30038

So why is ccmsetup trying to install an older client?

Looking further back in the ccmsetup.log it states it can’t find the upgrade code for vcredist_x64.exe in the MSI database:

Item 'x64/vcredist_x64.exe' is applicable. Detecting whether it exists.
Couldn't find a product with MSI upgrade code '{36F68A90-239C-34DF-B58C-64B30153CE35}' in the MSI database.
Item x64/vcredist_x64.exe has not been installed yet. Put to pending install list.

It also shows where it detects the x86 version just fine:

Item 'i386/vcredist_x86.exe' is applicable. Detecting whether it exists.
Upgrade code '{65E5BD06-6392-3027-8C26-853107D3CF1A}': product = '{E42108AD-89A2-4ECC-9206-B41EE965BD09}', installed = 1, version = 14.29.30038
Checking '{65E5BD06-6392-3027-8C26-853107D3CF1A}' version '14.29.30038' expecting >= '14.28.29914'.
Detected item 'i386/vcredist_x86.exe'

I figured I should try a repair first, so I logged onto the computer and clicked “Change” and then “Repair”:

But then it prompted me for the location of VC_redist.x64:

I tried the repair on the x86 version and that worked fine, so it looks like there might be something screwy with the x64 install…  I downloaded the latest version from here and installed it, and after a reboot ccmsetup ran successfully.

Where does Configuration Manager get the Windows 10/11 Version Value?

I briefly looked at this once before, but recently noticed some Versions missing, so I wanted to trace it back further to figure out why.

For example, I have several Windows 10 Enterprise workstations that have Build01 = 10.0.19043 and OSBranch01 = 1 in v_R_System:

But when I use my query to find the version, it returns NULL:

Other workstations with OSBranch01 = 0 do return data for Value:

To research this, I looked at where the dashboards under Software Library -> Windows Servicing gets their data.

Using SQL Profiler, I found that the data comes from calling the stored procedure spDashboardsGetChartData 6 times with different ChartGUIDs.

For instance, one call looks like this:

EXEC spDashboardsGetChartData @chartGuid=N'7ce4d25d-72f1-4277-8c83-d1f3a261db6e', @chartConfigData=N'<ChartConfigData><SiteID>SMS00001</SiteID></ChartConfigData>', @userSids=N'0123456789ABCDE0123456789ABCDE0123456789ABCDE0123456789A,0123456789ABCDE0123456789ABCDE0123456789ABCDE0123456789A'

The spDashboardsGetChartData uses the ChartGuid parameter to query the Console_DashboardCharts  table.  The table contains the names other stored procedures:

It then builds and executes a SQL statement using the stored procedure name returned.  Below I have a query that lists the 6 ChartGuids used:

select * from Console_DashboardCharts
where ChartGuid in (
'7ce4d25d-72f1-4277-8c83-d1f3a261db6e',
'b9c92f54-bdb0-4dab-aa07-3a502572e777',
'944baf10-bb43-4a60-ba7e-448a91d369c5',
'27b56a08-aaec-4884-aa43-8ab2f658a466',
'9e1d9f10-3aa3-4814-a7d0-a9ffc6556e38',
'182c09d5-5abc-4abe-956a-aeff6c42425f'
)
ChartGuidSqlHandler
B9C92F54-BDB0-4DAB-AA07-3A502572E777spGetWin10SetupDiagHistory
944BAF10-BB43-4A60-BA7E-448A91D369C5spGetWin10Dash
27B56A08-AAEC-4884-AA43-8AB2F658A466spGetWin10QualityUpdateVersions
9E1D9F10-3AA3-4814-A7D0-A9FFC6556E38spGetWin10LatestBuild
182C09D5-5ABC-4ABE-956A-AEFF6C42425FspGetWin11LatestBuild
7CE4D25D-72F1-4277-8C83-D1F3A261DB6EspGetWin10SetupDiagDeviceCounts

I’m just guessing here that the stored procedures return data for the following charts:

SqlHandlerChart
spGetWin10SetupDiagHistoryErrors Timeline
spGetWin10DashFeature Update Versions
spGetWin10QualityUpdateVersionsQuality Update Versions
spGetWin10LatestBuildWindows 10 Latest Feature Update
spGetWin11LatestBuildWindows 11 Latest Feature Update
spGetWin10SetupDiagDeviceCountsCollection Errors

From here, I dug into the spGetWin10Dash and spGetWin10LatestBuild stored procedures.  These procedures select data from the vSMS_WindowsServicingStates and vSMS_WindowsServicingLocalizedNames views, which in turn selects their data from the fn_GetWindowsServicingStates() and fn_GetWindowsServicingLocalizedNames() functions.  Finally, these functions get their data from the AdminUIContent table.  The functions execute the following in their queries:

fn_GetWindowsServicingStates()

SELECT CONVERT(XML, Data) FROM AdminUIContent WHERE Name = 'WindowsServicingStates.xml'

fn_GetWindowsServicingLocalizedNames()

SELECT CONVERT(XML, Data) FROM AdminUIContent WHERE Name = 'WindowsServicingLocalizedNames.xml'

The queries above return XML data, which is converted to rows in the functions.  An example of the results from the query used in the fn_GetWindowsServicingLocalizedNames() function:

OK, so let’s look at the data in the AdminUIContent for WindowsServicingStates.  You can query this data by executing the following:

DECLARE @doc XML = (SELECT CONVERT(XML, Data) FROM AdminUIContent WHERE Name = 'WindowsServicingStates.xml');
SELECT
  ServicingState.value('@Name', 'NVARCHAR(128)') AS Name,
  ServicingState.value('@Branch', 'NVARCHAR(32)') AS Branch,
  ServicingState.value('@Build', 'NVARCHAR(32)') AS Build,
  ServicingState.value('@State', 'TINYINT') AS State
FROM @doc.nodes('/WindowsServicingStates/WindowsServicingState') ServicingStates(ServicingState)

Specifically, for Build 10.0.19043:

There is no row for Branch = 1, that’s why.

To figure out where the data in the AdminUIContent table comes from, I searched through the log files and found this in the dmpdownloader.log file:

Redirected to URL https://configmgrbits.azureedge.net/adminuicontent/ConfigMgr.AdminUIContent.cab

I downloaded that file, and sure enough, there is no entry in the WindowsServicingStates.xml for Build = 10.0.19043 and Branch = 1.

Now I know why it’s missing.  Maybe Microsoft will update the WindowsServicingStates.xml?  Or maybe there’s some reason it’s left off?  I don’t know.

ConfigMgr: Building a report for Application Group deployment statuses

Haven’t been able to find any built-in reports for the deployment statuses of Application Groups, so I built one.

The report works like this… first, select the Application Group:

Then the collection(s):

View Report generates the following:

Datasets

ApplicationGroup DataSet

select distinct SoftwareName from v_DeploymentSummary
where FeatureType = 12
order by 1

CollectionName DataSet

select CollectionName from v_DeploymentSummary
where FeatureType = 12 and SoftwareName = @SoftwareName
order by 1

Results DataSet

declare @LocaleID int = (select LocaleID from vSMSData)

select
ad.AppGroupName
, ad.CollectionName
, ds.DeploymentTime
, ds.EnforcementDeadline
, case ds.[Enabled]
when 1 then 'True'
when 0 then 'False'
end [Enabled]
, ad.UserName
, ad.MachineName
, CONVERT (NVARCHAR, DATEADD (HH, DATEDIFF (hh, GETUTCDATE (), GETDATE ()), cdr.LastActiveTime), 22) LastActiveTime
, cdr.Domain
, scum.TopConsoleUser0
, case ds.DeploymentIntent
when 1 then 'Required'
when 2 then 'Available'
when 3 then 'Simulate'
end DeploymentIntent
, case ad.StatusType
when 1 then 'Compliant'
when 2 then 'In Progress'
when 4 then 'Unknown'
when 5 then 'Error'
end [Status]
from fn_AppGroupDeploymentAssetDetails (@LocaleID) ad
inner join (
select AssignmentID, DeploymentIntent, [Enabled], DeploymentTime, EnforcementDeadline
from v_DeploymentSummary where SoftwareName = @SoftwareName and CollectionName in (@CollectionName)
) ds on ds.AssignmentID = ad.AssignmentID
inner join v_CombinedDeviceResources cdr on cdr.MachineID = ad.MachineID
left join v_GS_SYSTEM_CONSOLE_USAGE_MAXGROUP scum on scum.ResourceID = ad.MachineID
order by
ad.CollectionName
, ad.MachineName

Parameters

SoftwareName Parameter

CollectionName Parameter