WMI/CIM을 C#·PowerShell에서 쓰기 ── 하드웨어 정보 가져오기·프로세스 모니터링·원격 조회의 실무 가이드

· 업데이트: · · Windows, C#, .NET, PowerShell, WMI, CIM, 업무 앱, Windows 개발

수정 이력(4건, 최종 수정 2026년 08월 22일)

이 글에 적용한 변경 사항의 기록입니다. 보관해 둔 수정 전 버전은 DOI가 부여된 고정 URL에서 읽을 수 있습니다.

지식 맵의 관계를 전면 점검해, 설명과 어긋나 있던 관계(방향 반전·과도한 일반화·술어 혼동)를 고쳤습니다. 본문 설명은 바꾸지 않았습니다.
지식 맵의 관계를 전면 점검해, 설명과 어긋나 있던 관계(방향 반전·과도한 일반화·술어 혼동)를 고쳤습니다. 본문 설명은 바꾸지 않았습니다.
지식 맵의 「이벤트 구독은 폴링에 권장된다」는 관계를 「이벤트 구독은 폴링을 대체한다」로 고쳤습니다. 본문 설명은 바꾸지 않았습니다.
구조 설명을 그림으로 따라갈 수 있도록 Mermaid 그림 19점을 추가했습니다. 업무 앱의 흔한 요구와 WMI/CIM의 대응, CIM 표준과 WMI 구현의 관계, WQL 조회가 네임스페이스에서 공급자로 이어지는 구조, CimInstance의 메서드 호출, 새 스크립트를 CIM cmdlet으로 쓰는 이유, 원격 연결 방식 선택과 WinRM 전제 구성, PowerShell 시제품에서 C#으로의 옮겨 적기, 속성 캐스트의 함정, 에이전트 없는 디스크 모니터링의 토대, 프로세스 시작 이벤트 구독의 흐름과 두 구독 방식의 대비, 상주 모니터링의 구독 재등록, 조회 범위 축소에 따른 성능 대책, 일반 사용자 환경의 모니터링 구성, 64bit 환경의 공급자 선택, 리포지토리 불일치 시 원인 분리 절차, DMTF 날짜 형식 처리, 수단 판단의 축을 그림으로 담았습니다. 본문 문장과 코드, 참고 링크는 바꾸지 않았습니다.
최초 공개
이 글을 인용하기(DOI(등록된 아카이브): 10.5281/zenodo.22175762)

아래 DOI는 이전에 등록된 아카이브를 가리키며 현재 본문과 다를 수 있습니다. 현재 본문을 참조할 때는 이 페이지의 URL을 사용하세요.

Go Komura (2026). 「WMI/CIM을 C#·PowerShell에서 쓰기 ── 하드웨어 정보 가져오기·프로세스 모니터링·원격 조회의 실무 가이드」. 합동회사 코무라소프트. https://comcomponent.com/ko/blog/wmi-cim-practical-guide/

DOI(등록된 아카이브)
10.5281/zenodo.22175762
DOI(마지막 등록 버전)
10.5281/zenodo.22175763

「PC 시리얼 번호와 모델명을 업무 앱 화면에 띄우고 싶다」「서버 디스크 여유 공간을 모니터링해 경고하고 싶다」「특정 프로세스가 시작된 것을 감지하고 싶다」「떨어진 곳의 PC 상태를 한꺼번에 조회하고 싶다」── Windows 업무 앱이나 관리 도구를 만들 때 이런 요구는 흔합니다. 그리고 그 흔한 답이 WMI(Windows Management Instrumentation), 표준 이름으로 말하면 CIM(Common Information Model)입니다.

흔한 요구와 WMI/CIM시리얼 번호와 모델명 표시, 디스크 여유 공간 모니터링, 프로세스 시작 감지, 원격 PC 조회라는 업무 앱의 흔한 요구에 대한 흔한 답이 WMI이며, 표준 이름으로 말하면 CIM이다시리얼 번호·모델명WMI(표준 이름은 CIM)디스크 여유 공간 모니터링프로세스 시작 감지원격 PC 조회

그림 1: 업무 앱에서 흔한 네 가지 요구에 대한 흔한 답이 WMI/CIM.

골치 아픈 점은 WMI 관련 정보가 옛것과 새것이 뒤섞여 있다는 것입니다. 검색하면 Get-WmiObject를 쓴 10년 전 글과 Get-CimInstance를 쓴 글이 같이 나오고, C# 쪽도 System.ManagementMicrosoft.Management.Infrastructure 두 계통이 있습니다. 어느 쪽이 현재 작성법이고, 어느 쪽이 「지금도 동작하지만 새로 고르지 않는」 작성법인지 알기 어렵습니다. 실제로 Get-WmiObject는 PowerShell 7에 없어서, 5.1용으로 쓴 사내 스크립트를 옮길 때 갑자기 드러납니다.

이 글에서는 업무 앱에서 하드웨어 정보 가져오기·프로세스 모니터링·원격 PC 조회를 구현하는 C#/PowerShell 개발자를 대상으로, WMI/CIM 구조의 최소 이해부터 PowerShell CIM cmdlet, C#의 두 API, 자주 쓰는 실무 레시피, 성능·권한·64bit의 함정, 그리고 「WMI를 쓰지 말아야 할 장면」의 판단까지를 2026년 8월 시점의 1차 자료를 바탕으로 정리합니다.

1. 먼저 결론

  • CIM은 DMTF가 제정하는 관리 정보의 업계 표준이고, WMI는 그 Microsoft 구현입니다. PowerShell이나 C#의 「CIM」 계열 API는 이 표준을 따른 현재 세대 API이며, 연결 대상은 같은 WMI 기반입니다.1
  • PowerShell의 현재 선택은 CIM cmdlet(Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent)입니다. 구 WMI cmdlet(Get-WmiObject 등 5개)은 PowerShell 6 이후에서 삭제되어, PowerShell 7에서는 동작하지 않습니다.2
  • 기본 네임스페이스는 root/CIMV2이며, 일상 조회는 여기의 Win32_* 클래스를 WQL로 좁히는 형태가 기본입니다.3
  • 원격 조회는 WSMan(WinRM)이 기본입니다. -ComputerName을 지정하면 WSMan 임시 세션이 만들어집니다. 같은 상대에 여러 번 조회한다면 CIM 세션(New-CimSession)을 재사용하는 것이 성능 면의 정석이고, WinRM을 구성할 수 없는 옛 상대에는 DCOM 프로토콜 옵션이 있습니다.34
  • C#은 System.Management(ManagementObjectSearcher)와 Microsoft.Management.Infrastructure(CimSession) 두 계통입니다. 둘 다 Windows 전용이며, 현재 .NET에서는 NuGet으로 넣습니다. 원격이나 모니터링을 본격적으로 하려면 CIM cmdlet과 같은 형식 체계의 MI API가 맞습니다.56
  • 프로세스 시작 감지는 이벤트 구독으로 하고, 폴링으로 하지 마십시오. Win32_ProcessStartTrace 구독은 관리자 권한으로 실행해야 합니다.78
  • SELECT *를 습관적으로 쓰지 마십시오. -Filter / -Property / -KeyOnly로 전송 데이터를 줄이는 것이 WMI 성능 문제의 절반을 막습니다.3
  • WMI는 만능이 아닙니다. 고빈도 성능 모니터링, 자체 앱 설정 읽기·쓰기, 단발 OS 기능 호출에는 성능 카운터·레지스트리·Win32 API·전용 cmdlet 쪽이 맞습니다(8장의 판단표).

