Dùng WMI/CIM từ C# và PowerShell — hướng dẫn thực hành lấy thông tin phần cứng, giám sát tiến trình và truy vấn từ xa

· · Windows, C#, .NET, PowerShell, WMI, CIM, Ứng dụng nghiệp vụ, Phát triển Windows

“Tôi muốn hiện số serial và tên model của PC trên màn hình ứng dụng nghiệp vụ.” “Tôi muốn giám sát dung lượng đĩa trống của máy chủ và cảnh báo.” “Tôi muốn phát hiện khi một tiến trình cụ thể khởi chạy.” “Tôi muốn gom trạng thái các PC ở nơi xa về một chỗ.” — Khi xây ứng dụng nghiệp vụ Windows và công cụ quản lý, loại yêu cầu này là chuyện thường gặp. Và câu trả lời chuẩn cho chúng là WMI (Windows Management Instrumentation), hay, theo tên chuẩn, CIM (Common Information Model).

Yêu cầu thường gặp và WMI/CIMCâu trả lời chuẩn cho các yêu cầu thường gặp của ứng dụng nghiệp vụ gồm hiện số serial và tên model, giám sát dung lượng đĩa trống, phát hiện tiến trình khởi chạy, truy vấn PC từ xa là WMI, hay CIM theo tên chuẩnSố serial · tên modelWMI(tên chuẩn là CIM)Giám sát dung lượng đĩa trốngPhát hiện tiến trình khởi chạyTruy vấn PC từ xa

Hình 1: Câu trả lời chuẩn cho bốn yêu cầu thường gặp của ứng dụng nghiệp vụ là WMI/CIM.

Điều gây khó là thông tin quanh WMI trộn lẫn cũ và mới. Tìm kiếm thì bài mười năm tuổi dùng Get-WmiObject ngồi cạnh bài dùng Get-CimInstance, phía C# lại có hai dòng System.ManagementMicrosoft.Management.Infrastructure. Cái nào là cách viết hiện hành, cái nào là “vẫn chạy nhưng không chọn cho mã mới” thì khó nhìn ra. Thực tế, Get-WmiObject không tồn tại trên PowerShell 7, và điều đó đột ngột lộ ra khi di chuyển tập lệnh nội bộ viết cho 5.1.

Bài này hướng tới nhà phát triển C#/PowerShell đang gắn lấy thông tin phần cứng, giám sát tiến trình và truy vấn PC từ xa vào ứng dụng nghiệp vụ. Nó đi từ hiểu tối thiểu cấu trúc WMI/CIM, qua cmdlet CIM của PowerShell, hai API C#, công thức thực tế hay dùng, các cạm bẫy về hiệu năng, quyền và 64-bit, rồi cách phán “khi nào không nên dùng WMI” — tất cả sắp xếp từ nguồn gốc tính tới tháng 8 năm 2026.

1. Kết luận trước

  • CIM là mô hình chuẩn ngành về thông tin quản lý do DMTF soạn thảo, WMI là triển khai của Microsoft cho chuẩn đó. API họ “CIM” trong PowerShell và C# là thế hệ hiện hành bám chuẩn này, và chúng kết nối tới cùng nền tảng WMI.1
  • Trên PowerShell, thế hệ hiện hành là cmdlet CIM (Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent). Các cmdlet WMI cũ (Get-WmiObject và bốn cái nữa) đã bị xóa từ PowerShell 6 trở đi và không chạy trên PowerShell 7.2
  • Không gian tên mặc định là root/CIMV2, và truy vấn hàng ngày cơ bản là lọc các lớp Win32_* ở đó bằng WQL.3
  • Truy vấn từ xa mặc định dùng WSMan (WinRM). Chỉ định -ComputerName tạo phiên tạm WSMan. Nếu bạn truy vấn cùng một đích nhiều lần, tái sử dụng phiên CIM (New-CimSession) là phép tắc về hiệu năng, và với máy cũ không cấu hình được WinRM thì có tùy chọn giao thức DCOM.34
  • C# có hai dòng: System.Management (ManagementObjectSearcher) và Microsoft.Management.Infrastructure (CimSession). Cả hai đều chỉ dành cho Windows, và trên .NET hiện hành bạn đưa chúng vào qua NuGet. Nếu gắn truy vấn từ xa hay giám sát vào sản phẩm thật, MI API — cùng hệ kiểu với cmdlet CIM — hợp hơn.56
  • Phát hiện tiến trình khởi chạy bằng đăng ký sự kiện, không polling. Đăng ký Win32_ProcessStartTrace phải chạy với quyền quản trị viên.78
  • Đừng dùng SELECT * theo thói quen. Lọc dữ liệu chuyển đi bằng -Filter / -Property / -KeyOnly ngăn khoảng nửa vấn đề hiệu năng của WMI.3
  • WMI không phải lời giải vạn năng. Với giám sát hiệu năng tần suất cao, đọc ghi thiết lập của chính ứng dụng, hay gọi chức năng OS một lần, bộ đếm hiệu năng, registry, Win32 API, hoặc cmdlet chuyên biệt hợp hơn (xem bảng quyết định ở mục 8).

2. WMI/CIM là gì — chuẩn và triển khai, không gian tên, lớp, WQL

Trước hết, sắp xếp quan hệ thuật ngữ một lần cho xong.

