You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:将注册表条目导入root/cimv2自定义WMI类

问题需求

在root/cimv2命名空间创建自定义WMI类,自动遍历HKLM:\SOFTWARE\OSDBuild注册表项的所有条目并导入该类。已有注册表写入代码,但WMI导入代码无法正常运行。

原注册表写入代码的小问题修正

原代码存在几处拼写错误,修正后版本:

$RegKeyName = "OSDBuild"

# Set values
$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$FullRegKeyName = "HKLM:\SOFTWARE\" + $regkeyname 

# Create Registry key
New-Item -Path $FullRegKeyName -type Directory -Force -ErrorAction SilentlyContinue

# Get values
$InstallTime = Get-Date -Format G 
$OSDStartTime = $tsenv.Value("OSDStartTSTime")
$AdvertisementID = $tsenv.Value("_SMSTSAdvertID")
$Organisation = $tsenv.Value("_SMSTSOrgName")
$TaskSequenceID = $tsenv.Value("_SMSTSPackageID")
$Packagename = $tsenv.Value("_SMSTSPackageName")
$MachineName = $env:computername
$Installationmode = $tsenv.Value("_SMSTSLaunchMode")
$BuildRevision = $tsenv.Value("BuildRevision")
$OSName = $tsenv.Value("OSName")
$OSDDateUTC = (Get-Date).ToUniversalTime()

#Calculate time elapsed
$OSDTimeSpan = New-TimeSpan -start $OSDStartTime -end $InstallTime
$OSDDuration = "{0:hh}:{0:mm}:{0:ss}" -f $OSDTimeSpan

# Write values
New-ItemProperty $FullRegKeyName -Name "InstalledDate" -value $InstallTime -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "OSDStartTime" -value $OSDStartTime -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "OSDDuration" -value $OSDDuration -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "OrganisationName" -value $Organisation -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "AdvertisementID" -value $AdvertisementID -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "TaskSequenceID" -value $TaskSequenceID -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "Task Sequence Name" -value $Packagename -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "Installation Type" -value $Installationmode -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "Computername" -value $MachineName -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "OSVersion" -value (Get-CimInstance Win32_Operatingsystem).version -PropertyType String -Force | Out-Null
New-ItemProperty $FullRegKeyName -Name "BuildRevision" -value $BuildRevision -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "OSVersionName" -value $OSName -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty $FullRegKeyName -Name "OSDDateUTC" -value $OSDDateUTC -Type STRING -Force -ErrorAction SilentlyContinue | Out-Null

原WMI导入代码的问题分析

  • 重复赋值$registryKey:多次赋值后仅保留最后一个值,导致所有WMI实例的RegistryKeyName错误,应使用注册表项的实际名称(如OSDBuild)。
  • CimInstance创建逻辑错误:重复调用New-CimInstance,且无需先转换为PSCustomObject,直接通过属性哈希表创建即可。
  • 未处理类已存在的情况:重复运行会报错,需先检查类是否存在,按需跳过或重建。
  • 缺少错误处理:未判断注册表路径是否存在,可能导致后续操作失败。

修正后的WMI导入代码

# 定义命名空间和类名
$namespace = "root\cimv2"
$className = "OSDBuild"
$registryPath = "HKLM:\SOFTWARE\OSDBuild"

# 检查注册表路径是否存在
if (-not (Test-Path $registryPath)) {
    Write-Error "注册表路径 $registryPath 不存在"
    exit 1
}

# 检查WMI类是否存在,不存在则创建
$existingClass = Get-CimClass -Namespace $namespace -ClassName $className -ErrorAction SilentlyContinue
if (-not $existingClass) {
    # 定义类属性
    $classProperties = @(
        New-CimProperty -Name "RegistryKeyName" -CimType String -Flags "Key, ReadOnly"
        New-CimProperty -Name "RegistryValueName" -CimType String -Flags "Key, ReadOnly"
        New-CimProperty -Name "RegistryValueData" -CimType String -Flags "ReadOnly"
    )
    # 创建类
    New-CimClass -Namespace $namespace -ClassName $className -PropertyDefinition $classProperties | Out-Null
    Write-Host "已创建WMI类 $namespace\$className"
} else {
    Write-Host "WMI类 $namespace\$className 已存在,跳过创建"
}

# 获取注册表项的名称(如OSDBuild)
$registryKeyName = (Get-Item $registryPath).PSChildName

# 获取注册表所有值
$registryValues = Get-ItemProperty -Path $registryPath

# 遍历注册表值并创建WMI实例
foreach ($property in $registryValues.PSObject.Properties) {
    # 跳过PowerShell内置属性
    if ($property.Name -in "PSPath", "PSParentPath", "PSChildName", "PSDrive", "PSProvider") {
        continue
    }

    # 准备实例属性
    $instanceProps = @{
        RegistryKeyName   = $registryKeyName
        RegistryValueName = $property.Name
        RegistryValueData = $property.Value.ToString()
    }

    # 检查该实例是否已存在,避免重复创建
    $existingInstance = Get-CimInstance -Namespace $namespace -ClassName $className -Filter "RegistryKeyName='$registryKeyName' AND RegistryValueName='$($property.Name)'" -ErrorAction SilentlyContinue
    if (-not $existingInstance) {
        # 创建并保存WMI实例
        New-CimInstance -Namespace $namespace -ClassName $className -Property $instanceProps | Out-Null
        Write-Host "已导入注册表值: $($property.Name) = $($property.Value)"
    } else {
        Write-Host "注册表值 $($property.Name) 已存在于WMI类中,跳过"
    }
}

代码说明

  • 类存在性检查:避免重复创建类导致的错误。
  • 注册表路径检查:提前判断路径是否存在,防止后续操作失败。
  • 实例去重:通过键属性(RegistryKeyName + RegistryValueName)检查是否已存在,避免重复导入。
  • 数据类型统一:将注册表值转为String,匹配WMI类的属性类型。

内容的提问来源于stack exchange,提问作者user25512276

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 09:44:55