그림의 실선은 항상 성립하는 관계, 점선은 조건이 붙는 관계입니다(성립 조건은 상세 페이지의 관계별 설명에 적혀 있습니다). 관계 전체 목록(총 26건, 근거와 확신도 포함)과 주요 개념의 정의는 지식 맵 상세 페이지에 정리되어 있습니다(일본어). 데이터: JSON-LD / Turtle

2. WMI/CIM이란 무엇인가 ── 표준과 구현, 네임스페이스, 클래스, WQL

먼저 용어의 관계를 한 번에 정리합니다.

용어 실체
CIM (Common Information Model) 시스템·앱·네트워크·디바이스 등 관리 대상을 표현하는 업계 표준 모델. DMTF(Distributed Management Task Force)가 제정·유지1
WBEM (Web-Based Enterprise Management) 기업 환경의 관리 정보에 접근하는 표준 기술을 만드는 업계 이니셔티브1
WMI WBEM의 Microsoft 구현. CIM 표준으로 관리 대상을 표현하며, Windows에 들어 있음1
MI (Windows Management Infrastructure) WMI의 다음 세대. 기존 WMI와 완전 호환이며, 새 공급자 상당수는 MI로 작성됨1
CIM 표준과 WMI 구현의 관계DMTF가 제정·유지하는 CIM 표준을 WBEM 이니셔티브 틀에서 쓰고, 그 Microsoft 구현이 WMI이며, 다음 세대 MI는 기존 WMI와 완전 호환이고, CIM 계열 API의 연결 대상은 같은 WMI 기반이다DMTF가 제정·유지CIM(업계 표준 모델)WBEM(업계 이니셔티브)WMI(Microsoft 구현)MI(다음 세대·완전 호환)CIM 계열 API(PowerShell / C#)

그림 2: CIM이 사양, WMI가 Windows상의 구현. CIM 계열 API의 연결 대상은 같은 WMI 기반.

개발자가 잡아야 할 구조는 다음 네 가지입니다.

  • 네임스페이스(namespace): 클래스를 묶는 계층입니다. 일상 조회에서 쓰는 것은 거의 root/CIMV2이고, CIM cmdlet의 기본값도 여기입니다.3 그밖에 root\default(레지스트리 공급자 등) 등이 있습니다.
  • 클래스: Win32_ComputerSystem(컴퓨터 본체), Win32_LogicalDisk(논리 드라이브), Win32_Process(프로세스)와 같은 관리 대상의 형식입니다. CIM 표준 클래스(CIM_LogicalDisk 등)를 상속한 Windows 고유 클래스가 Win32_ 접두사를 가집니다.9
  • 공급자: 클래스의 실체를 제공하는 구성 요소입니다. 조회하면 공급자가 그 자리에서 OS에 물어 값을 만듭니다.
  • WQL: SQL과 비슷한 조회 언어입니다. SELECT Name, State FROM Win32_Service WHERE StartMode = 'Auto'처럼 클래스를 테이블로 보고 좁힙니다. CIM cmdlet의 기본 조회 언어도 WQL입니다.3

「OS나 하드웨어 정보를 통일된 클래스와 쿼리 언어로 읽을 수 있다」── 이것이 WMI의 가치입니다. 거꾸로 말하면 쓰기나 조작은 Invoke-CimMethod로 호출할 수 있는 메서드를 가진 일부 클래스에 한정되며, 무엇이든 되는 구조는 아닙니다.

WMI 조회의 구조WQL 조회는 네임스페이스 root/CIMV2 안의 Win32_* 클래스를 향하고, 클래스 실체를 제공하는 공급자가 그 자리에서 OS에 물어 값을 만들어 결과가 돌아온다WQL로 조회네임스페이스 root/CIMV2Win32_* 클래스공급자그 자리에서 OS에 질의결과를 반환

그림 3: 조회는 네임스페이스, 클래스, 공급자 순으로 따라가며, 값은 그 자리에서 만들어집니다.

3. PowerShell에서 쓰기 ── CIM cmdlet이 현재 선택, WMI cmdlet은 삭제됨

3.1. 기본은 Get-CimInstance

# 클래스 지정(기본 네임스페이스 root/CIMV2)
Get-CimInstance -ClassName Win32_OperatingSystem

# WHERE 절만 -Filter에 쓴다(WHERE 키워드는 쓰지 않음)
Get-CimInstance -ClassName Win32_Service -Filter "StartMode = 'Auto' AND State <> 'Running'"

# 필요한 속성만 가져와 전송량을 줄인다
Get-CimInstance -ClassName Win32_Process -Property Name, ProcessId, CreationDate

# WQL을 그대로 쓰려면 -Query
Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name LIKE 'p%'"

-Filter는 WQL WHERE 절 그 자체이고, -Property는 가져올 열의 한정입니다.3 반환값은 CimInstance 객체이며, 날짜 속성(CreationDateLastBootUpTime 등)은 DateTime으로 변환된 채 돌아옵니다. 구 Get-WmiObject와 달리 가져온 객체는 메서드를 직접 갖지 않으므로, 메서드 호출은 Invoke-CimMethod에 넘깁니다.

CimInstance의 메서드 호출Get-CimInstance가 반환하는 CimInstance는 날짜 속성이 DateTime으로 변환된 채 돌아오는 한편 메서드를 직접 갖지 않으므로, 메서드 호출은 인스턴스를 Invoke-CimMethod에 넘겨 수행한다Get-CimInstanceCimInstance 객체날짜는 DateTime으로 변환됨메서드를 직접 갖지 않음Invoke-CimMethod에 넘김메서드 호출

그림 4: CimInstance는 메서드를 갖지 않으므로, 메서드 호출은 Invoke-CimMethod에 넘겨 수행합니다.

# 인스턴스 메서드 호출: 각 프로세스의 소유자를 가져온다
Get-CimInstance -ClassName Win32_Process -Filter "Name = 'notepad.exe'" |
    Invoke-CimMethod -MethodName GetOwner

# 클래스 정적 메서드 호출: 프로세스를 시작한다
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ CommandLine = 'notepad.exe' }

# 클래스 정의(속성·메서드 목록)를 조사한다
Get-CimClass -ClassName Win32_Process

3.2. 구 WMI cmdlet에서의 이전 대응표

PowerShell 6 이후(현재 PowerShell 7)에서는 다음 WMI v1 cmdlet이 삭제되어 있습니다. 같은 기능은 CimCmdlets 모듈(WMI v2)이 제공합니다.2

