Windows 中 WMI 的深入探索与应用
1. Windows 中 WMI 的基础信息
Windows 在操作系统安装过程中会安装 WMI,其大部分组件,包括存储库、工具和提供程序等,会被安装到
C:\Windows\System32\WBEM
文件夹中。在运行的 Windows 主机里,WMI 以
winmgmt
服务(
winmgmt.exe
)的形式运行,该服务在共享服务进程(
svchost.exe
)内执行。早期 Windows 版本的 WMI 会将所有 WMI 提供程序加载到
winmgmt
服务中,单个提供程序的故障可能导致整个 WMI 服务失败。后来,从 Windows XP 及更高版本开始,微软改进了 WMI,将提供程序加载到单独的进程
WmiPrvSE.exe
中。
2. 探索 WBEM 文件夹及相关组件
以下是一系列操作步骤,帮助你深入了解 WMI 的各个方面:
1.
查看 WBEM 文件夹内容
$WBEMFOLDER = "$Env:windir\system32\wbem"
Get-ChildItem -Path $WBEMFOLDER |
Select-Object -First 20
- 查看 WMI 存储库文件夹
Get-ChildItem -Path $WBEMFOLDER\Repository
- 查看 WMI 服务详细信息
Get-Service -Name Winmgmt |
Format-List -Property *
- 获取进程详细信息
$S = tasklist.exe /svc /fi "SERVICES eq winmgmt" |
Select-Object -Last 1
$P = [int] ($S.Substring(30,4))
Get-Process -Id $P
- 检查 WMI 服务进程加载的 DLL
Get-Process -Id $P |
Select-Object -ExpandProperty modules |
Where-Object ModuleName -match 'wmi' |
Format-Table -Property FileName, Description, FileVersion
- 发现 WMI 提供程序
Get-ChildItem -Path $WBEMFOLDER\*.dll |
Select-Object -ExpandProperty Versioninfo |
Where-Object FileDescription -match 'prov' |
Format-Table -Property Internalname,
FileDescription,
ProductVersion
- 检查 WmiPrvSE 进程
Get-Process -Name WmiPrvSE
- 查找 WMI 事件日志
$Log = Get-WinEvent -ListLog *wmi*
$Log
- 查看 WMI 日志中的事件类型
$Events = Get-WinEvent -LogName $Log.LogName
$Events | Group-Object -Property LevelDisplayName
- 检查 WMI 事件日志条目
$Events |
Select-Object -First 5 |
Format-Table -Wrap
- 查看 WBEM 文件夹中的可执行程序
$Files = Get-ChildItem -Path $WBEMFOLDER\*.exe
"{0,15} {1,-40}" -f 'File Name','Description'
Foreach ($File in $Files){
$Name = $File.Name
$Desc = ($File |
Select-Object -ExpandProperty VersionInfo).FileDescription
"{0,15} {1,-40}" -f $Name,$Desc
}
- 检查 CimCmdlets 模块
Get-Module -Name CimCmdlets |
Select-Object -ExcludeProperty Exported*
Format-List -Property *
- 查找 CimCmdlets 模块中的 cmdlet
Get-Command -Module CimCmdlets
- 检查 Get-CimInstance 返回的 .NET 类型
Get-CimInstance -ClassName Win32_Share | Get-Member
3. 探索 WMI 命名空间
WMI 命名空间是组织 CIM 数据库信息的重要方式,PowerShell 的 CIM cmdlet 可用于对其进行操作。以下是相关操作步骤:
1.
查看根命名空间中的 WMI 类
Get-CimClass -Namespace 'ROOT' |
Select-Object -First 10
- 查看根命名空间中的 __NAMESPACE 类
Get-CimInstance -Namespace 'ROOT' -ClassName __NAMESPACE |
Sort-Object -Property Name
- 获取并统计 ROOT\CIMV2 命名空间中的类
$Classes = Get-CimClass -Namespace 'ROOT\CIMV2'
"There are $($Classes.Count) classes in ROOT\CIMV2"
- 发现 SRV1 上的所有命名空间
Function Get-WMINamespaceEnum {
[CmdletBinding()]
Param($NS)
Write-Output $NS
Get-CimInstance "__Namespace" -Namespace $NS @EAHT |
ForEach-Object { Get-WMINamespaceEnum "$ns\$($_.name)" }
} # End of function
$Namespaces = Get-WMINamespaceEnum 'ROOT' |
Sort-Object
"There are $($Namespaces.Count) WMI namespaces on SRV1"
- 查看 SRV1 上的前 25 个命名空间
$Namespaces |
Select-Object -First 25
- 创建脚本块以统计命名空间和类
$SB = {
Function Get-WMINamespaceEnum {
[CmdletBinding()]
Param(
$NS
)
Write-Output $NS
$EAHT = @{ErrorAction = 'SilentlyContinue'}
Get-CimInstance "__Namespace" -Namespace $NS @EAHT |
ForEach-Object { Get-WMINamespaceEnum "$NS\$($_.Name)" }
} # End of function
$Namespaces = Get-WMINamespaceEnum 'ROOT' | Sort-Object
$WMIClasses = @()
Foreach ($Namespace in $Namespaces) {
$WMIClasses += Get-CimClass -Namespace $Namespace
}
"There are $($Namespaces.Count) WMI namespaces on $(hostname)"
"There are $($WMIClasses.Count) classes on $(hostname)"
}
- 在 SRV1 上本地运行脚本块
Invoke-Command -ComputerName SRV1 -ScriptBlock $SB
- 在 SRV2 上运行脚本块
Invoke-Command -ComputerName SRV2 -ScriptBlock $SB
- 在 DC1 上运行脚本块
Invoke-Command -ComputerName DC1 -ScriptBlock $SB
4. 探索 WMI 类
WMI 类定义了 WMI 管理的对象,包含属性、方法和事件等成员。以下是探索 WMI 类的操作步骤:
1.
查看 Win32_Share 类
Get-CimClass -ClassName Win32_Share
- 查看 Win32_Share 类的属性
Get-CimClass -ClassName Win32_Share |
Select-Object -ExpandProperty CimClassProperties |
Sort-Object -Property Name |
Format-Table -Property Name, CimType
- 获取 Win32_Share 类的方法
Get-CimClass -ClassName Win32_Share |
Select-Object -ExpandProperty CimClassMethods
- 获取非默认命名空间中的类
Get-CimClass -Namespace root\directory\LDAP |
Where-Object CimClassName -match '^ds_group'
- 查看 ds_group 类的实例
Get-CimInstance -Namespace root\directory\LDAP -Classname 'DS_Group' |
Format-Table -Property DS_name, DS_Member
5. 获取本地和远程 WMI 对象
使用
Get-CimInstance
cmdlet 可以获取本地或远程主机上 WMI 类的实例,有以下三种使用方式:
1.
返回所有类的实例和属性
:直接使用
Get-CimInstance
命令,不添加额外参数。
2.
使用 -Filter 参数指定 WMI 过滤器
:例如
Get-CimInstance -ClassName <类名> -Filter "<过滤条件>"
。
3.
使用 WMI 查询语言(WQL)
:例如
Get-CimInstance -Query "SELECT * FROM <类名> WHERE <条件>"
。
当通过网络使用 WMI 时,指定过滤器或完整的 WMI 查询可以减少网络传输的数据量,提高性能。
总结
通过以上步骤,你可以全面深入地了解 Windows 中 WMI 的各个方面,包括 WBEM 文件夹内容、WMI 命名空间、WMI 类以及如何获取本地和远程 WMI 对象。这些操作对于系统管理和故障排除都具有重要意义。
流程图
graph LR
A[开始] --> B[探索 WBEM 文件夹]
B --> C[探索 WMI 命名空间]
C --> D[探索 WMI 类]
D --> E[获取本地和远程 WMI 对象]
E --> F[结束]
表格
| 操作步骤 | 相关命令 |
|---|---|
| 查看 WBEM 文件夹内容 |
Get-ChildItem -Path $WBEMFOLDER | Select-Object -First 20
|
| 查看 WMI 存储库文件夹 |
Get-ChildItem -Path $WBEMFOLDER\Repository
|
| 查看 WMI 服务详细信息 |
Get-Service -Name Winmgmt | Format-List -Property *
|
| 获取进程详细信息 |
$S = tasklist.exe /svc /fi "SERVICES eq winmgmt" | Select-Object -Last 1; $P = [int] ($S.Substring(30,4)); Get-Process -Id $P
|
| 检查 WMI 服务进程加载的 DLL |
Get-Process -Id $P | Select-Object -ExpandProperty modules | Where-Object ModuleName -match 'wmi' | Format-Table -Property FileName, Description, FileVersion
|
| 发现 WMI 提供程序 |
Get-ChildItem -Path $WBEMFOLDER\*.dll | Select-Object -ExpandProperty Versioninfo | Where-Object FileDescription -match 'prov' | Format-Table -Property Internalname, FileDescription, ProductVersion
|
| 检查 WmiPrvSE 进程 |
Get-Process -Name WmiPrvSE
|
| 查找 WMI 事件日志 |
$Log = Get-WinEvent -ListLog *wmi*; $Log
|
| 查看 WMI 日志中的事件类型 |
$Events = Get-WinEvent -LogName $Log.LogName; $Events | Group-Object -Property LevelDisplayName
|
| 检查 WMI 事件日志条目 |
$Events | Select-Object -First 5 | Format-Table -Wrap
|
| 查看 WBEM 文件夹中的可执行程序 |
$Files = Get-ChildItem -Path $WBEMFOLDER\*.exe; "{0,15} {1,-40}" -f 'File Name','Description'; Foreach ($File in $Files){ $Name = $File.Name; $Desc = ($File | Select-Object -ExpandProperty VersionInfo).FileDescription; "{0,15} {1,-40}" -f $Name,$Desc }
|
| 检查 CimCmdlets 模块 |
Get-Module -Name CimCmdlets | Select-Object -ExcludeProperty Exported*; Format-List -Property *
|
| 查找 CimCmdlets 模块中的 cmdlet |
Get-Command -Module CimCmdlets
|
| 检查 Get-CimInstance 返回的 .NET 类型 |
Get-CimInstance -ClassName Win32_Share | Get-Member
|
| 查看根命名空间中的 WMI 类 |
Get-CimClass -Namespace 'ROOT' | Select-Object -First 10
|
| 查看根命名空间中的 __NAMESPACE 类 |
Get-CimInstance -Namespace 'ROOT' -ClassName __NAMESPACE | Sort-Object -Property Name
|
| 获取并统计 ROOT\CIMV2 命名空间中的类 |
$Classes = Get-CimClass -Namespace 'ROOT\CIMV2'; "There are $($Classes.Count) classes in ROOT\CIMV2"
|
| 发现 SRV1 上的所有命名空间 |
Function Get-WMINamespaceEnum { [CmdletBinding()]; Param($NS); Write-Output $NS; Get-CimInstance "__Namespace" -Namespace $NS @EAHT | ForEach-Object { Get-WMINamespaceEnum "$ns\$($_.name)" } }; $Namespaces = Get-WMINamespaceEnum 'ROOT' | Sort-Object; "There are $($Namespaces.Count) WMI namespaces on SRV1"
|
| 查看 SRV1 上的前 25 个命名空间 |
$Namespaces | Select-Object -First 25
|
| 创建脚本块以统计命名空间和类 |
$SB = { Function Get-WMINamespaceEnum { [CmdletBinding()]; Param($NS); Write-Output $NS; $EAHT = @{ErrorAction = 'SilentlyContinue'}; Get-CimInstance "__Namespace" -Namespace $NS @EAHT | ForEach-Object { Get-WMINamespaceEnum "$NS\$($_.Name)" } }; $Namespaces = Get-WMINamespaceEnum 'ROOT' | Sort-Object; $WMIClasses = @(); Foreach ($Namespace in $Namespaces) { $WMIClasses += Get-CimClass -Namespace $Namespace }; "There are $($Namespaces.Count) WMI namespaces on $(hostname)"; "There are $($WMIClasses.Count) classes on $(hostname)" }
|
| 在 SRV1 上本地运行脚本块 |
Invoke-Command -ComputerName SRV1 -ScriptBlock $SB
|
| 在 SRV2 上运行脚本块 |
Invoke-Command -ComputerName SRV2 -ScriptBlock $SB
|
| 在 DC1 上运行脚本块 |
Invoke-Command -ComputerName DC1 -ScriptBlock $SB
|
| 查看 Win32_Share 类 |
Get-CimClass -ClassName Win32_Share
|
| 查看 Win32_Share 类的属性 |
Get-CimClass -ClassName Win32_Share | Select-Object -ExpandProperty CimClassProperties | Sort-Object -Property Name | Format-Table -Property Name, CimType
|
| 获取 Win32_Share 类的方法 |
Get-CimClass -ClassName Win32_Share | Select-Object -ExpandProperty CimClassMethods
|
| 获取非默认命名空间中的类 |
Get-CimClass -Namespace root\directory\LDAP | Where-Object CimClassName -match '^ds_group'
|
| 查看 ds_group 类的实例 |
Get-CimInstance -Namespace root\directory\LDAP -Classname 'DS_Group' | Format-Table -Property DS_name, DS_Member
|
Windows 中 WMI 的深入探索与应用
6. 操作注意事项与分析
在前面的操作中,有一些细节值得进一步分析:
-
WBEM 文件夹操作
:在查看 WBEM 文件夹内容时,只显示了前 20 个文件/文件夹,实际上该文件夹包含更多文件,其中就有系统可用的 WMI 提供程序的 DLL 文件。
-
WmiPrvSE 进程
:查看 WmiPrvSE 进程时,该进程用于托管 WMI 提供程序。根据 WMI 当前的操作,主机上可能会出现零个、一个或多个该进程实例。
-
WMI 系统事件日志
:在查看 WMI 系统事件日志时,在 SRV1 上可以看到既有错误(Error)也有信息(Information)类型的日志条目。信息条目大多表明 WMI 已加载并调用了特定的提供程序。大多数情况下,看到的错误事件消息是暂时的或无害的。
-
Get-CimInstance 返回数据
:查看 Get-CimInstance 返回的数据时,该 cmdlet 返回从 WMI 类获取的数据,这些数据封装在一个 .NET 对象中,类名为
Microsoft.Management.Infrastructure.CimInstance
,并带有一个后缀表示 WMI 类的路径。返回的对象及其内容与
Get-WMIObject
返回的不同,这在升级以前使用旧 WMI cmdlet 的 Windows PowerShell 脚本时可能会成为问题。
7. 重要命名空间分析
WMI 中有许多命名空间和类,不同的命名空间和类有不同的用途:
| 命名空间 | 说明 |
| ---- | ---- |
| ROOT\CIMV2 | 由 Win32 WMI 提供程序实现,包含对 IT 专业人员有用的 WMI 类,这些类提供了系统软件和硬件的详细信息,如 BIOS、操作系统、文件等。 |
| ROOT\directory\LDAP | 不太常用的命名空间,包含与 Active Directory 相关的类。虽然大部分 AD 管理使用 AD cmdlet,但该命名空间的某些功能(如事件处理)是 AD cmdlet 所没有的,可能会很有用。 |
8. 常见问题及解决思路
-
脚本升级问题
:由于
Get-CimInstance返回的数据与Get-WMIObject不同,在升级 Windows PowerShell 脚本时,需要注意对返回对象的处理。可以通过详细测试新脚本,确保其能正确处理新的数据格式。 - WMI 错误事件处理 :对于 WMI 系统事件日志中的错误事件,大多数是暂时的或无害的。但如果错误事件频繁出现,需要进一步分析具体的错误信息,查看是否是某个 WMI 提供程序出现问题,或者是系统配置存在异常。
9. 总结与建议
通过对 Windows 中 WMI 的全面探索,我们了解了其安装位置、服务运行方式、命名空间、类以及如何获取本地和远程对象等内容。以下是一些总结和建议:
-
操作总结
- 可以使用一系列 PowerShell 命令来查看 WBEM 文件夹、WMI 服务、命名空间、类等信息。
- 利用
Get-CimInstance
cmdlet 可以方便地获取本地或远程主机上 WMI 类的实例,并且可以通过不同的方式指定过滤条件,减少网络传输数据量。
-
建议
- 在进行 WMI 相关操作时,尤其是涉及到系统配置和远程操作,建议先在测试环境中进行测试,避免对生产环境造成影响。
- 对于复杂的 WMI 查询和操作,可以编写脚本进行自动化处理,提高工作效率。
流程图
graph LR
A[开始] --> B[分析 WBEM 文件夹操作]
B --> C[分析 WmiPrvSE 进程]
C --> D[分析 WMI 系统事件日志]
D --> E[分析 Get-CimInstance 返回数据]
E --> F[分析重要命名空间]
F --> G[解决常见问题]
G --> H[总结与建议]
H --> I[结束]
表格
| 问题类型 | 问题描述 | 解决思路 |
|---|---|---|
| 脚本升级问题 |
Get-CimInstance
返回数据与
Get-WMIObject
不同,升级脚本可能出现问题
| 详细测试新脚本,确保能正确处理新的数据格式 |
| WMI 错误事件处理 | WMI 系统事件日志中错误事件频繁出现 | 进一步分析具体错误信息,查看是否是 WMI 提供程序或系统配置问题 |
超级会员免费看
11

被折叠的 条评论
为什么被折叠?



