Path Registry Value Type (Client Core Health)
The Tanium Client Core Health sensor can return this on Windows endpoints:
The machine's system PATH is stored in the registry with the wrong value type. Everything else on the machine usually looks normal, so treat it as a cleanup item, not an outage. This page explains the error, how to find the affected machines in Tanium, and a package that fixes the value type without touching the data.
The same sensor returns other messages too. The PowerShell execution test error and Other messages from this sensor cover them, including a small package to check and repair WMI.
Test status
Fix-PathRegType.ps1 was tested on Windows 11 with Windows PowerShell 5.1 against a scratch registry key, run through cmd.exe the same way a Tanium package runs it. See Test results. The sensor behavior described on this page comes from reading the sensor's script. Repair-WmiHealth.ps1 was tested the same way, with the salvage step stubbed out. Neither package has been run through a Tanium action yet. Use Reproduce it in a lab and test on one machine before deploying wider.
What the error means
The system PATH lives in this registry value:
On a normal Windows install, its type is REG_EXPAND_SZ. That type tells Windows to expand variables such as %SystemRoot% into real paths such as C:\Windows.
On the affected machines the value has been rewritten as REG_SZ, a plain string. The entries can still contain %SystemRoot%, but nothing marks them as variables that need expanding.
The sensor only reports this error when both of these are true:
- The Path value is not
REG_EXPAND_SZ. - The Path data contains a
%.
A REG_SZ Path with no variables in it is not flagged. The fix script below converts any REG_SZ Path anyway, since REG_EXPAND_SZ is the Windows default and the conversion does not change the data.
I have not confirmed what changes the value. Scripts and installers that rewrite PATH without setting the value type are the usual suspects.
Find the affected machines
Run these in Interact, in the question bar.
All machines with the error:
Get Computer Name and Tanium Client Core Health from all machines with Tanium Client Core Health contains "REG_EXPAND_SZ"
One machine, for example after running the fix:
No direct or remote access to the endpoint is needed for either question.
Why the fix is written the way it is
The obvious fix is to read PATH with Get-ItemProperty, delete the value, and recreate it as ExpandString. The script avoids that for two reasons.
Get-ItemProperty expands the value when it reads it. On a healthy machine it returns C:\WINDOWS\system32, not %SystemRoot%\system32. Writing that back would replace every variable with a hardcoded path. The script reads the raw value with the .NET registry API and the DoNotExpandEnvironmentNames option instead.
Deleting and recreating leaves a gap. If the recreate step fails, the machine has no system PATH at all. The script overwrites the value in place with one call, changing only the type.
The script also:
- Leaves machines alone when PATH is already
REG_EXPAND_SZ. - Refuses to write when PATH is missing, empty, or a type other than
REG_SZ. - Exports the whole
Environmentkey toC:\Windows\Temp\Environment_Path_backup.regbefore writing, and stops if the export fails. - Reads the value back after writing and confirms the type is
REG_EXPAND_SZand the data did not change.
HKLM\SYSTEM is not redirected for 32-bit processes, so the script gives the same result whether the Tanium client starts 32-bit or 64-bit PowerShell.
Exit codes
| Exit code | Meaning |
|---|---|
0 |
PATH was converted to REG_EXPAND_SZ, or it already was. |
1 |
The write or the check after the write failed. Run the rollback package. |
2 |
The backup failed. Nothing was changed. |
3 |
PATH is missing, empty, or an unexpected type. Nothing was changed. |
Requirements
- Windows endpoints with Windows PowerShell 5.1.
- A Tanium account with permission to create packages in a content set and deploy actions to the target computers.
Create the package
Menu labels can differ slightly between Tanium versions.
- Save the script at the bottom of this page as
Fix-PathRegType.ps1. - In the Tanium Console, go to Administration > Content > Packages.
- Click Create Package.
- Fill in the fields:
- Package Display Name:
Fix Path Registry Value Type(add your team's prefix if you use one). - Content Set: the content set your team uses for custom content.
- Command:
- Command Timeout:
5minutes. The script normally finishes in a few seconds.
- Package Display Name:
- Under Files, click Add, choose Local File, and upload
Fix-PathRegType.ps1. - Click Save.
The package has no parameters.
Deploy the package
Start with one machine.
- In Interact, ask:
- Select one computer in the results grid.
- Click Deploy Action.
- In Deployment Package, search for and select
Fix Path Registry Value Type. - Under the schedule, leave it as a one-time action.
- Click Show preview to continue, review the target, then click Deploy Action.
- When the action completes, ask the single-machine question from Find the affected machines for that computer. If the result has not changed, wait a few minutes and ask again. Tanium can return a cached sensor result until it ages out.
- Once that machine reports healthy, repeat steps 1 through 6 with the rest of the computers selected.
The script skips machines that are already correct, so targeting a broad group is safe.
After the fix
The registry change takes effect right away, but processes that were already running keep the environment they started with. Services keep it until the machine reboots. Let the machines reboot in their normal maintenance window instead of forcing one.
View the results
- Open the action from Administration > Actions > Action History.
- Select an endpoint.
- Open its action log. The script output appears between the
Command Lineline and theCompletedline.
A converted machine:
2026-10-13 16:08:33 [INFO] Current type: String
2026-10-13 16:08:33 [INFO] Path has 4 entries. Contains variables: True
2026-10-13 16:08:33 [INFO] Backup saved: C:\Windows\Temp\Environment_Path_backup.reg
2026-10-13 16:08:33 [INFO] Converted Path from REG_SZ to REG_EXPAND_SZ. Data unchanged.
2026-10-13 16:08:33 [INFO] Running processes keep their old environment until they restart or the machine reboots.
A machine that was already correct:
2026-10-13 16:08:34 [INFO] Current type: ExpandString
2026-10-13 16:08:34 [INFO] Path is already REG_EXPAND_SZ. Nothing to do.
For many endpoints, ask a question with the built-in Tanium Action Log sensor, using the action ID from the top of the log:
Roll back
Rollback is a second package with no files. It imports the backup the fix saved on each endpoint.
- In Administration > Content > Packages, click Create Package.
- Fill in the fields:
- Package Display Name:
Rollback Path Registry Value Type - Content Set: the same content set as the fix.
- Command:
- Command Timeout:
5minutes.
- Package Display Name:
- Click Save.
- Deploy it only to the machines you want to roll back, then let them reboot in the normal maintenance window.
The import restores every value in the Environment key to what it was when the backup was taken, not only Path. If anything else in that key changed after the fix ran, the import reverts it too.
The PowerShell execution test error
The same sensor can also return:
Unable to perform PowerShell execution test, please ensure the latest Default Content tools are installed.
Despite the wording, this is not a PowerShell problem. Before the sensor runs its PowerShell test, it checks for this file in the Tanium Client folder:
If the file is missing, the sensor reports this message and skips the test. It never starts PowerShell. Confirm the file is missing with:
Get Computer Name and File Exists[C:\Program Files (x86)\Tanium\Tanium Client\Tools\StdUtils\tanium-clm-test.ps1] from all machines with Tanium Client Core Health contains "PowerShell execution test"
That path assumes the default install folder. The sensor finds the client folder from the TANIUM_CLIENT_ROOT environment variable, or from the Path value under HKLM\SOFTWARE\Tanium\Tanium Client (or HKLM\SOFTWARE\WOW6432Node\Tanium\Tanium Client). Adjust the path if your clients are installed somewhere else.
If the file is missing, get the Standard Utilities tools redistributed to that endpoint. In Administration > Content > Packages, search for Standard Utilities to find the package that distributes them. In most environments a scheduled action already does this, so also check why it did not reach the machine.
If the file is present, the sensor runs it and reports a different message when PowerShell fails or is not in FullLanguage mode. See the next section.
Other messages from this sensor
The sensor runs a series of checks and prints one line for each check that fails. It prints Healthy only when every check passes. One machine can return several lines, so the counts in a question's results are lines, not machines. Add Computer Name to see which machine returned what:
Get Computer Name and Tanium Client Core Health from all machines with Tanium Client Core Health does not contain "Healthy"
If the sensor cannot create its basic objects (WScript.Shell, FileSystemObject, or the WMI registry provider), it prints that one error and stops. The rest of the checks never run on that machine, so fix that error first and ask again.
| Message | What failed | What to do |
|---|---|---|
Error: <number>. Cannot create StdRegProv object. |
The WMI registry provider in root\default could not be loaded |
Check and repair WMI |
Error: Cannot properly access registry via WMI |
A registry read through WMI failed | Check and repair WMI |
Error: <number>. Cannot create WMI object. / Cannot query WMI. |
WMI root\cimv2 could not be opened or queried |
Check and repair WMI |
Error: WMI cannot retrieve a basic property |
Select ProductType from Win32_OperatingSystem returned nothing |
Check and repair WMI |
Error: Path is missing Windows\system32 directory (or Wbem) |
The PATH the Tanium Client is running with does not include those folders | Fix the system Path, then restart the Tanium Client service or reboot. The client keeps the PATH it started with |
Tanium Signing Certificate <years> Not Found |
That Tanium code-signing certificate is not in the machine's Trusted Publishers store | Reinstall the Tanium signing certificates. Signed Tanium PowerShell content can fail where AllSigned or WDAC is enforced |
Unable to execute PowerShell from the Tanium Client / PowerShell command failed with exit code <n> / Unable to determine Powershell execution status |
The test script ran but did not report success | Check whether antivirus or application control is blocking PowerShell started by the Tanium Client |
PowerShell is not operating in the required FullLanguage mode. |
PowerShell is in Constrained Language Mode | The sensor names the cause: either the __PSLockdownPolicy system variable, which should be removed, or WDAC, which needs a rule allowing Tanium-signed scripts |
PowerShell Not Found / PowerShell must be at least version 3.0 |
No supported PowerShell version found in the registry | Install or repair Windows PowerShell 5.1 |
TSE-Error: Sensor evaluation timed out |
The Tanium Client stopped the sensor before it finished | Ask again. The PowerShell test waits for PowerShell to exit, so a hung PowerShell or WMI call can cause this. If it repeats, check whether other PowerShell sensors also time out on that machine |
TSE-Error: Failed to send to sensor child process: broken pipe |
The Tanium Client lost contact with the sensor process. This comes from the client, not the sensor script | Ask again. If it keeps happening on the same machine, restart the Tanium Client service |
The negative numbers in the WMI messages are Windows error codes. Convert them to hex to look them up. For example, -2147217406 is 0x80041002, which means WMI could not find the class or object it was asked for.
Check and repair WMI
Repair-WmiHealth.ps1 runs the same two WMI calls the sensor depends on:
- A registry read through
StdRegProvinroot\default. Select ProductType from Win32_OperatingSysteminroot\cimv2.
In Check mode it only reports. In Repair mode it runs winmgmt /salvagerepository when a check fails, then runs the checks again. Salvage only rebuilds the WMI repository if it finds it inconsistent, and it keeps everything it can still read. The script never runs /resetrepository.
Every run also logs the Winmgmt service state and the result of winmgmt /verifyrepository, so the action log shows what was wrong before anything changed.
| Exit code | Meaning |
|---|---|
0 |
Both checks pass, either right away or after the salvage. |
1 |
Repair mode ran the salvage and a check still fails. |
2 |
A check failed in Check mode. Nothing was changed. |
3 |
The Mode value was not Check or Repair. |
Create the package
- Save
Repair-WmiHealth.ps1from the Scripts section. - In the Tanium Console, go to Administration > Content > Packages and click Create Package.
- Fill in the fields:
- Package Display Name:
Check and Repair WMI - Content Set: the content set your team uses for custom content.
- Command:
- Command Timeout:
15minutes. A salvage can take several minutes on a slow machine.
- Package Display Name:
- Under Files, click Add, choose Local File, and upload
Repair-WmiHealth.ps1. - Expand Parameters. Under Parameter Inputs, add a Drop Down List parameter. It shows in the list as
$1.- Label:
Mode - Values:
CheckandRepair, withCheckas the default.
- Label:
- Click Save.
Use it
- In Interact, find the machines with a WMI message:
- Deploy the package with Mode set to
Check, and read the action log on each machine. - Deploy again with Mode set to
Repairon the machines that failed. - Ask the sensor again for those machines.
A check that fails in Check mode looks like this. The error text after the check name depends on what is broken on the machine:
2026-10-13 16:46:20 [INFO] Mode: Check
2026-10-13 16:46:20 [INFO] Winmgmt service: Running, startup Automatic
2026-10-13 16:46:21 [ERROR] StdRegProv (root\default): Invalid namespace
2026-10-13 16:46:21 [INFO] Win32_OperatingSystem (root\cimv2): OK, ProductType 1
2026-10-13 16:46:21 [WARN] WMI checks failed. Check mode, nothing changed. Run again with Mode Repair.
If Repair mode ends with exit code 1, the repository may be consistent while a provider is missing or broken, which a salvage does not fix. That machine needs hands-on work, such as re-registering the WMI providers. winmgmt /resetrepository is the last resort: it removes classes that other software registered (for example a configuration management client) until that software registers them again.
Reproduce it in a lab
Break-PathRegType.ps1 puts a lab VM into the broken state so the fix and the sensor can be checked end to end. Only run it on a lab VM, and take a snapshot first.
Run each command in an elevated PowerShell session on the VM, from the folder where the script is saved.
- Check the starting state. Path type should be
ExpandString: - Break PATH the same way the affected machines were broken:
- In Interact, confirm the sensor now returns the
REG_EXPAND_SZerror for the VM. - Deploy the fix package to the VM and confirm the sensor clears.
- Optional: run
-Mode BreakNoVars, which leaves PATH asREG_SZwith no%in it. The sensor should not report the error for this case. Run-Mode Restorebefore the next step. - Optional: run
-Mode HideClmTest, which renamestanium-clm-test.ps1totanium-clm-test.ps1.bak. The sensor should return the PowerShell execution test error. - Put everything back:
The first Break or BreakNoVars saves the untouched key to C:\Windows\Temp\Break-PathRegType_original.reg, and Restore imports it.
Test results
Each case ran Fix-PathRegType.ps1 through cmd.exe, the same way a Tanium package runs it, against a scratch key under HKCU instead of the real system PATH.
| Case | Expected | Result |
|---|---|---|
REG_SZ containing %SystemRoot% |
Exit 0, REG_EXPAND_SZ, data unchanged |
Pass |
| Run again on the fixed value | Exit 0, nothing to do | Pass |
Rollback with reg import |
Back to REG_SZ, data unchanged |
Pass |
REG_SZ with no variables |
Exit 0, REG_EXPAND_SZ |
Pass |
Empty REG_SZ |
Exit 3, unchanged | Pass |
| Path value missing | Exit 3, not created | Pass |
Unexpected type (REG_MULTI_SZ) |
Exit 3, unchanged | Pass |
| Backup fails | Exit 2, unchanged | Pass |
| Run from 32-bit PowerShell | Exit 0, REG_EXPAND_SZ |
Pass |
Also confirmed on Windows 11: Get-ItemProperty returns the Path entries already expanded, and 32-bit PowerShell reads the same HKLM\SYSTEM value as 64-bit PowerShell.
Repair-WmiHealth.ps1
Each case ran through cmd.exe with the Mode parameter quoted, the same way a Tanium package runs it. The broken cases used a copy of the script pointed at a namespace that does not exist, with the salvage command replaced by a stub, so no real WMI repository was changed.
| Case | Expected | Result |
|---|---|---|
| Healthy machine, Check | Exit 0, both checks logged | Pass |
| Blank Mode | Treated as Check, exit 0 | Pass |
| Healthy machine, Repair | Exit 0, no salvage | Pass |
| Invalid Mode | Exit 3 | Pass |
| Run from 32-bit PowerShell | Restarts as 64-bit, exit 0 | Pass |
| Broken check, Check | Exit 2, no salvage | Pass |
| Broken check, salvage does not help | Exit 1 | Pass |
| Broken check, salvage fixes it | Exit 0 | Pass |
winmgmt /salvagerepository itself was not run in testing. winmgmt /verifyrepository needs administrator rights, which a Tanium action has as SYSTEM.
Scripts
Fix-PathRegType.ps1
<#
.SYNOPSIS
Converts the machine Path registry value from REG_SZ to REG_EXPAND_SZ
without changing its data. Built for a Tanium package.
.DESCRIPTION
Tanium package command:
cmd.exe /d /c powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File Fix-PathRegType.ps1
Value fixed:
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\Path
The data is read raw, so %SystemRoot% stays %SystemRoot% and is never
replaced with C:\Windows. The value is overwritten in place with one call,
never deleted and recreated. The whole Environment key is exported to
C:\Windows\Temp\Environment_Path_backup.reg before anything is written.
HKLM\SYSTEM is not redirected for 32-bit processes, so the script works
from 32-bit or 64-bit PowerShell.
Exit codes:
0 Converted to REG_EXPAND_SZ, or it already was REG_EXPAND_SZ
1 Write or verification failed. Restore from the backup
2 Backup failed. Nothing changed
3 Path is missing, empty, or an unexpected type. Nothing changed
#>
$keyPath = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
$backup = 'C:\Windows\Temp\Environment_Path_backup.reg'
$noExpand = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
$expandKind = [Microsoft.Win32.RegistryValueKind]::ExpandString
function Write-Log {
param ([string]$Message, [string]$Level = 'INFO')
Write-Output ("{0} [{1}] {2}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $Level, $Message)
}
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($keyPath, $true)
if (-not $key) {
Write-Log "Could not open HKLM\$keyPath for writing. Is the script running as SYSTEM or an administrator?" 'ERROR'
exit 3
}
try {
# --- Read the current type and raw data ----------------------------------
if ($key.GetValueNames() -notcontains 'Path') {
Write-Log 'Path value does not exist. Nothing changed.' 'ERROR'
exit 3
}
$kind = $key.GetValueKind('Path')
$raw = $key.GetValue('Path', $null, $noExpand)
Write-Log "Current type: $kind"
if ($kind -eq $expandKind) {
Write-Log 'Path is already REG_EXPAND_SZ. Nothing to do.'
exit 0
}
if ($kind -ne [Microsoft.Win32.RegistryValueKind]::String) {
Write-Log "Path is $kind, which this script does not handle. Nothing changed." 'ERROR'
exit 3
}
if ([string]::IsNullOrWhiteSpace($raw)) {
Write-Log 'Path is empty. Nothing changed.' 'ERROR'
exit 3
}
Write-Log ("Path has {0} entries. Contains variables: {1}" -f ($raw -split ';' | Where-Object { $_ }).Count, ($raw -match '%'))
# --- Back up the whole Environment key -----------------------------------
& reg.exe export "HKLM\$keyPath" $backup /y 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $backup)) {
Write-Log "Backup to $backup failed (reg.exe exit $LASTEXITCODE). Nothing changed." 'ERROR'
exit 2
}
Write-Log "Backup saved: $backup"
# --- Overwrite in place with the new type --------------------------------
try {
$key.SetValue('Path', $raw, $expandKind)
} catch {
Write-Log "Write failed: $($_.Exception.Message)" 'ERROR'
exit 1
}
# --- Verify --------------------------------------------------------------
$newKind = $key.GetValueKind('Path')
$newRaw = $key.GetValue('Path', $null, $noExpand)
if ($newKind -eq $expandKind -and $newRaw -ceq $raw) {
Write-Log 'Converted Path from REG_SZ to REG_EXPAND_SZ. Data unchanged.'
Write-Log 'Running processes keep their old environment until they restart or the machine reboots.'
exit 0
}
Write-Log "Verification failed. Type is now $newKind, data matches: $($newRaw -ceq $raw). Restore from $backup." 'ERROR'
exit 1
}
finally {
$key.Close()
}
Repair-WmiHealth.ps1
<#
.SYNOPSIS
Checks the two WMI calls the Tanium Client Core Health sensor depends on,
and optionally salvages the WMI repository. Built for a Tanium package.
.DESCRIPTION
Tanium package command:
cmd.exe /d /c powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File Repair-WmiHealth.ps1 "$1"
$1 Mode Check (default) or Repair
Checks, matching the sensor:
1. root\default StdRegProv: EnumValues on HKLM\SYSTEM returns 0
2. root\cimv2: Select ProductType from Win32_OperatingSystem returns a value
Check mode only reports. Repair mode runs winmgmt /salvagerepository when a
check fails, then checks again. Salvage rebuilds the repository only if it
is inconsistent and keeps whatever it can read. /resetrepository is never run.
Exit codes:
0 Both checks pass (before or after repair)
1 Repair ran and a check still fails
2 A check failed in Check mode. Nothing changed
3 Invalid Mode value
#>
param ([string]$Mode = "")
# Run as 64-bit so winmgmt.exe and WMI are the native versions.
if ([Environment]::Is64BitOperatingSystem -and -not [Environment]::Is64BitProcess) {
$ps64 = Join-Path $env:SystemRoot 'Sysnative\WindowsPowerShell\v1.0\powershell.exe'
$argList = @('-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-File', $PSCommandPath)
if ($Mode) { $argList += @('-Mode', $Mode) }
& $ps64 @argList
exit $LASTEXITCODE
}
function Write-Log {
param ([string]$Message, [string]$Level = 'INFO')
Write-Output ("{0} [{1}] {2}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $Level, $Message)
}
$Mode = ([Uri]::UnescapeDataString($Mode)).Trim().Trim('"').Trim()
if (-not $Mode) { $Mode = 'Check' }
if ($Mode -notin 'Check', 'Repair') {
Write-Log "Mode must be Check or Repair, got '$Mode'." 'ERROR'
exit 3
}
Write-Log "Mode: $Mode"
$winmgmt = Join-Path $env:SystemRoot 'System32\wbem\winmgmt.exe'
# Sets $script:wmiOk instead of returning it. Write-Log writes to the output
# stream, so a return value would be mixed in with the log lines.
function Test-Wmi {
$ok = $true
try {
$r = Invoke-CimMethod -Namespace root/default -ClassName StdRegProv -MethodName EnumValues `
-Arguments @{ hDefKey = [uint32]2147483650; sSubKeyName = 'SYSTEM' } -OperationTimeoutSec 60 -ErrorAction Stop
if ($r.ReturnValue -eq 0) {
Write-Log 'StdRegProv (root\default): OK'
} else {
Write-Log "StdRegProv (root\default): EnumValues returned $($r.ReturnValue)" 'ERROR'
$ok = $false
}
} catch {
Write-Log "StdRegProv (root\default): $($_.Exception.Message)" 'ERROR'
$ok = $false
}
try {
$os = Get-CimInstance -Query 'Select ProductType from Win32_OperatingSystem' -OperationTimeoutSec 60 -ErrorAction Stop
if ($null -ne $os.ProductType) {
Write-Log "Win32_OperatingSystem (root\cimv2): OK, ProductType $($os.ProductType)"
} else {
Write-Log 'Win32_OperatingSystem (root\cimv2): no ProductType returned' 'ERROR'
$ok = $false
}
} catch {
Write-Log "Win32_OperatingSystem (root\cimv2): $($_.Exception.Message)" 'ERROR'
$ok = $false
}
$script:wmiOk = $ok
}
function Write-VerifyResult {
$out = & $winmgmt /verifyrepository 2>&1
Write-Log ("winmgmt /verifyrepository (exit {0}): {1}" -f $LASTEXITCODE, (($out | Where-Object { "$_".Trim() }) -join ' | '))
}
$svc = Get-Service -Name Winmgmt -ErrorAction SilentlyContinue
Write-Log ("Winmgmt service: {0}, startup {1}" -f $svc.Status, $svc.StartType)
Write-VerifyResult
Test-Wmi
if ($script:wmiOk) {
Write-Log 'WMI checks passed. Nothing to do.'
exit 0
}
if ($Mode -eq 'Check') {
Write-Log 'WMI checks failed. Check mode, nothing changed. Run again with Mode Repair.' 'WARN'
exit 2
}
Write-Log 'Running winmgmt /salvagerepository.'
$out = & $winmgmt /salvagerepository 2>&1
Write-Log ("winmgmt /salvagerepository (exit {0}): {1}" -f $LASTEXITCODE, (($out | Where-Object { "$_".Trim() }) -join ' | '))
Start-Sleep -Seconds 15
Write-VerifyResult
Test-Wmi
if ($script:wmiOk) {
Write-Log 'WMI checks pass after salvage.'
exit 0
}
Write-Log 'WMI checks still fail after salvage. This needs hands-on troubleshooting.' 'ERROR'
exit 1
Break-PathRegType.ps1 (lab only)
<#
.SYNOPSIS
LAB ONLY. Reproduces the Tanium Client Core Health errors on a test VM so
Fix-PathRegType.ps1 can be validated. Never run this on a production machine.
.DESCRIPTION
Run in an elevated PowerShell session on a lab VM. Take a VM snapshot first.
.\Break-PathRegType.ps1 -Mode Break Path becomes REG_SZ, data unchanged (%SystemRoot% kept)
.\Break-PathRegType.ps1 -Mode BreakNoVars Path becomes REG_SZ with variables expanded (no %)
.\Break-PathRegType.ps1 -Mode HideClmTest Renames Tools\StdUtils\tanium-clm-test.ps1 to .bak
.\Break-PathRegType.ps1 -Mode Status Shows the current state, changes nothing
.\Break-PathRegType.ps1 -Mode Restore Puts everything back
The first Break or BreakNoVars saves the untouched Environment key to
C:\Windows\Temp\Break-PathRegType_original.reg. Later runs do not overwrite it.
#>
param (
[ValidateSet('Break', 'BreakNoVars', 'HideClmTest', 'Status', 'Restore')]
[string]$Mode = 'Status'
)
$keyPath = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
$original = 'C:\Windows\Temp\Break-PathRegType_original.reg'
$noExpand = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) { Write-Output 'Run this from an elevated PowerShell session.'; exit 1 }
function Get-ClmTestPath {
foreach ($k in 'HKLM:\SOFTWARE\WOW6432Node\Tanium\Tanium Client', 'HKLM:\SOFTWARE\Tanium\Tanium Client') {
$dir = (Get-ItemProperty -Path $k -Name Path -ErrorAction SilentlyContinue).Path
if ($dir) { return Join-Path $dir 'Tools\StdUtils\tanium-clm-test.ps1' }
}
return $null
}
function Show-Status {
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($keyPath)
Write-Output ("Path type: {0}" -f $key.GetValueKind('Path'))
Write-Output ("First entry: {0}" -f (($key.GetValue('Path', $null, $noExpand) -split ';')[0]))
$key.Close()
$clm = Get-ClmTestPath
if ($clm) {
Write-Output ("clm test: {0} exists: {1}, .bak exists: {2}" -f $clm, (Test-Path -LiteralPath $clm), (Test-Path -LiteralPath "$clm.bak"))
} else {
Write-Output 'clm test: Tanium Client folder not found in the registry'
}
Write-Output ("Backup saved: {0}" -f (Test-Path -LiteralPath $original))
}
function Save-Original {
if (Test-Path -LiteralPath $original) { return }
& reg.exe export "HKLM\$keyPath" $original /y | Out-Null
if ($LASTEXITCODE -ne 0) { Write-Output 'Backup failed. Nothing changed.'; exit 1 }
Write-Output "Original Environment key saved to $original"
}
switch ($Mode) {
'Break' {
Save-Original
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($keyPath, $true)
$key.SetValue('Path', $key.GetValue('Path', $null, $noExpand), [Microsoft.Win32.RegistryValueKind]::String)
$key.Close()
Write-Output 'Path is now REG_SZ with %SystemRoot% still in it.'
}
'BreakNoVars' {
Save-Original
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($keyPath, $true)
$key.SetValue('Path', $key.GetValue('Path'), [Microsoft.Win32.RegistryValueKind]::String)
$key.Close()
Write-Output 'Path is now REG_SZ with every variable expanded (no % left).'
}
'HideClmTest' {
$clm = Get-ClmTestPath
if (-not $clm -or -not (Test-Path -LiteralPath $clm)) { Write-Output "Not found: $clm"; exit 1 }
Rename-Item -LiteralPath $clm -NewName 'tanium-clm-test.ps1.bak'
Write-Output "Renamed $clm to tanium-clm-test.ps1.bak"
}
'Restore' {
if (Test-Path -LiteralPath $original) {
& reg.exe import $original 2>&1 | Out-Null
if ($LASTEXITCODE -eq 0) {
Remove-Item -LiteralPath $original
Write-Output 'Environment key restored from the original backup.'
} else {
Write-Output "reg import failed. The backup is still at $original"
}
}
$clm = Get-ClmTestPath
if ($clm -and (Test-Path -LiteralPath "$clm.bak") -and -not (Test-Path -LiteralPath $clm)) {
Rename-Item -LiteralPath "$clm.bak" -NewName 'tanium-clm-test.ps1'
Write-Output 'tanium-clm-test.ps1 restored.'
}
}
}
Show-Status