구(Windows PowerShell 5.1까지) 현재(CIM cmdlet) 보충
Get-WmiObject Get-CimInstance -Filter / -Query의 사고방식은 같음
Get-WmiObject -List Get-CimClass 클래스 탐색·정의 확인
Invoke-WmiMethod Invoke-CimMethod 인수는 -Arguments @{ } 해시테이블로 전달
Register-WmiEvent Register-CimIndicationEvent 이벤트 구독(6.3절)
Set-WmiInstance Set-CimInstance 쓰기 가능 속성의 변경
Remove-WmiObject Remove-CimInstance 인스턴스 삭제

Windows PowerShell 5.1에서도 CIM cmdlet을 쓸 수 있으므로, 새로 쓰는 것은 5.1에서 돌리더라도 CIM 쪽으로 작성하는 것이 이전 비용을 남기지 않는 방법입니다. 5.1과 7의 공존·이전 전체 그림은 「Windows PowerShell 5.1과 PowerShell 7의 차이」에 정리했습니다.

새 스크립트를 CIM으로 쓰는 이유WMI cmdlet으로 쓴 스크립트는 5.1에서는 동작하지만 PowerShell 6 이후에서 삭제되어 이전 때 다시 써야 하고, CIM cmdlet은 5.1에서도 쓸 수 있어 새로 쓰는 것은 CIM 쪽으로 쓰면 이전 비용이 남지 않는다WMI cmdletCIM cmdlet새로 쓰는 스크립트어느 쪽으로 쓸 것인가?5.1에서는 동작5.1에서도 사용 가능PowerShell 7에서 삭제됨이전 때 다시 작성이전 비용이 남지 않음

그림 5: 새 스크립트는 CIM cmdlet으로 써 두면, PowerShell 7로 옮길 때 다시 쓸 필요가 없습니다.

4. 원격 조회 ── CIM 세션(WSMan 기본)과 DCOM 옵션

CIM cmdlet은 지정이 없으면 로컬 WMI에 COM으로 연결하고, -ComputerName을 지정하면 WSMan(WinRM) 프로토콜로 임시 세션을 만들어 연결합니다. 같은 컴퓨터에 여러 작업을 할 때는 CIM 세션을 만들어 재사용하는 쪽이 성능상 유리합니다.3

CIM 연결 방식의 선택지정이 없으면 로컬 WMI에 COM 연결, ComputerName 지정은 WSMan 임시 세션이 조회마다 만들어지고, 같은 상대에 대한 여러 작업은 New-CimSession 재사용이 성능상 유리하며, WinRM 미구성 상대에는 DCOM 프로토콜 옵션이 있다없음있음단발여러 번CIM cmdlet 실행ComputerName 지정?로컬 WMI에 COM 연결같은 상대에 여러 작업?WSMan 임시 세션New-CimSession을 재사용조회마다 만들어짐WinRM 미구성 상대DCOM 프로토콜 옵션

그림 6: 원격 조회는 WSMan이 기본이고, 같은 상대에 대한 여러 작업은 CIM 세션 재사용이 정석입니다.

# 단발이면 -ComputerName(호출마다 임시 세션이 만들어짐)
Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName Server01, Server02

# 반복 조회라면 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

WinRM을 구성할 수 없는 옛 머신처럼 WSMan으로 연결하지 못하는 상대에는 DCOM 프로토콜을 고를 수 있습니다.4

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

원격 조회의 전제는 다음과 같습니다.

  • 대상에서 WinRM이 구성되어 있을 것. winrm quickconfig가 서비스 자동 시작·HTTP 리스너(기본 포트 5985) 생성·방화벽 예외 등록을 한 번에 합니다.10 HTTPS(기본 포트 5986)로 연결하려면 이것만으로는 부족하고, 서버 인증서를 준비한 뒤 winrm quickconfig -transport:https 등으로 HTTPS 리스너를 따로 구성해야 합니다.10
  • 경로상의 방화벽에서 해당 포트가 열려 있을 것. 수신 규칙의 설계와 등록 실무는 「Windows 방화벽과 업무 앱」 글에서 다룬 바와 같습니다.
  • 인증. 도메인 환경이면 Kerberos로 상호 인증됩니다. 워크그룹에서는 Kerberos를 쓸 수 없어, 클라이언트 쪽 TrustedHosts 등록이 필요한 경우가 있습니다. 등록 대상은 필요 최소한으로 좁힙니다.10
  • 권한. 기본 구성에서는 원격 WMI 조회·조작을 대상의 관리자 그룹에 속한 계정으로 하는 것이 기본입니다. 일반 사용자에게 열려면 WinRM과 WMI 네임스페이스 양쪽에서 액세스 권한을 구성해야 합니다.10
  • 덧붙여 DCOM은 고정 대기 포트가 없고(RPC 동적 포트를 씀) 방화벽을 넘는 설계가 어려워집니다. 앞으로 만들 구조는 WSMan을 기본으로 보는 편이 무난합니다.
원격 조회의 전제 확인대상에서는 winrm quickconfig가 서비스 자동 시작과 HTTP 리스너 생성과 방화벽 예외 등록을 한 번에 하고, HTTPS 리스너는 인증서를 준비해 따로 구성하며, 워크그룹 환경에서는 TrustedHosts 등록이 필요한 경우가 있다winrm quickconfig서비스 자동 시작HTTP 리스너 생성(5985)방화벽 예외HTTPS 리스너(5986)인증서를 준비해 따로 구성워크그룹 환경TrustedHosts에 등록

그림 7: winrm quickconfig는 기본 구성을 한 번에 하고, HTTPS 리스너와 워크그룹 인증은 따로 대응합니다.

5. C#에서 쓰기 ── System.Management와 Microsoft.Management.Infrastructure

C#에서 WMI를 쓰는 API는 두 계통입니다. 둘 다 Windows 전용입니다.

  System.Management Microsoft.Management.Infrastructure (MI API)
도입 .NET Framework는 기본 제공. 현재 .NET에서는 NuGet 패키지 System.Management5 NuGet 패키지 Microsoft.Management.Infrastructure6
진입점 클래스 ManagementObjectSearcher(WQL을 넘겨 조회)5 CimSession(Create → QueryInstances / InvokeMethod / Subscribe)6
형식 체계 ManagementObject / ManagementEventWatcher11 CimInstance / CimSession ── CIM cmdlet과 같은 형식3
원격 DCOM 기반 WSMan(CIM 세션) 기반. 비동기 버전(*Async) 있음6
맞는 장면 로컬 정보 조회. 기존 코드 자산 유지 원격 조회·모니터링 도입. PowerShell을 함께 쓰는 설계

5.1. System.Management: ManagementObjectSearcher의 기본

WQL을 문자열로 넘기고, Get()으로 결과 컬렉션을 받습니다.5

// NuGet: System.Management(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"]} 여유 {freeGb:F1} GB / 전체 {sizeGb:F1} GB");
}

속성은 인덱서로 object로 돌아오므로, 클래스 문서에서 CIM 형식(이 예에서는 FreeSpace / Size는 uint649)을 확인한 뒤 캐스트합니다. 여기를 int로 착각하고 캐스트하면 InvalidCastException이 난다는 것이 첫 번째 흔한 실수입니다.