Thuật ngữ Bản chất
CIM (Common Information Model) Mô hình chuẩn ngành để biểu diễn đối tượng quản lý như hệ thống, ứng dụng, mạng và thiết bị. DMTF (Distributed Management Task Force) soạn thảo và duy trì1
WBEM (Web-Based Enterprise Management) Sáng kiến ngành nhằm tạo công nghệ chuẩn để truy cập thông tin quản lý trong môi trường doanh nghiệp1
WMI Triển khai của Microsoft cho WBEM. Biểu diễn đối tượng quản lý bằng chuẩn CIM và được gắn sẵn trong Windows1
MI (Windows Management Infrastructure) Thế hệ kế của WMI. Tương thích hoàn toàn với WMI cũ, và hầu hết provider mới được viết bằng MI1
Quan hệ chuẩn CIM và triển khai WMIChuẩn CIM do DMTF soạn thảo và duy trì được dùng trong khuôn khổ sáng kiến WBEM, triển khai của Microsoft là WMI, MI thế hệ kế tương thích hoàn toàn với WMI cũ, và API họ CIM kết nối tới cùng nền tảng WMIDMTF soạn thảo và duy trìCIM(mô hình chuẩn ngành)WBEM(sáng kiến ngành)WMI(triển khai của Microsoft)MI(thế hệ kế · tương thích hoàn toàn)API họ CIM(PowerShell / C#)

Hình 2: CIM là đặc tả, WMI là triển khai trên Windows. API họ CIM kết nối tới cùng nền tảng WMI.

Với tư cách nhà phát triển, bốn mảnh cấu trúc đáng nắm là như sau.

  • Không gian tên (namespace): phân cấp gom các lớp lại. Truy vấn hàng ngày gần như luôn dùng root/CIMV2, cũng là mặc định của cmdlet CIM.3 Ngoài ra còn root\default (provider registry, v.v.).
  • Lớp: kiểu biểu diễn đối tượng quản lý, như Win32_ComputerSystem (máy tính), Win32_LogicalDisk (ổ logic), hay Win32_Process (tiến trình). Các lớp riêng Windows kế thừa lớp chuẩn CIM (như CIM_LogicalDisk) mang tiền tố Win32_.9
  • Provider: thành phần cung cấp thực thể của lớp. Khi bạn truy vấn, provider hỏi OS ngay tại chỗ và dựng giá trị.
  • WQL: ngôn ngữ truy vấn giống SQL. Như SELECT Name, State FROM Win32_Service WHERE StartMode = 'Auto', nó coi lớp như bảng rồi lọc. WQL cũng là ngôn ngữ truy vấn mặc định của cmdlet CIM.3

“Đọc thông tin OS và phần cứng qua một bộ lớp thống nhất và một ngôn ngữ truy vấn” — đó là giá trị WMI mang lại. Ngược lại, ghi và thao tác bị giới hạn ở một số lớp có phương thức gọi được qua Invoke-CimMethod; đây không phải cơ chế làm được mọi thứ.

Cấu trúc truy vấn WMITruy vấn WQL hướng tới lớp Win32_* trong không gian tên root/CIMV2, provider cung cấp thực thể của lớp hỏi OS ngay tại chỗ để dựng giá trị, rồi kết quả được trả vềTruy vấn bằng WQLKhông gian tên root/CIMV2Lớp Win32_*ProviderHỏi OS ngay tại chỗTrả kết quả

Hình 3: Truy vấn lần theo không gian tên, lớp, rồi provider, và giá trị được dựng tại chỗ.

3. Dùng từ PowerShell — cmdlet CIM là hiện hành, cmdlet WMI đã bị xóa

3.1. Nền tảng: Get-CimInstance

# Theo tên lớp (không gian tên mặc định root/CIMV2)
Get-CimInstance -ClassName Win32_OperatingSystem

# Chỉ viết nội dung mệnh đề WHERE vào -Filter (đừng viết từ khóa WHERE)
Get-CimInstance -ClassName Win32_Service -Filter "StartMode = 'Auto' AND State <> 'Running'"

# Chỉ lấy thuộc tính cần thiết để giảm lượng truyền
Get-CimInstance -ClassName Win32_Process -Property Name, ProcessId, CreationDate

# Dùng -Query nếu muốn viết WQL nguyên văn
Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name LIKE 'p%'"

-Filter chính là mệnh đề WHERE của WQL, còn -Property hạn chế cột lấy về.3 Giá trị trả về là đối tượng CimInstance, và thuộc tính ngày (như CreationDate hay LastBootUpTime) đã được chuyển thành DateTime. Khác Get-WmiObject cũ, đối tượng lấy về không mang phương thức trực tiếp, nên gọi phương thức bằng cách đưa vào Invoke-CimMethod.

Gọi phương thức trên CimInstanceCimInstance do Get-CimInstance trả về đã chuyển thuộc tính ngày thành DateTime nhưng không mang phương thức trực tiếp, nên gọi phương thức bằng cách đưa instance vào Invoke-CimMethodGet-CimInstanceĐối tượng CimInstanceNgày đã chuyển thành DateTimeKhông mang phương thức trực tiếpĐưa vào Invoke-CimMethodGọi phương thức

Hình 4: CimInstance không mang phương thức nên gọi phương thức bằng cách đưa vào Invoke-CimMethod.

# Gọi phương thức trên thể hiện: lấy chủ mỗi tiến trình
Get-CimInstance -ClassName Win32_Process -Filter "Name = 'notepad.exe'" |
    Invoke-CimMethod -MethodName GetOwner

# Gọi phương thức tĩnh của lớp: khởi chạy tiến trình
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ CommandLine = 'notepad.exe' }

# Xem định nghĩa lớp (thuộc tính và phương thức)
Get-CimClass -ClassName Win32_Process

3.2. Bảng tương ứng khi di chuyển từ cmdlet WMI cũ

Từ PowerShell 6 trở đi (gồm PowerShell 7 hiện hành), các cmdlet WMI v1 sau đã bị xóa. Cùng chức năng được module CimCmdlets (WMI v2) cung cấp.2

Cũ (tới Windows PowerShell 5.1) Hiện hành (cmdlet CIM) Ghi chú
Get-WmiObject Get-CimInstance Cách nghĩ -Filter / -Query giống nhau
Get-WmiObject -List Get-CimClass Khám phá lớp và xem định nghĩa
Invoke-WmiMethod Invoke-CimMethod Đối số đưa qua hashtable -Arguments @{ }
Register-WmiEvent Register-CimIndicationEvent Đăng ký sự kiện (mục 6.3)
Set-WmiInstance Set-CimInstance Đổi thuộc tính ghi được
Remove-WmiObject Remove-CimInstance Xóa instance

Cmdlet CIM cũng chạy được trên Windows PowerShell 5.1, nên cái viết mới nên viết phía CIM ngay cả khi sẽ chạy trên 5.1 — như vậy không để lại chi phí di chuyển. Toàn cảnh cùng tồn tại và di chuyển giữa 5.1 và 7 nằm trong “Khác biệt giữa Windows PowerShell 5.1 và PowerShell 7”.

Lý do viết tập lệnh mới bằng CIMTập lệnh viết bằng cmdlet WMI chạy trên 5.1 nhưng đã bị xóa từ PowerShell 6 nên phải viết lại khi di chuyển, còn cmdlet CIM dùng được cả trên 5.1 nên viết mới phía CIM thì không để lại chi phí di chuyểnCmdlet WMICmdlet CIMTập lệnh viết mớiViết bằng cái nào?Chạy được trên 5.1Dùng được cả trên 5.1Đã bị xóa trên PowerShell 7Phải viết lại khi di chuyểnKhông để lại chi phí di chuyển

Hình 5: Viết mới bằng cmdlet CIM thì khi sang PowerShell 7 không phải viết lại.

4. Truy vấn từ xa — phiên CIM (WSMan mặc định) và tùy chọn DCOM

Cmdlet CIM, nếu không chỉ định đích, kết nối tới WMI cục bộ qua COM; nếu chỉ định -ComputerName, chúng tạo phiên tạm qua giao thức WSMan (WinRM) để kết nối. Khi thực hiện nhiều thao tác trên cùng một máy, tạo phiên CIM rồi tái sử dụng có lợi hơn về hiệu năng.3

Chọn cách kết nối CIMKhông chỉ định thì kết nối COM tới WMI cục bộ, chỉ định ComputerName thì phiên tạm WSMan được tạo mỗi lần truy vấn, nhiều thao tác trên cùng đích thì tái sử dụng New-CimSession có lợi về hiệu năng, và máy chưa cấu hình WinRM có tùy chọn giao thức DCOMKhôngMột lầnNhiềuChạy cmdlet CIMCó chỉ định ComputerName?Kết nối COM tới WMI cục bộNhiều thao tác trên cùng máy?Phiên tạm WSManTái sử dụng New-CimSessionĐược tạo mỗi lần truy vấnMáy chưa cấu hình WinRMTùy chọn giao thức DCOM

