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.:
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
).
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.
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:
SelectQuery query = new SelectQuery("klasa", "opcjonalny warunek");
var wmiObjects = new ManagementObjectSearcher(query).Get();
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();
}
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).
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.
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, 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).
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…