속성 조회와 캐스트의 함정System.Management의 속성은 인덱서로 object로 돌아오므로, 클래스 문서에서 CIM 형식을 확인한 뒤 캐스트해야 하며, int로 착각하고 캐스트하면 InvalidCastException이 난다인덱서로 조회object로 반환문서에서 CIM 형식 확인올바른 형으로 캐스트int로 착각하고 캐스트InvalidCastException

그림 8: 속성은 object로 돌아오므로, CIM 형식을 확인한 뒤 캐스트합니다.

5.2. MI API: CimSession의 기본

CimSession은 로컬·원격을 같은 형태로 다룹니다. 열거·조회·메서드 호출·이벤트 구독과 비동기 버전까지 한 세트가 갖춰져 있습니다.6

// NuGet: Microsoft.Management.Infrastructure(Windows 전용)
using Microsoft.Management.Infrastructure;

// 로컬이면 CimSession.Create(null), 원격이면 컴퓨터 이름을 넘긴다
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} 여유 {free / 1024.0 / 1024 / 1024:F1} GB");
}

PowerShell CIM cmdlet이 반환하는 것과 같은 CimInstance를 다루므로, 「PowerShell로 시험한 뒤 C#으로 옮겨 적는다」는 개발 흐름이 자연스럽게 이어집니다. C#과 PowerShell 연동 자체를 설계한다면 「C#에서 PowerShell을 실행해 객체로 받는 방법」도 참고하십시오.

PowerShell로 시험한 뒤 C#으로 옮겨 적는 흐름PowerShell CIM cmdlet과 C# MI API는 같은 CimInstance 형을 다루므로, PowerShell로 시제품 만든 뒤 C#으로 옮겨 적는 개발 흐름이 자연스럽게 이어진다PowerShell로 시제품CIM cmdletC#으로 본구현MI API같은 CimInstance 형옮겨 적기가 자연스럽게 이어짐

그림 9: CIM cmdlet과 MI API는 같은 CimInstance 형을 다루므로, 시제품에서 본구현으로 이어집니다.

6. 자주 쓰는 실무 레시피

6.1. 자주 쓰는 클래스 한눈에 보기

얻고 싶은 정보 클래스 주요 속성
제조사·모델명 Win32_ComputerSystem Manufacturer, Model
본체 시리얼 번호 Win32_BIOS SerialNumber
OS 버전·부팅 시각 Win32_OperatingSystem Caption, Version, LastBootUpTime
디스크 여유 용량 Win32_LogicalDisk DeviceID, FreeSpace, Size, DriveType9
서비스 상태 Win32_Service Name, State, StartMode
프로세스 목록 Win32_Process Name, ProcessId, CommandLine

6.2. 자산 관리의 기본: 시리얼 번호·모델명·디스크 여유 공간

# 모델 정보와 시리얼 번호(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
}

# 로컬 디스크(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은 「로컬 디스크」를 나타내는 값으로, 이동식(2)·네트워크 드라이브(4)·CD(5)를 제외합니다.9 모니터링이라면 이 스크립트를 CIM 세션으로 각 서버에 돌리기만 해도, 에이전트 없는 디스크 모니터링의 토대가 됩니다.

에이전트 없는 디스크 모니터링의 토대DriveType 3으로 좁혀 이동식·네트워크 드라이브·CD를 제외하고 로컬 디스크만 대상으로 하며, 같은 스크립트를 CIM 세션으로 각 서버에 돌려 에이전트 없는 디스크 모니터링의 토대가 된다여유 용량 조회 스크립트DriveType = 3으로 좁힘이동식 등을 제외CIM 세션 경유각 서버에 돌림에이전트 없는 모니터링

그림 10: 로컬 디스크로 좁힌 스크립트를 CIM 세션으로 각 서버에 돌리는 것이 모니터링의 토대입니다.

6.3. 프로세스 시작 감지 ── 이벤트 구독

「폴링으로 Win32_Process를 주기적으로 가져와 차이를 본다」가 아니라 이벤트 구독으로 합니다. 프로세스 시작은 Win32_ProcessStartTrace(커널 추적 공급자의 이벤트 클래스. ProcessName / ProcessID / ParentProcessID 등을 가집니다8)를 구독하는 것이 간단합니다.