Hình 6: Truy vấn từ xa mặc định dùng WSMan, và nhiều thao tác trên cùng đích thì tái sử dụng phiên CIM là phép tắc.

# Truy vấn một lần thì dùng -ComputerName (mỗi lần tạo phiên tạm)
Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName Server01, Server02

# Truy vấn lặp lại thì tái sử dụng phiên CIM
$session = New-CimSession -ComputerName Server01
Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $session
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" -CimSession $session
Remove-CimSession $session

Với máy không tới được bằng WSMan — như máy cũ không cấu hình được WinRM — bạn có thể chọn giao thức DCOM.4

$dcom = New-CimSessionOption -Protocol Dcom
$session = New-CimSession -ComputerName OldServer -SessionOption $dcom

Điều kiện tiên quyết của truy vấn từ xa như sau.

  • WinRM phải được cấu hình trên máy đích. winrm quickconfig đặt dịch vụ tự khởi động, tạo listener HTTP (cổng mặc định 5985), và đăng ký ngoại lệ tường lửa, tất cả một lần.10 Nếu muốn kết nối HTTPS (cổng mặc định 5986), chỉ vậy chưa đủ — cần chuẩn bị chứng chỉ máy chủ rồi cấu hình riêng listener HTTPS bằng winrm quickconfig -transport:https hoặc tương tự.10
  • Các cổng liên quan phải mở trên tường lửa trên đường đi. Công việc thiết kế và đăng ký quy tắc vào được trình bày trong bài “Windows Firewall và ứng dụng nghiệp vụ”.
  • Xác thực. Trong môi trường domain, Kerberos cung cấp xác thực lẫn nhau. Trong workgroup, Kerberos không dùng được, nên bạn có thể cần đăng ký đích vào TrustedHosts phía máy khách. Giữ danh sách đó hẹp hết mức có thể.10
  • Quyền. Với cấu hình mặc định, truy vấn và thao tác WMI từ xa về cơ bản dùng tài khoản thuộc nhóm quản trị viên trên máy đích. Muốn mở cho người dùng thường, cần cấu hình quyền truy cập trên cả WinRM lẫn không gian tên WMI.10
  • Lưu ý rằng DCOM không có cổng lắng nghe cố định (nó dùng cổng RPC động), nên thiết kế xuyên tường lửa khó hơn. An toàn nhất là coi WSMan là mặc định cho thứ bạn xây từ nay.
Kiểm tra điều kiện tiên quyết của truy vấn từ xaTrên máy đích winrm quickconfig đặt dịch vụ tự khởi động, tạo listener HTTP và đăng ký ngoại lệ tường lửa một lần, listener HTTPS cần chuẩn bị chứng chỉ rồi cấu hình riêng, và môi trường workgroup đôi khi cần đăng ký TrustedHostswinrm quickconfigĐặt dịch vụ tự khởi độngTạo listener HTTP(5985)Ngoại lệ tường lửaListener HTTPS(5986)Chuẩn bị chứng chỉ và cấu hình riêngMôi trường workgroupĐăng ký vào TrustedHosts

Hình 7: winrm quickconfig làm cấu hình mặc định một lần, còn listener HTTPS và xác thực workgroup xử lý riêng.

5. Dùng từ C# — System.Management và Microsoft.Management.Infrastructure

Có hai dòng API để dùng WMI từ C#. Cả hai đều chỉ dành cho Windows.

  System.Management Microsoft.Management.Infrastructure (MI API)
Đưa vào Mặc định trong .NET Framework. Trên .NET hiện hành, gói NuGet System.Management5 Gói NuGet Microsoft.Management.Infrastructure6
Lớp cửa vào ManagementObjectSearcher (đưa WQL để truy vấn)5 CimSession (Create → QueryInstances / InvokeMethod / Subscribe)6
Hệ kiểu ManagementObject / ManagementEventWatcher11 CimInstance / CimSessioncùng kiểu với cmdlet CIM3
Từ xa Dựa trên DCOM Dựa trên WSMan (phiên CIM). Có biến thể bất đồng bộ (*Async)6
Hợp khi Lấy thông tin cục bộ. Giữ tài sản mã sẵn có Gắn truy vấn từ xa và giám sát. Thiết kế đi cùng PowerShell

5.1. System.Management: nền tảng ManagementObjectSearcher

Bạn đưa WQL dạng chuỗi và nhận bộ sưu tập kết quả qua Get().5

// NuGet: System.Management (chỉ Windows)
using System.Management;

using var searcher = new ManagementObjectSearcher(
    @"root\cimv2",
    "SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3");

foreach (ManagementObject disk in searcher.Get())
{
    var freeGb = (ulong)disk["FreeSpace"] / 1024.0 / 1024.0 / 1024.0;
    var sizeGb = (ulong)disk["Size"] / 1024.0 / 1024.0 / 1024.0;
    Console.WriteLine($"{disk["DeviceID"]} trống {freeGb:F1} GB / tổng {sizeGb:F1} GB");
}

Thuộc tính trả về dưới dạng object qua indexer, nên bạn cần xem tài liệu lớp để biết kiểu CIM (ở ví dụ này FreeSpace / Size là uint649) rồi ép kiểu. Tưởng là int rồi ép, dẫn tới InvalidCastException, là vấp ngã kinh điển đầu tiên ở đây.

Cạm bẫy khi lấy thuộc tính và ép kiểuThuộc tính System.Management trả về object qua indexer nên phải xác nhận kiểu CIM trong tài liệu lớp rồi mới ép, và ép vì tưởng là int thì thành InvalidCastExceptionLấy qua indexerTrả về dưới dạng objectXác nhận kiểu CIM trong tài liệuÉp sang kiểu đúngÉp vì tưởng là intInvalidCastException

Hình 8: Thuộc tính trả về object nên xác nhận kiểu CIM rồi mới ép.

5.2. MI API: nền tảng CimSession

CimSession xử lý cục bộ và từ xa cùng một hình dạng. Nó gom liệt kê, truy vấn, gọi phương thức, đăng ký sự kiện, và cả biến thể bất đồng bộ.6

// NuGet: Microsoft.Management.Infrastructure (chỉ Windows)
using Microsoft.Management.Infrastructure;

// Cục bộ thì CimSession.Create(null), từ xa thì truyền tên máy
using CimSession session = CimSession.Create(null);

IEnumerable<CimInstance> disks = session.QueryInstances(
    @"root\cimv2", "WQL",
    "SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3");

foreach (CimInstance disk in disks)
{
    var deviceId = (string)disk.CimInstanceProperties["DeviceID"].Value;
    var free = (ulong)disk.CimInstanceProperties["FreeSpace"].Value;
    Console.WriteLine($"{deviceId} trống {free / 1024.0 / 1024 / 1024:F1} GB");
}

Vì nó làm việc với cùng CimInstance mà cmdlet CIM của PowerShell trả về, luồng phát triển “thử bằng PowerShell rồi chép sang C#” nối tự nhiên. Nếu bạn đang thiết kế chính sự phối hợp C# và PowerShell, cũng xem “Cách chạy PowerShell từ C# (CSharp) và nhận kết quả dưới dạng đối tượng”.

