WMI, czyli jak dobrać się do informacji o komputerze
Wysłany dnia 13 sierpnia 2010 o godzinie 00:46. Skomentuj!, kategorie: .NET, Kingdoms Clash.NET, Programowanie, tagi: , .

Postanowiłem sobie odpocząć od „projektowania” silnika(jeśli można to nazwać projektowaniem… ;) ) i napisać klasę, która będzie mi udostępniać podstawowe informacje o komputerze i systemie operacyjnym, np.:

  • wersję SO
  • wersję CLR
  • nazwę procesora, jego taktowanie i liczbę rdzeni
  • ilość zainstalowanej pamięci RAM
  • model karty graficznej, jej pamięć i wersję sterowników

Gdy pisałem coś podobnego w C++ do pobrania informacji o procesorze używałem asemblera i instrukcji cpuid, tutaj „nie ma tak dobrze”. Do pobrania informacji o karcie graficznej używałem OpenGL i glGetString, lecz zdobywałem ich tyle co kot napłakał.

Po krótkim poszukiwaniu dowiedziałem się jak to pobrać – WMI(i System.Environment ;) ).

Co to w ogóle WMI?

WMI, jak definiuje Wikipedia, jest to „zestaw protokołów i rozszerzeń systemu Windows umożliwiających zarządzanie i dostęp do zasobów komputera” i jest Microsoftową implementacją protokołu CIM. W skrócie: dzięki niemu mamy dostęp do informacji i możliwość zarządzania sprzętem i oprogramowaniem na nim zainstalowanym. Możemy bez problemu pobrać informacje o każdym zainstalowanym podzespole(karty sieciowe, graficzne, dyski itp.), co pokrótce postaram się opisać(informacje o oprogramowaniu są mi w tej chwili niepotrzebne). Dane w WMI reprezentowane są jako klasy, podobnie jak w „normalnych” językach programowania, a dostęp do nich jest odbywa się poprzez język podobny do SQL.

WMI i .NET

Aby uzyskać dostęp do WMI w .NET musimy użyć klas z przestrzeni nazw System.Management. Aby pobrać wartości w zupełności wystarczą nam cztery z nich – SelectQuery do tworzenia zapytań, ManagementObjectSearcher do wykonywania zapytań, ManagementObjectCollecton reprezentującej kolekcje obiektów WMI i ManagementObject reprezentującą same obiekty.

Metoda działania jest zawsze taka sama:

  • tworzymy zapytanie pobierające obiekty WMI
    SelectQuery query = new SelectQuery("klasa", "opcjonalny warunek");
  • wykonujemy zapytanie i pobieramy kolekcję obiektów
    var wmiObjects = new ManagementObjectSearcher(query).Get();
  • przetwarzamy je!
    foreach(var obj In wmiObjects) { /*…*/ }

Często otrzymujemy w kolekcji tylko jeden obiekt, ale lepiej się zabezpieczyć. Do poszczególnych pól mamy dostęp przez operator[] z pierwszym(i jedynym) parametrem oznaczającym nazwę pola. Dostajemy dzięki temu wartość pola jako object, które wystarczy zrzutować na odpowiadający typ.

Powyższe kody można upakować w jedną metodę, by uprościć sobie pobieranie obiektów:

ManagementObjectCollection Get(string @class, string condition = "")
{
   SelectQuery select = new SelectQuery(@class, condition);
   return new ManagementObjectSearcher(select).Get();
}

Wersja SO i CLR

Aby pobrać wersję systemu operacyjnego i CLR nie musimy używać WMI, wystarczy klasa System.Environment i jej pola OSVersion(system operacyjny) i Version(CLR).

Pamięć RAM

Aby pobrać informacje o dostępnej pamięci RAM możemy użyć dwóch klas: Win32_PhysicalMemoryArray lub Win32_PhysicalMemory. Obie zawierają informację o pamięci(RAM, dzielonej z pamięcią karty graficznej i innych), lecz ta druga zawiera dane bardziej „niskopoziomowe” – informacje o poszczególnych kościach(pamięć na kości, taktowanie, producenta itp.). W większości nie są one nam do niczego potrzebne a taka reprezentacja tylko utrudnia pobranie całkowitego jej rozmiaru, dlatego też użyjemy „tablicy pamięci”.

Rozmiar pamięci przechowywany jest w kilobajtach w polu MaxCapcity o typie UInt32. Dobrze jest też sprawdzić, czy pamięć jest pamięcią systemową a nie np. wideo. Możemy to zrobić sprawdzając czy pole Use(UInt16) ma wartość 3(dla, np., pamięci wideo jest to 4). A więc kod pobierający rozmiar pamięci będzie wyglądał tak:

uint memorySize;
foreach(var obj In Get("Win32_PhysicalMemoryArray", "Use = 3"))
{
   memorySize = (uint)item["MaxCapacity"];
   break;
}

Oczywiście można pozbyć się pętli foreach używając np. IEnumerator.Current, ale uważam to za bezsensowne.

Procesor

Do pobrania informacji o procesorze możemy użyć klasy Win32_Processor. Pobierze ona nam wszystkie zainstalowane procesory(a że przeważnie jest jeden…) i informacje o nich. Ja osobiście potrzebowałem tylko 4 pól – Name(nazwa procesora, ta sama co w menadżerze urządzeń), Architecture, określającej architekturę procesora, CurrentClockSpeed informujące nas o taktowaniu i NumberOfCores – liczbie rdzeni.

Karta graficzna

Karta graficzna, czyli inaczej kontroler wideo, reprezentowana jest przez klasę Win32_VideoController. Dostarcza ona nam informacji o dosłownie wszystkim – sprzęcie(pamięć, producent, model), sterownikach, stanie czy konfiguracji. Ja potrzebowałem bardzo niewielu informacji – nazwy(Name), zainstalowanej pamięci(AdapterRAM) i wersji sterownika(DriverVersion).

Podsumowanie

Jak widać WMI to potężne narzędzie, ja użyłem tylko minimalnej funkcjonalności. Zachęcam do zapoznania się z nim, gdyż dzięki niemu można nie dość, że uzyskać naprawdę dużo informacji, to jeszcze zautomatyzować sobie wiele rzeczy(na MSDN jest duża ilość przykładów zastosować(w VBScript)).

Dla zainteresowanych: na GitHubie(tak! projekt jest tam aktualizowany!) jest moja klasa SystemInformation, która opakowuje informacje(te, które wymieniłem) o komputerze.

A miał mi wyjść krótki news…

Dodaj komentarz

XHTML: Możesz użyć: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>