# 관리자 권한 PowerShell에서 실행할 것
$action = {
    $name = $Event.SourceEventArgs.NewEvent.ProcessName
    $id   = $Event.SourceEventArgs.NewEvent.ProcessID
    Write-Host "프로세스 시작: $name (PID=$id)"
}
Register-CimIndicationEvent -ClassName Win32_ProcessStartTrace `
    -SourceIdentifier ProcessStarted -Action $action

구독은 이 등록을 한 PowerShell 세션이 살아 있는 동안 계속 유효하고, 프로세스가 시작될 때마다 -Action이 실행됩니다. 해제 명령까지 이어서 한 번에 실행해 버리면 모니터링이 시작되기 전에 구독만 사라지므로 주의하십시오. 해제는 모니터링을 끝낼 때 실행합니다.

# 모니터링을 끝낼 때: 구독 해제
Unregister-Event -SourceIdentifier ProcessStarted

Register-CimIndicationEvent는 클래스 이름 또는 WQL 이벤트 쿼리로 구독을 등록하고, -Action의 스크립트 블록이 도착할 때마다 실행됩니다.7 이 클래스의 구독에는 관리자 권한이 필요합니다.7 이벤트를 누가 받을 수 있는지는 이벤트 클래스의 보안 설명자로 제어되며, 일반 사용자인 채로는 액세스가 거부됩니다.8

프로세스 시작 이벤트 구독의 흐름관리자 권한 PowerShell 세션에서 Register-CimIndicationEvent가 구독을 등록하고, 프로세스가 시작될 때마다 이벤트가 도착해 Action이 실행되며, 모니터링을 끝낼 때 Unregister-Event로 해제한다WMIPowerShell 세션WMIPowerShell 세션관리자 권한으로 실행Register-CimIndicationEvent로 구독 등록프로세스 시작마다 이벤트 도착-Action 실행Unregister-Event로 해제(모니터링 종료 시)

그림 11: 구독은 등록한 세션이 살아 있는 동안 계속 유효하고, 해제는 모니터링을 끝낼 때 합니다.

또 하나의 방법이 임의의 클래스에 쓸 수 있는 범용 인스턴스 생성 이벤트(__InstanceCreationEvent)입니다. 이쪽은 WMI가 WITHIN으로 지정한 간격으로 폴링해 차이를 이벤트로 만드는 구조이므로, 감지 간격과 부하의 트레이드오프를 스스로 정하게 됩니다.

프로세스 시작 감지의 두 구독 방식Win32_ProcessStartTrace는 커널 추적 공급자의 이벤트 클래스를 구독하는 방식이고, 범용 __InstanceCreationEvent는 WMI가 WITHIN 지정 간격으로 폴링해 차이를 이벤트로 만들므로 감지 간격과 부하의 트레이드오프를 스스로 정한다프로세스 시작 감지Win32_ProcessStartTrace__InstanceCreationEvent커널 추적 구독WITHIN 간격으로 폴링간격과 부하의 트레이드오프

그림 12: 전용 이벤트 클래스를 구독할지, 범용 인스턴스 생성 이벤트를 폴링 간격과 함께 쓸지입니다.

# 5초 간격 폴링으로 Win32_Process의 새 인스턴스를 모니터링
$query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"
Register-CimIndicationEvent -Query $query -SourceIdentifier ProcPoll -Action {
    Write-Host "시작: $($Event.SourceEventArgs.NewEvent.TargetInstance.Name)"
}

C#(System.Management)에서는 ManagementEventWatcher가 같은 역할입니다.11

using System.Management;

// 관리자 권한으로 실행 중인 프로세스에서
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($"프로세스 시작: {name} (PID={pid})");
};
watcher.Start();
// 모니터링 종료 시 watcher.Stop()과 Dispose를 잊지 말 것

상주 모니터링에 넣을 때는 구독이 끊겼을 때의 재등록(서비스 다시 시작 시·오류 시)까지 설계에 넣으십시오. 디바이스 모니터링을 포함한 「상태 확인과 표시」의 설계론은 「외부 기기의 상태 확인과 표시의 베스트 프랙티스」에서 다룹니다.

상주 모니터링의 구독 수명 주기상주 모니터링에서는 구독 중인 상태가 서비스 다시 시작이나 오류로 끊길 수 있으므로, 끊긴 것을 감지해 재등록하고 구독 중으로 되돌리는 설계까지 넣는다서비스 다시 시작·오류구독 중구독이 끊긴 상태재등록

그림 13: 상주 모니터링에서는 구독이 끊겼을 때 재등록해 구독 중으로 되돌리는 설계까지 넣습니다.

7. 함정 ── 성능·권한·64bit·리포지토리·날짜

7.1. SELECT *와 폴링 남용

WMI 조회는 「공급자가 그 자리에서 값을 만드는」 처리이며 공짜가 아닙니다. 흔한 안티패턴은 두 가지입니다.

  • SELECT *의 습관적 사용. Win32_Process를 모든 속성으로 전건 가져오면 그만큼 공급자의 일과 네트워크 전송(원격 시)이 커집니다. -Filter로 행을, -Property로 열을 좁히고, 후속 작업에 키만 필요하면 -KeyOnly를 씁니다. 어느 쪽이든 「객체 크기와 네트워크 트래픽을 줄이기 위해」 공식으로 마련된 수단입니다.3
  • 짧은 주기 폴링. 「1초마다 Get-CimInstance Win32_Process」 같은 설계는 6.3절의 이벤트 구독으로 바꿉니다. 어쩔 수 없이 폴링형(WITHIN)을 쓸 때도, 요구에 대해 필요 충분한 간격까지 늘립니다.

또한 원격에 대해 한 대씩 -ComputerName으로 반복하는 것도 낭비가 큽니다. 임시 세션 생성이 조회마다 돌아가므로, 여러 작업은 CIM 세션 재사용으로 바꿉니다.3

성능 안티패턴과 대체처SELECT 별표의 습관적 사용은 Filter와 Property로 행과 열을 좁히고 키만 필요하면 KeyOnly를 쓰며, 짧은 주기 폴링은 이벤트 구독으로, 한 대씩 ComputerName 지정 반복은 CIM 세션 재사용으로 바꾼다SELECT *의 습관적 사용Filter와 Property로 좁힘키만 필요하면 KeyOnly짧은 주기 폴링이벤트 구독으로 대체한 대씩 ComputerNameCIM 세션을 재사용

그림 14: 행·열·키를 좁히고 이벤트 구독으로 바꾸는 것이 WMI 성능 문제의 절반을 막습니다.

7.2. 이벤트 구독의 권한

6.3절에서 본 대로 Win32_ProcessStartTrace 계열 구독은 관리자 권한이 전제입니다.7 「개발기(관리자로 실행)에서는 됐는데, 고객사 일반 사용자 환경에서 모니터링이 안 된다」는 사고는 방화벽 알림 대화상자와 나란히 흔한 사례입니다. 일반 사용자로 도는 업무 앱에 모니터링을 넣으려면, 모니터링 부분을 Windows 서비스(LocalSystem 등)로 분리하고 앱 본체와는 프로세스 간 통신으로 잇는 구성을 검토하십시오.

일반 사용자 환경의 모니터링 구성관리자 권한이 전제인 구독은 일반 사용자로 도는 앱 본체에서 분리하고, LocalSystem 등으로 실행하는 Windows 서비스에 모니터링 부분을 두어 앱 본체와는 프로세스 간 통신으로 잇는다프로세스 간 통신모니터링용 Windows 서비스시작 추적을 구독LocalSystem 등으로 실행앱 본체(일반 사용자)

그림 15: 관리자 권한이 필요한 구독은 서비스 쪽으로 분리하고, 앱 본체와는 프로세스 간 통신으로 잇습니다.

7.3. 32bit/64bit와 공급자

64bit Windows에서는 공급자에 32bit판과 64bit판이 공존하는 것이 있고, 기본값으로는 호출한 앱의 비트 수에 맞는 쪽이 응답합니다.12 전형이 root\default의 레지스트리 공급자(StdRegProv)로, 32bit 앱에서 읽으면 Wow6432Node 쪽(32bit 뷰) 값이 돌아옵니다.12 「WMI로 읽은 레지스트리 값이 regedit로 본 값과 다르다」면 먼저 이것을 의심하십시오. 반대쪽 뷰가 필요하면 연결 시 컨텍스트에 __ProviderArchitecture(그리고 필수로 하려면 __RequiredArchitecture)를 지정해 명시적으로 요청할 수 있습니다.12 비트 수 문제의 전체 그림은 「C#에서 Win32 API를 안전하게 호출하기 ── P/Invoke 실무 가이드」에서도 다룹니다.

64bit 환경의 공급자 선택기본값으로는 호출한 앱의 비트 수에 맞는 공급자가 응답하고, 32bit 앱의 레지스트리 조회는 Wow6432Node 쪽 값을 받지만, __ProviderArchitecture 지정으로 반대쪽 뷰를 명시적으로 요청할 수 있다32bit64bit호출 측의 비트 수는?32bit 공급자가 응답64bit 공급자가 응답레지스트리는 Wow6432Node 쪽 값__ProviderArchitecture 지정반대쪽 뷰를 명시적으로 요청

그림 16: 기본값으로는 호출 측 비트 수에 맞는 쪽이 응답하므로, 32bit 앱은 Wow6432Node 쪽을 읽습니다.

7.4. WMI 리포지토리 손상 시의 증상과 대처

WMI의 클래스 정의는 리포지토리(단일 파일이 아니라 Repository 폴더 안의 파일 집합이 데이터베이스로 동작합니다13)에 저장됩니다. 여기가 불일치하면 「있어야 할 클래스를 찾을 수 없다」「네임스페이스가 유효하지 않다」 같은 오류가, 앱 쪽은 아무것도 바꾸지 않았는데도 나타나기 시작합니다. 원인 분리와 복구에는 winmgmt.exe를 씁니다.13

rem 정합성 검사(결과가 inconsistent이면 불일치 있음)
winmgmt /verifyrepository

rem 정합성 검사 + 불일치가 있으면 재구축(읽을 수 있는 내용은 병합됨)
winmgmt /salvagerepository

주의할 점은 리포지토리 삭제나 초기화를 첫 수단으로 삼지 않는 것입니다. WMI를 거쳐 나오는 오류는 OS의 다른 부분에 원인이 있는 경우도 있고, Microsoft는 리포지토리 삭제를 첫 대처로 하면 「시스템이나 설치된 앱에 손상을 초래할 수 있다」고 명시합니다.13 /verifyrepository로 확인 → /salvagerepository로 복구, 이 순서를 지킵니다.

WMI 리포지토리 불일치의 원인 분리 절차클래스를 찾을 수 없는 등의 오류가 나면 winmgmt의 verifyrepository로 정합성을 확인하고, 불일치면 salvagerepository로 재구축하며, 리포지토리 삭제나 초기화를 첫 수단으로 하지 않는다아니요클래스를 찾을 수 없는 등의 오류winmgmt /verifyrepository결과는 inconsistent?winmgmt /salvagerepositoryOS의 다른 부분의 원인을 의심읽을 수 있는 내용은 병합됨리포지토리 삭제·초기화첫 수단으로 하지 않음

그림 17: verify로 확인한 뒤 salvage로 복구하는 순서를 지키고, 삭제를 첫 수단으로 하지 않습니다.

7.5. DMTF 날짜 형식의 변환

WMI 날짜는 CIM 사양의 DMTF 형식 yyyymmddHHMMSS.mmmmmm±UUU(끝은 UTC 오프셋 분. 예: 20260801100000.000000+540) 문자열로 저장됩니다. 원본 값을 문자열 처리로 잘라 붙이지 말고 변환 API를 쓰십시오.

  • C# (System.Management): ManagementDateTimeConverter가 DMTF 형식과 DateTime / TimeSpan의 상호 변환을 제공합니다.11
  • CIM 계열 API(Get-CimInstance / MI API): 날짜 속성이 DateTime으로 변환된 채 돌아오므로, 애초에 이 문제를 만나지 않습니다. (Get-CimInstance Win32_OperatingSystem).LastBootUpTime은 그대로 DateTime으로 계산에 쓸 수 있습니다.
DMTF 날짜 형식의 처리WMI 날짜는 DMTF 형식 문자열로 저장되어 있으며, System.Management에서 원본 값을 읽은 경우에는 ManagementDateTimeConverter로 변환하고, CIM 계열 API라면 DateTime으로 변환된 채 돌아오므로, 직접 문자열을 잘라 붙이지 않는다System.ManagementCIM 계열 APIDMTF 형식 문자열어느 API로 가져왔는가?ManagementDateTimeConverterDateTime으로 변환된 채 반환DateTime / TimeSpan으로 변환직접 문자열 잘라 붙이기쓰지 않음

그림 18: DMTF 문자열 변환은 변환 API에 맡기고, CIM 계열 API라면 변환된 DateTime을 그대로 씁니다.

8. WMI를 쓰지 말아야 할 장면 ── 수단 판단표

WMI는 「통일된 읽기 창구」로는 뛰어나지만 항상 최선은 아닙니다. 실무에서 나누어 쓰는 기준입니다.

하고 싶은 일 맞는 수단 WMI를 고르지 않는 이유
하드웨어 정보·OS 구성 조회, 에이전트 없는 원격 조회 WMI/CIM 여기가 WMI의 본령. 전용 API를 하나씩 두드리는 것보다 통일적
자체 앱 설정의 읽기·쓰기 레지스트리 직접 읽기(Microsoft.Win32.Registry)·구성 파일 WMI를 거친 레지스트리 조작은 우회이며, 7.3절의 비트 수 문제도 떠안게 됨
CPU 사용률 등 고빈도·연속 성능 모니터링 성능 카운터(System.Diagnostics.PerformanceCounter 등) 카운터는 그것을 위한 구조. WMI의 짧은 주기 폴링은 부하와 정밀도에서 불리
단발 OS 기능 호출·저지연이 필요한 처리 Win32 API(P/Invoke) WMI는 COM/공급자를 거치는 만큼의 오버헤드가 있음
자체 프로세스 권한으로 충분한 로컬 프로세스 열거·조작 System.Diagnostics.Process 표준 라이브러리로 끝나 의존이 줄어듦
방화벽·네트워크 등 Windows 관리 기능의 구성 Get-NetFirewallRule전용 CIM 기반 cmdlet 원본 WMI 클래스를 찾는 것보다 용도별로 갖춰진 cmdlet 군이 정확하고 안전
파일·폴더의 변경 감지 FileSystemWatcher 전용 API가 있는 영역에 WMI를 끌어들이지 않음

판단의 축은 단순합니다. 「전용 구조가 있는 영역에서는 전용 구조를 쓰고, 횡단 조회·원격 조회에는 WMI/CIM을 쓴다」입니다. 마지막 행의 Get-NetFirewallRule 등은 내부적으로는 CIM 위에 만든 cmdlet 군이며, 「WMI/CIM을 직접 건드리지 않고 그 혜택만 받는」 형태라고 할 수 있습니다.

수단 판단의 축전용 구조가 있는 영역에서는 전용 구조를 쓰고, 없는 영역의 횡단 조회나 원격 조회에 WMI와 CIM을 쓰는 것이 판단의 축이며, 전용 CIM 기반 cmdlet은 WMI와 CIM을 직접 건드리지 않고 혜택만 받는 형태이다있다없다전용 구조가 있는가?전용 구조를 쓴다WMI / CIM을 쓴다횡단 조회·원격 조회전용 CIM 기반 cmdlet혜택만 받는 형태

그림 19: 전용 구조가 있는 영역에서는 전용을 쓰고, 횡단 조회와 원격 조회에 WMI/CIM을 씁니다.

9. 정리

  • CIM은 DMTF의 업계 표준, WMI는 그 Microsoft 구현입니다. PowerShell CIM cmdlet도 C# MI API도 이 표준을 따른 현재 세대의 진입점입니다.
  • PowerShell에서는 Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent가 현재 선택입니다. Get-WmiObject 등 WMI cmdlet은 PowerShell 7에 없으므로, 새 스크립트는 5.1용이라도 CIM 쪽으로 씁니다.
  • 원격 조회는 WSMan(WinRM)이 기본이며, 여러 작업은 CIM 세션을 재사용합니다. WinRM 미구성 상대에는 DCOM 옵션이라는 우회로가 있습니다.
  • C#은 System.Management(간편·로컬 지향)와 Microsoft.Management.Infrastructure(원격·모니터링 지향, CIM cmdlet과 같은 형식 체계) 두 계통에서 고릅니다. 둘 다 Windows 전용 NuGet 패키지입니다.
  • 프로세스 모니터링은 폴링이 아니라 이벤트 구독으로. Win32_ProcessStartTrace 구독에는 관리자 권한이 필요합니다.
  • SELECT *와 짧은 주기 폴링을 피하고 -Filter / -Property / -KeyOnly로 좁힙니다. 32bit 프로세스에서의 조회는 32bit 공급자를 향한다는 점, DMTF 날짜는 변환 API를 쓴다는 점, 리포지토리 손상은 삭제가 아니라 verify→salvage 순서로 대처한다는 점을 기억해 두십시오.
  • 전용 구조가 있는 영역(설정·성능 카운터·단발 API 호출)에는 WMI를 끌어들이지 않고, 횡단 조회와 원격 조회에 WMI/CIM을 쓴다 ── 이것이 사용처를 정하는 한 문장입니다.

관련 글

관련 상담 영역

합동회사 코무라소프트는 WMI/CIM을 쓴 하드웨어 정보 가져오기·프로세스 모니터링·원격 PC 조회의 업무 앱 도입, Get-WmiObject 기반 사내 스크립트의 CIM cmdlet으로의 이전, 「개발기에서는 되는데 고객사에서 권한 오류가 난다」 종류의 원인 조사를 다룹니다. PowerShell 시제품부터 C# 본구현까지 한 흐름으로 상담하실 수 있습니다.

참고 링크

  1. Microsoft Learn, About WMI. WMI가 WBEM(기업 환경의 관리 정보 접근을 위한 표준 기술을 개발하는 업계 이니셔티브)의 Microsoft 구현이라는 점, 관리 대상 표현에 CIM(Common Information Model) 업계 표준을 쓰며 CIM은 DMTF(Distributed Management Task Force)가 개발·유지한다는 점, 다음 세대 MI(Windows Management Infrastructure)가 기존 WMI와 완전 호환이라는 점, 원격 WMI 연결이 DCOM으로 이루어지며 대안으로 WS-Management 기반 WinRM이 있다는 점에 대해.  2 3 4 5

  2. Microsoft Learn, Differences between Windows PowerShell 5.1 and PowerShell 7.x. WMI v1 cmdlet(Register-WmiEvent / Set-WmiInstance / Invoke-WmiMethod / Get-WmiObject / Remove-WmiObject)이 PowerShell에서 삭제되었다는 점, CimCmdlets 모듈(WMI v2)의 cmdlet이 같은 기능을 제공하며 새 기능과 다시 설계된 구문을 갖는다는 점에 대해.  2

  3. Microsoft Learn, Get-CimInstance (CimCmdlets). ComputerName도 CimSession도 지정하지 않으면 로컬 WMI에 COM 세션으로 연결하고 -ComputerName 지정 시에는 WsMan 프로토콜의 임시 세션을 만든다는 점, 같은 컴퓨터에 대한 여러 작업에는 CIM 세션 연결이 성능상 권장된다는 점, -Filter가 WHERE 키워드를 포함하지 않는 WQL/CQL의 where 절이라는 점, -Property나 -KeyOnly로 객체 크기와 네트워크 트래픽을 줄일 수 있다는 점, 기본 네임스페이스가 root/CIMV2이고 기본 조회 언어(-QueryDialect)가 WQL이라는 점, 출력이 Microsoft.Management.Infrastructure.CimInstance라는 점, Invoke-CimMethod와 조합한 GetOwner 호출 예, Windows 전용 cmdlet이라는 점에 대해.  2 3 4 5 6 7 8 9 10

  4. Microsoft Learn, New-CimSessionOption (CimCmdlets). CIM 세션 옵션에 WsMan용과 DCOM용 두 매개변수 집합이 있다는 점, -Protocol에 Dcom / Default / Wsman을 지정할 수 있다는 점, New-CimSessionOption -Protocol Dcom으로 만든 옵션을 New-CimSession의 -SessionOption에 넘겨 DCOM CIM 세션을 만드는 예, DCOM 세션의 기본 가장 수준이 Impersonate라는 점에 대해.  2

  5. Microsoft Learn, ManagementObjectSearcher Class (System.Management). 지정한 WQL 쿼리를 바탕으로 관리 객체 컬렉션을 가져오는, 관리 정보 조회의 가장 일반적인 진입점 클래스라는 점, ObjectQuery와 ManagementScope(WMI 네임스페이스)를 받아 Get()으로 ManagementObjectCollection을 반환한다는 점, System.Management.dll이 NuGet 패키지 System.Management로 제공된다는 점에 대해.  2 3 4

  6. Microsoft Learn, CimSession Class (Microsoft.Management.Infrastructure). Microsoft.Management.Infrastructure.dll이 NuGet 패키지 Microsoft.Management.Infrastructure로 제공된다는 점, Create(computerName)에 의한 세션 생성, QueryInstances(namespace, queryDialect, query)에 의한 쿼리 실행, EnumerateInstances / GetInstance / InvokeMethod / Subscribe 및 각각의 비동기 버전(*Async)을 갖추고 IDisposable을 구현한다는 점에 대해.  2 3 4 5

  7. Microsoft Learn, Register-CimIndicationEvent (CimCmdlets). 클래스 이름 또는 쿼리 식으로 indication(이벤트)을 구독하고 -SourceIdentifier로 구독 이름을 붙인다는 점, Win32_ProcessStartTrace 구독 예와 그 실행에 PowerShell 관리자 실행이 필요하다는 주석, -Action 스크립트 블록 안에서 $Event.SourceEventArgs.NewEvent로부터 ProcessName / ProcessId를 참조하는 예, -ComputerName 지정 시에는 WsMan 임시 세션·미지정 시에는 로컬에 COM으로 연결한다는 점, 구독 해제에 Unregister-Event를 쓴다는 점에 대해.  2 3 4

  8. Microsoft Learn, Win32_ProcessStartTrace class. 새 프로세스의 시작을 나타내는 이벤트 클래스이며 ProcessName / ProcessID / ParentProcessID / SessionID / Sid 등의 속성을 가진다는 점, SECURITY_DESCRIPTOR 속성이 어떤 사용자가 이벤트를 받을 수 있는지를 이벤트 공급자가 결정하기 위한 설명자라는 점, 네임스페이스가 Root\CIMV2이며 커널 추적 공급자(Krnlprov.dll)가 제공한다는 점에 대해.  2 3

  9. Microsoft Learn, Win32_LogicalDisk class. Win32_LogicalDisk가 CIM_LogicalDisk에서 파생된 로컬 스토리지 디바이스를 나타내는 클래스라는 점, DriveType 값(2=이동식, 3=로컬 디스크, 4=네트워크 드라이브, 5=CD 등), FreeSpace / Size가 uint64 바이트 값이라는 점, DeviceID가 키라는 점, DriveType = 3으로 좁히는 VBScript / C# 쿼리 예에 대해.  2 3 4

  10. Microsoft Learn, Installation and configuration for Windows Remote Management. 기본값으로는 WinRM 리스너가 구성되어 있지 않아 WS-Management 메시지를 주고받을 수 없다는 점, winrm quickconfig가 서비스 자동 시작·HTTP/HTTPS 리스너 구성·방화벽 예외 등록을 한다는 점, WinRM 2.0의 기본 포트가 HTTP 5985 / HTTPS 5986이라는 점, 워크그룹 등에서 상호 인증(Kerberos)을 세울 수 없는 경우에는 TrustedHosts를 가능한 한 한정해 설정한다는 점, 리스너에 대한 원격 액세스를 제어하는 기본 보안 설명자(RootSDDL)나 관리자 이외 사용자에게 WMI 플러그인 사용을 허용하는 경우의 추가 구성에 대해.  2 3 4

  11. Microsoft Learn, System.Management Namespace. WMI 기반으로의 조회를 ManagementObjectSearcher 계열 클래스로, 이벤트 구독을 ManagementEventWatcher로 수행하는 네임스페이스라는 점, WqlEventQuery가 WQL 형식의 이벤트 쿼리를 나타낸다는 점, ManagementDateTimeConverter가 DMTF 일시·시간 간격과 CLR의 DateTime / TimeSpan 상호 변환 메서드를 제공한다는 점에 대해.  2 3

  12. Microsoft Learn, Requesting WMI Data on a 64-bit Platform. 공급자에 32bit판과 64bit판이 공존하는 경우, 기본값으로는 32bit 앱(스크립트 포함)에는 32bit 공급자가, 64bit 앱에는 64bit 공급자가 응답한다는 점, 컨텍스트의 __ProviderArchitecture(32 또는 64)와 __RequiredArchitecture로 기본이 아닌 쪽 공급자를 요청·강제할 수 있다는 점(강제 시 해당 판이 없으면 WBEM_E_PROVIDER_LOAD_FAILURE), 레지스트리 공급자 예에서 32bit 클라이언트가 HKLM\SOFTWARE\Wow6432Node 쪽 데이터를 받는다는 점에 대해.  2 3

  13. Microsoft Learn, winmgmt. winmgmt.exe의 /verifyrepository가 WMI 리포지토리 정합성 검사를 한다는 점, /salvagerepository가 정합성 검사 후 불일치 검출 시 리포지토리를 재구축하고 읽을 수 있었던 내용을 병합한다는 점, /resetrepository가 OS 최초 설치 시 상태로 되돌린다는 점, 리포지토리가 Repository 폴더 안의 파일 집합으로 데이터베이스로서 동작한다는 점, WMI를 거친 오류가 OS의 다른 부분에 원인이 있는 경우도 있으며 첫 대처로서의 리포지토리 삭제는 시스템이나 설치된 앱의 손상으로 이어질 수 있으므로 해서는 안 된다는 점에 대해.  2 3

같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.

이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.

이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.

자주 묻는 질문

이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.

WMI와 CIM은 무엇이 다른가요?
CIM은 DMTF(Distributed Management Task Force)가 제정·유지하는 「시스템이나 디바이스 등 관리 대상을 표현하기 위한 업계 표준 모델」입니다. WMI는 그 표준을 쓰는 WBEM 이니셔티브의 Microsoft 구현이며, Windows에 들어 있습니다. 즉 CIM이 사양, WMI가 Windows상의 구현입니다. PowerShell의 Get-CimInstance나 C#의 Microsoft.Management.Infrastructure가 「CIM」을 이름에 넣는 것은 이 표준을 따른 API이기 때문이며, 연결 대상은 같은 WMI 기반입니다. 일상 개발에서는 「WMI 클래스(Win32_* 등)를 CIM 계열 API로 조회한다」고 이해해 두면 실무에서 막히지 않습니다.
Get-WmiObject는 이제 쓸 수 없나요?
Windows PowerShell 5.1에서는 지금도 동작합니다. 다만 PowerShell 6 이후(현재 PowerShell 7)에서는 Get-WmiObject·Invoke-WmiMethod·Register-WmiEvent·Set-WmiInstance·Remove-WmiObject라는 WMI v1 cmdlet이 삭제되어 실행할 수 없습니다. 같은 기능은 CimCmdlets 모듈(Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent 등)이 제공합니다. 새로 쓰는 스크립트는 5.1에서 돌리더라도 CIM cmdlet으로 작성해 두는 편이 안전합니다. 그렇게 하면 PowerShell 7로 옮길 때 WMI 부분을 다시 쓸 필요가 없습니다.
C#에서 WMI를 쓰려면 System.Management와 Microsoft.Management.Infrastructure 중 어느 쪽을 써야 하나요?
둘 다 Windows 전용이며, 현재 .NET에서는 NuGet 패키지로 사용합니다. System.Management는 ManagementObjectSearcher에 WQL만 넘기면 되는 고전 API로, 로컬 정보 조회가 중심이면 이것으로 충분합니다. DMTF 날짜를 변환하는 ManagementDateTimeConverter도 여기에 들어 있습니다. 한편 Microsoft.Management.Infrastructure(MI API)는 PowerShell CIM cmdlet과 같은 형식 체계(CimSession / CimInstance)를 갖고, WSMan을 통한 원격 조회, 비동기 버전 메서드, 이벤트 구독(Subscribe)까지 한결같이 다룹니다. 원격 PC 조회나 모니터링을 본격적으로 넣을 계획이면 MI API를 고르는 편이 타당합니다.
원격 PC에 Get-CimInstance가 연결되지 않습니다. 무엇을 확인해야 하나요?
먼저 대상에서 WinRM이 구성되어 있는지 확인하십시오. -ComputerName을 지정한 CIM 작업은 WSMan(WinRM) 프로토콜로 임시 세션을 만들기 때문에, 대상에서 WinRM 서비스와 리스너가 동작 중이어야 합니다. winrm quickconfig로 기본 구성(서비스 시작·리스너 생성·방화벽 예외)을 할 수 있습니다. 기본 포트는 HTTP 5985, HTTPS 5986이므로 경로상의 방화벽도 확인합니다. 워크그룹 환경에서는 Kerberos 상호 인증을 쓸 수 없어, 클라이언트 쪽 TrustedHosts 등록이 필요한 경우가 있습니다. 도저히 WinRM을 구성할 수 없는 상대에는 New-CimSessionOption -Protocol Dcom으로 만든 옵션을 써서 DCOM으로 연결하는 방법도 있습니다.
WMI 날짜가 「20260801100000.000000+540」 같은 형식으로 돌아오는 이유는 무엇인가요?
WMI 날짜는 DMTF CIM 사양에서 정한 문자열 형식(yyyymmddHHMMSS.mmmmmm±UUU, 끝은 UTC 오프셋 분)으로 저장되기 때문입니다. 구 Get-WmiObject나 System.Management에서 원본 값을 읽으면 이 문자열이 그대로 돌아옵니다. C#(System.Management)에는 ManagementDateTimeConverter에 DMTF 형식과 DateTime / TimeSpan 상호 변환 메서드가 있으므로, 문자열을 직접 잘라 붙이지 말고 이것을 쓰십시오. Get-CimInstance 등 CIM 계열 API로 가져온 경우에는 날짜 속성이 DateTime으로 변환된 채 돌아오므로, 이 문제 자체를 만나지 않습니다.

저자 프로필

기사 저자의 프로필 페이지입니다.

Go Komura

합동회사 코무라소프트 대표

Windows 소프트웨어 개발, 기술 상담, 장애 조사를 중심으로 재현이 어려운 장애 조사와 기존 자산이 남아 있는 프로젝트에 강점이 있습니다.

블로그 목록으로 돌아가기