Thử bằng PowerShell rồi chép sang C#Cmdlet CIM của PowerShell và MI API của C# cùng làm việc với kiểu CimInstance nên luồng phát triển thử bằng PowerShell rồi chép sang C# nối tự nhiênThử bằng PowerShellCmdlet CIMTriển khai thật bằng C#MI APICùng kiểu CimInstanceChép sang nối tự nhiên

Hình 9: Cmdlet CIM và MI API cùng kiểu CimInstance nên từ thử tới triển khai thật nối được.

6. Công thức thực tế hay dùng

6.1. Bảng tra nhanh các lớp thường gặp

Thông tin cần lấy Lớp Thuộc tính chính
Hãng / tên model Win32_ComputerSystem Manufacturer, Model
Số serial thân máy Win32_BIOS SerialNumber
Phiên bản OS / giờ khởi động Win32_OperatingSystem Caption, Version, LastBootUpTime
Dung lượng đĩa trống Win32_LogicalDisk DeviceID, FreeSpace, Size, DriveType9
Trạng thái dịch vụ Win32_Service Name, State, StartMode
Danh sách tiến trình Win32_Process Name, ProcessId, CommandLine

6.2. Công thức quản lý tài sản: số serial, tên model và dung lượng đĩa trống

# Thông tin mẫu mã và số sê-ri (để đối chiếu sổ tài sản PC)
$cs   = Get-CimInstance -ClassName Win32_ComputerSystem -Property Manufacturer, Model
$bios = Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber
[pscustomobject]@{
    Manufacturer = $cs.Manufacturer
    Model        = $cs.Model
    Serial       = $bios.SerialNumber
}

# Dung lượng trống trên đĩa cục bộ (DriveType = 3)
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" |
    Select-Object DeviceID,
        @{ Name = 'FreeGB'; Expression = { [math]::Round($_.FreeSpace / 1GB, 1) } },
        @{ Name = 'SizeGB'; Expression = { [math]::Round($_.Size / 1GB, 1) } }

DriveType = 3 là giá trị “ổ đĩa cục bộ”, loại trừ ổ tháo lắp (2), ổ mạng (4) và ổ CD (5).9 Với giám sát, chỉ cần chạy tập lệnh này lần lượt từng máy chủ qua phiên CIM là có nền cho giám sát đĩa không agent.

Nền giám sát đĩa không agentLọc DriveType 3 để loại ổ tháo lắp, ổ mạng và CD, chỉ còn ổ cục bộ, rồi chạy cùng tập lệnh qua phiên CIM lần lượt từng máy chủ thì có nền giám sát đĩa không agentTập lệnh lấy dung lượng trốngLọc DriveType = 3Loại trừ ổ tháo lắp v.v.Qua phiên CIMChạy lần lượt từng máy chủGiám sát không agent

Hình 10: Chạy tập lệnh đã lọc ổ cục bộ qua phiên CIM lần lượt từng máy chủ là nền của giám sát.

6.3. Phát hiện tiến trình khởi chạy — đăng ký sự kiện

Thay vì “định kỳ lấy Win32_Process bằng polling rồi so sai khác”, hãy dùng đăng ký sự kiện. Cách đơn giản để bắt tiến trình khởi chạy là đăng ký Win32_ProcessStartTrace (lớp sự kiện của kernel trace provider, với thuộc tính như ProcessName / ProcessID / ParentProcessID8).

# Chạy từ phiên PowerShell với quyền quản trị
$action = {
    $name = $Event.SourceEventArgs.NewEvent.ProcessName
    $id   = $Event.SourceEventArgs.NewEvent.ProcessID
    Write-Host "Tiến trình khởi chạy: $name (PID=$id)"
}
Register-CimIndicationEvent -ClassName Win32_ProcessStartTrace `
    -SourceIdentifier ProcessStarted -Action $action

Đăng ký còn hiệu lực suốt thời phiên PowerShell đã đăng ký còn sống, và -Action chạy mỗi khi một tiến trình khởi chạy. Đừng chạy luôn lệnh hủy ngay sau đó trong cùng một lô — làm vậy chỉ khiến đăng ký biến mất trước khi giám sát kịp bắt đầu. Chỉ chạy bước hủy khi bạn kết thúc giám sát.

# Khi kết thúc giám sát: hủy đăng ký
Unregister-Event -SourceIdentifier ProcessStarted

Register-CimIndicationEvent đăng ký theo tên lớp hoặc truy vấn sự kiện WQL, và khối script -Action chạy mỗi lần sự kiện đến.7 Đăng ký lớp này cần quyền quản trị viên.7 Ai nhận được sự kiện do mô tả bảo mật của lớp sự kiện kiểm soát, và người dùng thường không nâng quyền sẽ bị từ chối truy cập.8

Luồng đăng ký sự kiện khởi chạy tiến trìnhPhiên PowerShell với quyền quản trị viên dùng Register-CimIndicationEvent để đăng ký, mỗi khi tiến trình khởi chạy sự kiện đến và Action chạy, rồi Unregister-Event hủy khi kết thúc giám sátWMIPhiên PowerShellWMIPhiên PowerShellChạy với quyền quản trị viênĐăng ký bằng Register-CimIndicationEventSự kiện đến mỗi khi tiến trình khởi chạyThực thi -ActionHủy bằng Unregister-Event(khi kết thúc giám sát)

Hình 11: Đăng ký còn hiệu lực suốt thời phiên đã đăng ký còn sống, và hủy khi kết thúc giám sát.

Cách khác là sự kiện tạo instance chung (__InstanceCreationEvent), dùng được với lớp bất kỳ. Cơ chế này để WMI polling theo khoảng bạn chỉ định bằng WITHIN rồi biến sai khác thành sự kiện, nên bạn tự quyết đánh đổi giữa khoảng phát hiện và tải.

Hai cách đăng ký để phát hiện tiến trình khởi chạyWin32_ProcessStartTrace đăng ký lớp sự kiện của kernel trace provider, còn __InstanceCreationEvent chung để WMI polling theo khoảng WITHIN rồi biến sai khác thành sự kiện nên bạn tự quyết đánh đổi khoảng phát hiện và tảiPhát hiện tiến trình khởi chạyWin32_ProcessStartTrace__InstanceCreationEventĐăng ký kernel tracePolling theo khoảng WITHINĐánh đổi khoảng và tải

Hình 12: Đăng ký lớp sự kiện chuyên biệt, hoặc dùng sự kiện tạo instance chung kèm khoảng polling.

# Giám sát thể hiện Win32_Process mới bằng polling mỗi 5 giây
$query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"
Register-CimIndicationEvent -Query $query -SourceIdentifier ProcPoll -Action {
    Write-Host "Khởi chạy: $($Event.SourceEventArgs.NewEvent.TargetInstance.Name)"
}

Trong C# (System.Management), ManagementEventWatcher đóng cùng vai trò.11

using System.Management;

// Từ tiến trình đang chạy với quyền quản trị
var watcher = new ManagementEventWatcher(
    new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
watcher.EventArrived += (_, e) =>
{
    var name = (string)e.NewEvent["ProcessName"];
    var pid  = (uint)e.NewEvent["ProcessID"];
    Console.WriteLine($"Tiến trình khởi chạy: {name} (PID={pid})");
};
watcher.Start();
// Khi kết thúc giám sát đừng quên watcher.Stop() và Dispose

Nếu gắn vào giám sát thường trú, hãy đưa cả việc đăng ký lại khi đăng ký đứt (lúc dịch vụ khởi động lại hay khi lỗi) vào thiết kế. Luận thiết kế “kiểm tra và hiện trạng thái”, gồm giám sát thiết bị, nằm trong “Thực hành tốt nhất khi kiểm tra và hiển thị trạng thái thiết bị ngoài”.

Vòng đời đăng ký của giám sát thường trúGiám sát thường trú có lúc trạng thái đang theo dõi bị đứt vì dịch vụ khởi động lại hay lỗi nên thiết kế phải gồm phát hiện đứt rồi đăng ký lại để trở về đang theo dõiKhởi động lại dịch vụ · lỗiĐang theo dõiĐăng ký đã đứtĐăng ký lại

Hình 13: Giám sát thường trú cần thiết kế đăng ký lại khi đăng ký đứt để trở về đang theo dõi.

7. Cạm bẫy — hiệu năng, quyền, 64-bit, repository và ngày

7.1. SELECT * và polling quá dày

Truy vấn WMI là “provider dựng giá trị tại chỗ” — không miễn phí. Có hai anti-pattern kinh điển.

  • Dùng SELECT * theo thói quen. Lấy mọi thuộc tính mọi hàng của Win32_Process làm công việc của provider và lưu lượng mạng (khi từ xa) phình theo. Lọc hàng bằng -Filter, lọc cột bằng -Property, và dùng -KeyOnly nếu bạn chỉ cần khóa cho thao tác tiếp. Tất cả đều là phương tiện chính thức “để giảm kích thước đối tượng và lưu lượng mạng.”3
  • Polling chu kỳ ngắn. Thiết kế kiểu “Get-CimInstance Win32_Process mỗi giây” nên thay bằng đăng ký sự kiện ở mục 6.3. Dù phải dùng kiểu polling (WITHIN), hãy nới khoảng tới mức thật sự đủ cho yêu cầu.

Ngoài ra, lặp -ComputerName từng máy một với máy từ xa cũng lãng phí, vì phiên tạm được tạo cho mỗi lần truy vấn — hãy đổi sang tái sử dụng phiên CIM cho nhiều thao tác.3

Anti-pattern hiệu năng và chỗ thayDùng SELECT * theo thói quen thì lọc hàng và cột bằng Filter và Property, chỉ cần khóa thì dùng KeyOnly, polling chu kỳ ngắn thì thay bằng đăng ký sự kiện, còn lặp ComputerName từng máy thì tái sử dụng phiên CIMDùng SELECT * theo thói quenLọc bằng Filter và PropertyChỉ khóa thì dùng KeyOnlyPolling chu kỳ ngắnThay bằng đăng ký sự kiệnComputerName từng máy mộtTái sử dụng phiên CIM

Hình 14: Lọc hàng · cột · khóa và thay bằng đăng ký sự kiện ngăn khoảng nửa vấn đề hiệu năng của WMI.

7.2. Quyền cho đăng ký sự kiện

Như mục 6.3, đăng ký họ Win32_ProcessStartTrace lấy quyền quản trị viên làm tiền đề.7 “Máy phát triển (chạy với quản trị viên) thì được, nhưng môi trường người dùng thường phía khách hàng thì giám sát không chạy” là tai nạn kinh điển, sánh với hộp thoại thông báo tường lửa. Nếu gắn giám sát vào ứng dụng nghiệp vụ chạy dưới người dùng thường, hãy cân nhắc tách phần giám sát ra dịch vụ Windows (chạy dưới LocalSystem chẳng hạn) và nối với ứng dụng chính bằng giao tiếp liên tiến trình.

Cấu hình giám sát trong môi trường người dùng thườngĐăng ký lấy quyền quản trị viên làm tiền đề thì tách khỏi ứng dụng chính chạy dưới người dùng thường, đưa phần giám sát sang dịch vụ Windows chạy dưới LocalSystem v.v., rồi nối với ứng dụng chính bằng giao tiếp liên tiến trìnhGiao tiếp liên tiến trìnhDịch vụ Windows giám sátĐăng ký start traceChạy dưới LocalSystem v.v.Ứng dụng chính(người dùng thường)

Hình 15: Đăng ký cần quyền quản trị viên thì tách sang phía dịch vụ, rồi nối với ứng dụng chính bằng giao tiếp liên tiến trình.

7.3. 32-bit/64-bit và provider

Trên Windows 64-bit, một số provider tồn tại cả bản 32-bit lẫn 64-bit, và mặc định phía khớp bitness của ứng dụng gọi trả lời.12 Ví dụ điển hình là provider registry (StdRegProv) dưới root\default: đọc từ ứng dụng 32-bit trả về giá trị phía Wow6432Node (view 32-bit).12 Khi “giá trị registry đọc qua WMI không khớp những gì regedit hiện”, hãy nghi điều này trước. Nếu cần view phía kia, bạn có thể yêu cầu tường minh bằng cách đặt __ProviderArchitecture (và, nếu muốn ép, __RequiredArchitecture) trong ngữ cảnh kết nối.12 Toàn cảnh bài toán bitness cũng nằm trong “Gọi Win32 API an toàn từ C# — hướng dẫn thực hành P/Invoke”.

Chọn provider trên môi trường 64-bitMặc định provider khớp bitness của ứng dụng gọi trả lời, truy vấn registry từ ứng dụng 32-bit nhận giá trị phía Wow6432Node, nhưng chỉ định __ProviderArchitecture thì yêu cầu tường minh được view phía kia32bit64bitBitness của bên gọi?Provider 32-bit trả lờiProvider 64-bit trả lờiRegistry lấy giá trị phía Wow6432NodeChỉ định __ProviderArchitectureYêu cầu tường minh view phía kia

Hình 16: Mặc định phía khớp bitness của bên gọi trả lời, nên ứng dụng 32-bit đọc phía Wow6432Node.

7.4. Triệu chứng và xử lý khi WMI repository hỏng

Định nghĩa lớp WMI được lưu trong repository (không phải một tệp đơn — các tệp trong thư mục Repository cùng hoạt động như một cơ sở dữ liệu13). Khi nó mất nhất quán, lỗi kiểu “lớp lẽ ra tồn tại thì không tìm thấy” hay “không gian tên không hợp lệ” bắt đầu xuất hiện, dù phía ứng dụng chẳng đổi gì. Dùng winmgmt.exe để chẩn đoán và sửa.13

rem Kiểm tra tính nhất quán (kết quả inconsistent nghĩa là có lệch)
winmgmt /verifyrepository

rem Kiểm tra tính nhất quán và dựng lại nếu lệch (nội dung đọc được được gộp)
winmgmt /salvagerepository

Điều quan trọng là đừng lấy xóa hay khởi tạo repository làm bước đầu. Lỗi lộ qua WMI có thể bắt nguồn từ phần khác của OS, và chính Microsoft nói rõ rằng xóa repository làm phản ứng đầu “có thể gây tổn hại cho hệ thống hoặc ứng dụng đã cài.”13 Giữ thứ tự: kiểm tra bằng /verifyrepository, rồi sửa bằng /salvagerepository.

Quy trình tách nguyên nhân khi WMI repository mất nhất quánKhi có lỗi lớp không tìm thấy v.v. thì kiểm tra nhất quán bằng winmgmt verifyrepository, nếu mất nhất quán thì dựng lại bằng salvagerepository, và không lấy xóa hay khởi tạo repository làm bước đầuKhôngLỗi lớp không tìm thấy v.v.winmgmt /verifyrepositoryKết quả là inconsistent?winmgmt /salvagerepositoryNghi nguyên nhân ở phần khác của OSNội dung đọc được được mergeXóa · khởi tạo repositoryKhông dùng làm bước đầu

Hình 17: Giữ thứ tự verify rồi salvage để sửa, đừng lấy xóa làm bước đầu.

7.5. Chuyển đổi định dạng ngày DMTF

Ngày WMI được lưu dạng chuỗi theo định dạng DMTF của đặc tả CIM: yyyymmddHHMMSS.mmmmmm±UUU (phần cuối là lệch so với UTC tính bằng phút — ví dụ 20260801100000.000000+540). Đừng cắt dán giá trị thô bằng xử lý chuỗi; hãy dùng API chuyển đổi.

  • C# (System.Management): ManagementDateTimeConverter cung cấp chuyển đổi giữa dạng DMTF và DateTime / TimeSpan.11
  • API họ CIM (Get-CimInstance / MI API): thuộc tính ngày trả về đã chuyển thành DateTime, nên bạn không gặp bài toán này ngay từ đầu. (Get-CimInstance Win32_OperatingSystem).LastBootUpTime dùng trực tiếp như DateTime trong tính toán.
Cách xử lý định dạng ngày DMTFNgày WMI được lưu dạng chuỗi DMTF, nếu đọc giá trị thô bằng System.Management thì chuyển bằng ManagementDateTimeConverter, còn API họ CIM thì đã trả DateTime sẵn nên không tự cắt dán chuỗiSystem.ManagementAPI họ CIMChuỗi dạng DMTFLấy bằng API nào?ManagementDateTimeConverterĐã chuyển thành DateTimeChuyển sang DateTime / TimeSpanTự cắt dán chuỗiKhông dùng

Hình 18: Để API chuyển đổi lo chuỗi DMTF, còn API họ CIM thì dùng DateTime đã chuyển sẵn.

8. Khi không nên dùng WMI — bảng quyết định công cụ

WMI xuất sắc như “cửa đọc thống nhất”, nhưng không phải lúc nào cũng tối ưu. Đây là thước đo thực tế để chọn công cụ.

Việc muốn làm Công cụ đúng Vì sao không chọn WMI
Lấy thông tin phần cứng và cấu hình OS, truy vấn từ xa không agent WMI/CIM Đây đúng là sân nhà của WMI — thống nhất hơn việc gọi từng API chuyên biệt
Đọc ghi thiết lập của chính ứng dụng Đọc registry trực tiếp (Microsoft.Win32.Registry) hoặc tệp cấu hình Thao tác registry qua WMI là đường vòng, và còn mang theo bài toán bitness ở mục 7.3
Giám sát hiệu năng liên tục tần suất cao như CPU Bộ đếm hiệu năng (System.Diagnostics.PerformanceCounter, v.v.) Counter được làm đúng cho việc này. Polling WMI chu kỳ ngắn thua cả tải lẫn độ chính xác
Gọi chức năng OS một lần, hoặc xử lý cần độ trễ thấp Win32 API (P/Invoke) WMI mang phí đi qua COM/provider
Liệt kê và thao tác tiến trình cục bộ khi quyền của chính tiến trình đủ System.Diagnostics.Process Tự đủ trong thư viện chuẩn, ít phụ thuộc hơn
Cấu hình tính năng quản lý Windows như tường lửa hay mạng Cmdlet CIM chuyên biệt như Get-NetFirewallRule Bộ cmdlet xây và duy trì cho một mục đích cụ thể chính xác và an toàn hơn việc lần lớp WMI thô
Phát hiện thay đổi tệp hay thư mục FileSystemWatcher Đừng đưa WMI vào vùng đã có API chuyên biệt

Trục phán đơn giản: ở vùng đã có cơ chế chuyên biệt thì dùng cơ chế chuyên biệt, và dành WMI/CIM cho truy vấn xuyên suốt cùng truy vấn từ xa. Ví dụ Get-NetFirewallRule ở hàng cuối, bên trong, là bộ cmdlet dựng trên CIM — dạng “hưởng lợi ích của WMI/CIM mà không đụng trực tiếp.”

Trục phán khi chọn công cụỞ vùng đã có cơ chế chuyên biệt thì dùng cơ chế chuyên biệt, còn truy vấn xuyên suốt hay truy vấn từ xa ở vùng không có thì dùng WMI và CIM, và cmdlet CIM chuyên biệt là dạng chỉ hưởng lợi ích mà không đụng WMI và CIM trực tiếpKhôngCó cơ chế chuyên biệt?Dùng cơ chế chuyên biệtDùng WMI / CIMTruy vấn xuyên suốt · truy vấn từ xaCmdlet CIM chuyên biệtDạng chỉ hưởng lợi ích

Hình 19: Ở vùng đã có cơ chế chuyên biệt thì dùng chuyên biệt, và dành WMI/CIM cho truy vấn xuyên suốt cùng truy vấn từ xa.

9. Tóm tắt

  • CIM là chuẩn ngành của DMTF, WMI là triển khai của Microsoft cho chuẩn đó. Cả cmdlet CIM của PowerShell lẫn MI API của C# đều là cửa vào thế hệ hiện hành bám chuẩn này.
  • Trên PowerShell, Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent là hiện hành. Get-WmiObject và các cmdlet WMI khác không tồn tại trên PowerShell 7, nên tập lệnh mới viết phía CIM ngay cả khi nhắm 5.1.
  • Truy vấn từ xa mặc định dùng WSMan (WinRM), và nhiều thao tác thì tái sử dụng phiên CIM. Với máy chưa cấu hình WinRM, DCOM là đường thoát có sẵn.
  • Trên C#, chọn giữa System.Management (tiện, hướng cục bộ) và Microsoft.Management.Infrastructure (hướng từ xa và giám sát, cùng hệ kiểu với cmdlet CIM). Cả hai đều là gói NuGet chỉ dành cho Windows.
  • Giám sát tiến trình bằng đăng ký sự kiện, không polling. Đăng ký Win32_ProcessStartTrace cần quyền quản trị viên.
  • Tránh SELECT * và polling chu kỳ ngắn — lọc bằng -Filter / -Property / -KeyOnly. Nhớ rằng truy vấn từ tiến trình 32-bit được provider 32-bit phục vụ, ngày DMTF cần API chuyển đổi, và repository hỏng thì xử lý theo thứ tự verify → salvage, không xóa.
  • Đừng đưa WMI vào vùng đã có cơ chế chuyên biệt (thiết lập, bộ đếm hiệu năng, gọi API một lần) — dành WMI/CIM cho truy vấn xuyên suốt và truy vấn từ xa. Một câu đó tóm chỗ đứng của nó.

Bài viết liên quan

Lĩnh vực tư vấn liên quan

KomuraSoft LLC đảm nhận việc gắn lấy thông tin phần cứng, giám sát tiến trình và truy vấn PC từ xa bằng WMI/CIM vào ứng dụng nghiệp vụ, di chuyển tập lệnh nội bộ dựa trên Get-WmiObject sang cmdlet CIM, và điều tra loại sự cố “máy phát triển chạy được nhưng phía khách hàng báo lỗi quyền.” Chúng tôi hỗ trợ xuyên suốt từ thử bằng PowerShell đến triển khai thật bằng C#.

Liên kết tham khảo

  1. Microsoft Learn, About WMI. Về việc WMI là triển khai của Microsoft cho WBEM (sáng kiến ngành phát triển công nghệ chuẩn để truy cập thông tin quản lý trong môi trường doanh nghiệp), biểu diễn đối tượng quản lý bằng chuẩn ngành CIM (Common Information Model) do DMTF (Distributed Management Task Force) phát triển và duy trì; về MI (Windows Management Infrastructure) thế hệ kế tương thích hoàn toàn với WMI cũ; và về kết nối WMI từ xa dùng DCOM, với WinRM dựa trên WS-Management như lựa chọn thay.  2 3 4 5

  2. Microsoft Learn, Differences between Windows PowerShell 5.1 and PowerShell 7.x. Về việc các cmdlet WMI v1 (Register-WmiEvent / Set-WmiInstance / Invoke-WmiMethod / Get-WmiObject / Remove-WmiObject) đã bị xóa khỏi PowerShell, và các cmdlet module CimCmdlets (WMI v2) cung cấp cùng chức năng với tính năng mới và cú pháp thiết kế lại.  2

  3. Microsoft Learn, Get-CimInstance (CimCmdlets). Về việc không chỉ định ComputerName lẫn CimSession thì kết nối tới WMI cục bộ qua phiên COM, còn khi chỉ định -ComputerName thì tạo phiên tạm qua giao thức WsMan; về việc kết nối qua phiên CIM được khuyến nghị về hiệu năng khi thực hiện nhiều thao tác trên cùng máy; về -Filter là mệnh đề where WQL/CQL không gồm từ khóa WHERE; về -Property và -KeyOnly giảm kích thước đối tượng và lưu lượng mạng; về không gian tên mặc định là root/CIMV2 và ngôn ngữ truy vấn mặc định (-QueryDialect) là WQL; về đầu ra là Microsoft.Management.Infrastructure.CimInstance; về ví dụ gọi GetOwner kết hợp Invoke-CimMethod; và về cmdlet chỉ dành cho Windows.  2 3 4 5 6 7 8 9 10

  4. Microsoft Learn, New-CimSessionOption (CimCmdlets). Về việc tùy chọn phiên CIM có hai bộ tham số, cho WsMan và cho DCOM; về -Protocol nhận Dcom / Default / Wsman; về ví dụ đưa tùy chọn tạo bằng New-CimSessionOption -Protocol Dcom vào -SessionOption của New-CimSession để tạo phiên CIM DCOM; và về mức giả danh mặc định của phiên DCOM là Impersonate.  2

  5. Microsoft Learn, ManagementObjectSearcher Class (System.Management). Về đây là lớp cửa vào phổ biến nhất để lấy thông tin quản lý, lấy bộ sưu tập đối tượng quản lý dựa trên truy vấn WQL chỉ định; về nó nhận ObjectQuery và ManagementScope (không gian tên WMI) rồi trả ManagementObjectCollection qua Get(); và về System.Management.dll được cung cấp như gói NuGet System.Management.  2 3 4

  6. Microsoft Learn, CimSession Class (Microsoft.Management.Infrastructure). Về Microsoft.Management.Infrastructure.dll được cung cấp như gói NuGet Microsoft.Management.Infrastructure; về tạo phiên qua Create(computerName); về thực thi truy vấn qua QueryInstances(namespace, queryDialect, query); và về nó cung cấp EnumerateInstances / GetInstance / InvokeMethod / Subscribe cùng biến thể bất đồng bộ (*Async) của từng cái, đồng thời triển khai IDisposable.  2 3 4 5

  7. Microsoft Learn, Register-CimIndicationEvent (CimCmdlets). Về việc đăng ký indication (sự kiện) theo tên lớp hoặc biểu thức truy vấn và đặt tên đăng ký bằng -SourceIdentifier; về ví dụ đăng ký Win32_ProcessStartTrace, kèm ghi chú rằng cần chạy PowerShell với quyền quản trị viên; về ví dụ tham chiếu ProcessName / ProcessId từ $Event.SourceEventArgs.NewEvent trong khối script -Action; về kết nối qua phiên tạm WsMan khi chỉ định -ComputerName, và cục bộ qua COM khi không chỉ định; và về dùng Unregister-Event để hủy đăng ký.  2 3 4

  8. Microsoft Learn, Win32_ProcessStartTrace class. Về đây là lớp sự kiện báo một tiến trình mới khởi chạy, với thuộc tính gồm ProcessName / ProcessID / ParentProcessID / SessionID / Sid; về thuộc tính SECURITY_DESCRIPTOR là mô tả mà event provider dùng để quyết người dùng nào nhận được sự kiện; và về không gian tên là Root\CIMV2, do kernel trace provider (Krnlprov.dll) cung cấp.  2 3

  9. Microsoft Learn, Win32_LogicalDisk class. Về Win32_LogicalDisk là lớp dẫn xuất từ CIM_LogicalDisk biểu diễn thiết bị lưu trữ cục bộ; về giá trị DriveType (2 = ổ tháo lắp, 3 = ổ đĩa cục bộ, 4 = ổ mạng, 5 = CD, v.v.); về FreeSpace / Size là giá trị byte uint64; về DeviceID là khóa; và về ví dụ truy vấn VBScript / C# lọc DriveType = 3.  2 3 4

  10. Microsoft Learn, Installation and configuration for Windows Remote Management. Về việc mặc định listener WinRM chưa được cấu hình nên không gửi nhận được thông điệp WS-Management; về winrm quickconfig đặt dịch vụ tự khởi động, cấu hình listener HTTP/HTTPS, và đăng ký ngoại lệ tường lửa; về cổng mặc định của WinRM 2.0 là HTTP 5985 / HTTPS 5986; về đặt TrustedHosts hẹp hết mức khi không thiết lập được xác thực lẫn nhau (Kerberos), như trong workgroup; và về mô tả bảo mật mặc định (RootSDDL) kiểm soát truy cập từ xa tới listener, cùng cấu hình thêm cần thiết để cho phép người dùng không phải quản trị viên dùng plugin WMI.  2 3 4

  11. Microsoft Learn, System.Management Namespace. Về đây là không gian tên truy vấn hạ tầng WMI qua họ lớp ManagementObjectSearcher, và xử lý đăng ký sự kiện qua ManagementEventWatcher; về WqlEventQuery biểu diễn truy vấn sự kiện dạng WQL; và về ManagementDateTimeConverter cung cấp phương thức chuyển giữa biểu diễn ngày/giờ và khoảng thời gian DMTF với DateTime / TimeSpan của CLR.  2 3

  12. Microsoft Learn, Requesting WMI Data on a 64-bit Platform. Về việc, khi provider tồn tại cả bản 32-bit lẫn 64-bit, mặc định provider 32-bit trả lời ứng dụng 32-bit (gồm script) và provider 64-bit trả lời ứng dụng 64-bit; về việc có thể yêu cầu hoặc ép phiên bản provider không mặc định qua __ProviderArchitecture (32 hoặc 64) và __RequiredArchitecture của ngữ cảnh (WBEM_E_PROVIDER_LOAD_FAILURE xảy ra nếu ép phiên bản không có); và về ví dụ provider registry trong đó máy khách 32-bit nhận dữ liệu phía HKLM\SOFTWARE\Wow6432Node.  2 3

  13. Microsoft Learn, winmgmt. Về /verifyrepository của winmgmt.exe kiểm tra nhất quán WMI repository; về /salvagerepository kiểm tra nhất quán rồi, nếu phát hiện mất nhất quán, dựng lại repository đồng thời merge nội dung đọc được; về /resetrepository khôi phục repository về trạng thái lúc cài OS lần đầu; về repository hoạt động như cơ sở dữ liệu gồm các tệp trong thư mục Repository; và về lỗi lộ qua WMI đôi khi bắt nguồn từ phần khác của OS, nên tránh xóa repository làm phản ứng đầu vì có thể gây tổn hại cho hệ thống hoặc ứng dụng đã cài.  2 3

Các bài viết gần đây có cùng thẻ để tìm hiểu sâu hơn những chủ đề lân cận.

Các trang này đặt chủ đề trong bối cảnh rộng hơn của dịch vụ và quyết định.

Bài viết liên quan trực tiếp đến các dịch vụ sau.

Câu hỏi thường gặp

Các câu hỏi thường gặp khi tư vấn về chủ đề của bài viết.

WMI và CIM khác nhau thế nào?
CIM là "mô hình chuẩn ngành để biểu diễn đối tượng quản lý như hệ thống và thiết bị", do DMTF (Distributed Management Task Force) soạn thảo và duy trì. WMI là triển khai của Microsoft cho WBEM — sáng kiến dùng chuẩn đó — và được gắn sẵn trong Windows. Nói cách khác, CIM là đặc tả, WMI là triển khai trên Windows. Get-CimInstance của PowerShell và Microsoft.Management.Infrastructure của C# tự gọi là "CIM" vì chúng là API bám chuẩn này, nhưng điểm kết nối vẫn là cùng một nền tảng WMI. Với phát triển hàng ngày, hiểu là "truy vấn lớp WMI (Win32_* và tương tự) qua API họ CIM" là đủ cho thực tế.
Get-WmiObject không còn dùng được nữa sao?
Trên Windows PowerShell 5.1 nó vẫn chạy, nhưng từ PowerShell 6 trở đi (gồm PowerShell 7 hiện hành), các cmdlet WMI v1 — Get-WmiObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance và Remove-WmiObject — đã bị xóa và không chạy được. Cùng chức năng đó nằm trong module CimCmdlets (Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent, v.v.). Tập lệnh viết mới nên viết bằng cmdlet CIM ngay cả khi sẽ chạy trên 5.1. Làm vậy thì khi di chuyển sang PowerShell 7 bạn không phải viết lại phần WMI.
Từ C# nên dùng System.Management hay Microsoft.Management.Infrastructure để truy cập WMI?
Cả hai đều chỉ dành cho Windows, và từ .NET hiện hành bạn đưa chúng vào như gói NuGet. System.Management là API cổ điển, dùng được chỉ bằng cách đưa WQL vào ManagementObjectSearcher, và đủ nếu bạn chủ yếu lấy thông tin cục bộ. Nó cũng gồm ManagementDateTimeConverter để chuyển ngày DMTF. Còn Microsoft.Management.Infrastructure (MI API) chia sẻ cùng hệ kiểu (CimSession / CimInstance) với cmdlet CIM của PowerShell, và xử lý thống nhất truy vấn từ xa qua WSMan, biến thể phương thức bất đồng bộ, cùng đăng ký sự kiện (Subscribe). Nếu bạn gắn truy vấn PC từ xa và giám sát vào sản phẩm thật, chọn MI API là hợp lý.
Get-CimInstance không kết nối được tới PC từ xa. Nên kiểm tra gì?
Trước hết kiểm tra WinRM đã được cấu hình trên máy đích chưa. Thao tác CIM có -ComputerName tạo phiên tạm qua giao thức WSMan (WinRM), nên giả định dịch vụ WinRM và listener đang chạy trên đích. winrm quickconfig thực hiện cấu hình mặc định (khởi động dịch vụ, tạo listener, đăng ký ngoại lệ tường lửa). Cổng mặc định là 5985 cho HTTP và 5986 cho HTTPS, nên cũng kiểm tra tường lửa trên đường đi. Trong môi trường workgroup, xác thực lẫn nhau qua Kerberos không dùng được, nên bạn có thể cần đăng ký đích vào TrustedHosts phía máy khách. Với máy tuyệt đối không cấu hình được WinRM, bạn có thể kết nối qua DCOM bằng tùy chọn tạo từ New-CimSessionOption -Protocol Dcom.
Vì sao ngày WMI trả về dạng "20260801100000.000000+540"?
Ngày WMI được lưu theo chuỗi do đặc tả CIM của DMTF quy định (yyyymmddHHMMSS.mmmmmm±UUU, phần cuối là lệch so với UTC tính bằng phút). Nếu bạn đọc giá trị thô bằng Get-WmiObject cũ hoặc System.Management, chuỗi này trả về nguyên vậy. Trong C# (System.Management), ManagementDateTimeConverter cung cấp phương thức chuyển giữa dạng DMTF và DateTime / TimeSpan, nên dùng chúng thay vì tự cắt dán chuỗi. Lưu ý rằng khi lấy dữ liệu qua API họ CIM như Get-CimInstance, thuộc tính ngày đã được chuyển thành DateTime sẵn, nên bạn không gặp bài toán này ngay từ đầu.

Hồ sơ tác giả

Trang giới thiệu tác giả bài viết.

Go Komura

Đại diện của KomuraSoft LLC

Chuyên về phát triển phần mềm Windows, tư vấn kỹ thuật và điều tra lỗi, đặc biệt trong các dự án có hệ thống hiện hữu và lỗi khó tái hiện.

Liên kết công khai

Quay lại blog