Rejestr systemu Windows
Jacek Matulewski
15 maja 2015
Programowanie Windows
http://www.fizyka.umk.pl/~jacek/dydaktyka/winprog/
Trivia
• Rejestr to centralna hierarchiczna baza danych
przechowująca ustawienia systemu Windows (w tym konfiguracja sprzętu), jego użytkowników oraz
zainstalowanego w tym systemie oprogramowania
• Pliki rekestru: Windows\System32\Config\User.dat, Classes.dat, System.dat (i inne, np. .sav)
• Hierarchiczność = klucze rejestru tworzą strukturę drzewa analogicznie jak foldery w systemach plików (klucze-podklucze, foldery-podfoldery)
• Klucze mogą przechowywać wartości
(typy: binarny, liczba całkowita 32-bitowa, ciągi)
Klucze główne rejestru
• HKEY_USERS – profile użytkowników (jego programów)
• HKEY_CURRENT_USER – alias do klucza bieżącego użytkownika z HKEY_USERS
• HKEY_LOCAL_MACHINE – konfiguracja komputera
(m.in. informacje o sterownika), także zainst. oprogramowanie
• HKEY_CLASSES_ROOT – alias do podklucza HKLM (ważny!);
wykorzystywana przez powłokę przy uruchamianiu aplikacji Alias do: HKEY_LOCAL_MACHINE\Software\Classes
• HKEY_CURRENT_CONFIG – rejestr używany przy uruchamianiu komputera (profil sprzętowy), alias do:
HKLM\SYSTEM\CurrentControlSet\Hardware\Profiles
• Niezależne klucze 32-bitowe i 64-bitowe, część „odbita”
(mogą mieć te same nazwy)
Podstawowe typy wartości
• REG_BINARY – wartość binarna; HEX
• REG_DWORD – 4-bajtowa (32 bity) liczba całkowita
(odpowiada typowi DWORD w WinAPI); HEX, DEC, BIN
• REG_QWORD – 64-bitowa liczba całkowita; BIN (od Win. 2000)
• REG_SZ – ciąg zakończony wartością \0
• REG_MULTI_SZ – kilka ciągów, każdy zakończony znakiem \0
• REG_EXPAND_SZ – ciąg ze zmiennymi systemowymi, które przy odczycie zostaną zastąpione wartościami tych zmiennych
• Typy używane przez sterowniki sprzętu (seria zagnieżdżonych tablic):
REG_RESOURCE_LIST, REG_RESOURCE_REQUIREMENTS_LIST, REG_FULL_RESOURCE_DESCRIPTOR
• REG_LINK – ciąg Unicode z linkami symbolicznymi
• REG_NONE – dane nie „sformatowane”
Rejestr a tworzenie aplikacji
• Przechowywanie danych (ustawień) aplikacji
• Automatyczne uruchamianie aplikacji (także jednokrotne)
• Informacje o zainstalowanym programie
odczytywane przez aplet Dodaj/usuń programy
• Odczytywanie ustawień systemowych
• Modyfikacja menu systemowego tworzonej aplikacji
• Edycja skojarzeń plików oraz poleceń dla typów plików
(ustawianie tworzonej aplikacji jako edytora)
Podstawowe funkcje dot. kluczy
• Lista wszystkich funkcji: https://msdn.microsoft.com/en- us/library/windows/desktop/ms724875(v=vs.85).aspx
• RegCreateKeyEx – tworzenie klucza
• RegOpenKeyEx – otwarcie klucza;
można otworzyć tylko jeden klucz rejestru
• RegCloseKey – zamknięcie klucza
• RegDeleteKey – usunięcie klucza; także RegDeleteTree
• Wszystkie te funkcje zwracają numer błędu (LONG).
Powodzenie – ERROR_SUCCESS.
Komunikat można uzyskać dzięki funkcji FormatMessage
• RegQueryInfoKey – informacje o kluczu
Podstawowe funkcje dot. wartości
• Lista wszystkich funkcji: https://msdn.microsoft.com/en- us/library/windows/desktop/ms724875(v=vs.85).aspx
• RegQueryValueEx – odczytanie wartości;
można także sprawdzić, czy wartość o podanej nazwie istnieje w otwartym kluczu
• RegQueryMultipleValues – odczytywanie serii wartości
• RegDeleteValue – usuwanie wartości
• RegSetValueEx – zmiana wartości
• RegNotifyChangeKeyValue – można ustalić
powiadamianie o zmianach we wskazanym kluczu lub wartości
Demo: RejestrSystemuWindows
• Klasa CRejestr obsługująca operacje dotyczące rejestru (pliki Rejestr.h i Rejestr.cpp)
• Przegląd metod klasy CRejestr dotyczących kluczy i wartości
User Access Control (UAC)
Aby uzyskać dostęp do rejestrów z uprawnieniami
administratora (np. HKEY_LOCAL_MACHINE)
należy uzyskać uprawnienia administratora
Przykład: przechowywanie położenia i rozmiaru okna
void ZapiszPolozenieIWielkoscOknaWRejestrze(HWND uchwytOkna,const wchar_t* klucz) {
wchar_t tytul[1024];
GetWindowText(uchwytOkna,tytul,1024);
CRejestr rejestr(HKEY_CURRENT_USER,KEY_WRITE, true);
if(!rejestr.CzyKluczIstnieje(klucz)) rejestr.UtworzKlucz(klucz);
if(rejestr.OtworzKlucz(klucz)) {
CRect rect;
GetWindowRect(uchwytOkna,&rect);
rejestr.ZapiszInt(L"Left",rect.left);
rejestr.ZapiszInt(L"Top",rect.top);
rejestr.ZapiszInt(L"Width",rect.Width());
rejestr.ZapiszInt(L"Height",rect.Height());
rejestr.ZamknijKlucz();
} }
void CPrzykladDlg::OnDestroy() {
CDialog::OnDestroy();
ZapiszPolozenieIWielkoscOknaWRejestrze(this->m_hWnd, L"Software\\UMK\\Przyklad\\Okno");
}
Zapis i odczyt danych aplikacji
Zapis i odczyt danych aplikacji
Przykład: przechowywanie położenia i rozmiaru okna
bool CzytajPolozenieIWielkoscOknaZRejestru(HWND uchwytOkna,const wchar_t* klucz) {
...
if(rejestr.OtworzKlucz(klucz)) {
try {
left = rejestr.CzytajInt(L"Left");
top = rejestr.CzytajInt(L"Top");
width = rejestr.CzytajInt(L"Width");
height = rejestr.CzytajInt(L"Height");
MoveWindow(uchwytOkna,left,top,width,height,TRUE);
wynik=true;
}
catch /*...*/
rejestr.ZamknijKlucz();
}
return wynik;
}
BOOL CPrzykladDlg::OnInitDialog() {
CDialog::OnInitDialog();
...
if (!CzytajPolozenieIWielkoscOknaZRejestru(this->m_hWnd, L"Software\\UMK\\Przyklad\\Okno")) {
MessageBox(L"Pierwsze uruchomienie programu");
}
return TRUE;
}
Automatyczne uruchamianie
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run po zalogowaniu użytkownika (tego, w którego kluczu znajduje się wpis)
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce po zalogowaniu użytkownika, wartości usuwane po jednokrotnym uruchomieniu
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run po zalogowaniu dowolnego użytkownika
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce j.w., ale wartości usuwane po jednokrotnym uruchomieniu
HKLM\Software\Microsoft\Windows\CurrentVersion\RunServices do uruchamiania usług, już przy pokazaniu okna logowania
HKLM\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce
j.w., ale wartości usuwane po jednokrotnym uruchomieniu
Automatyczne uruchamianie
enum CAutostartCzynnosci { acSprawdz = 0, acZapisz = 1, acUsun = 2 };
bool KonfigurujAutostart(HKEY kluczGlowny, const wchar_t* nazwa,
const wchar_t* sciezkaPliku, CAutostartCzynnosci czynnosc) {
const wchar_t klucz[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
bool wynik = false;
CRejestr rejestr(kluczGlowny, (czynnosc == acSprawdz)?KEY_READ:KEY_WRITE);
if(!rejestr.CzyKluczIstnieje(klucz)) ...
if(rejestr.OtworzKlucz(klucz)) {
switch (czynnosc) {
case acSprawdz: wynik = rejestr.CzyWartoscIstnieje(nazwa); break;
case acZapisz: wynik = rejestr.ZapiszString(nazwa,sciezkaPliku); break;
case acUsun: wynik = rejestr.UsunWartosc(nazwa); break;
}
rejestr.ZamknijKlucz();
}
return wynik;
}
Automatyczne uruchamianie
enum CAutostartCzynnosci { acSprawdz = 0, acZapisz = 1, acUsun = 2 };
...
bool CzyIstniejeZapisAutostart(HKEY kluczGlowny, const wchar_t* nazwa) {
return KonfigurujAutostart(kluczGlowny,nazwa,L"",acSprawdz);
}
bool ZapiszAutostart(HKEY kluczGlowny, const wchar_t* nazwa,const wchar_t* sciezkaPliku) {
return KonfigurujAutostart(kluczGlowny,nazwa,sciezkaPliku,acZapisz);
}
bool UsunAutostart(HKEY kluczGlowny, const wchar_t* nazwa) {
return KonfigurujAutostart(kluczGlowny,nazwa,L"",acUsun);
}
BOOL CPrzykladDlg::OnInitDialog() {
CDialog::OnInitDialog();
...
checkBox1.SetCheck((int)CzyIstniejeZapisAutostart(HKEY_CURRENT_USER, AfxGetAppName()));
return TRUE;
}
void CRejestrSystemuWindowsDlg::OnBnClickedCheck1() {
wchar_t sciezkaPliku[MAX_PATH]; GetModuleFileName(NULL,sciezkaPliku,MAX_PATH);
if(checkBox1.GetCheck()) ZapiszAutostart(HKEY_CURRENT_USER,AfxGetAppName(),sciezkaPliku);
else UsunAutostart(HKEY_CURRENT_USER,AfxGetAppName());
}
Informacje o zainstalowanych aplk.
• Klucz:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
• Przechowywane dane:
struct CDodajUsunInfo {
CString DisplayName, DisplayIcon, DisplayVersion, Contact, Publisher, Comments, URLUpdateInfo, URLInfoAbout, InstallLocation, InstallSource, ProductID, UninstallString, UninstallPath, ModifyPath, Readme, HelpLink, HelpTelephone, RegCompany, RegOwner, LogFile;
int VersionMajor, VersionMinor, NoRemove, NoRepair, Language;
};
Demo: RejestrSystemuWindows
• Przechowywanie położenia i rozmiaru okna (sprawdzić RegEdit)
• Automatyczne uruchamianie aplikacji
• Informacje dla apletu Dodaj/Usuń programy
Informacje o zainstalowanych aplk.
• Klucz katalogów specjalnych:
Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
• Lepiej używać funkcji powłoki (zob. poprzedni wykład)
wchar_t* PobierzSciezkeDoKataloguSpecjalnego(const wchar_t* nazwa, wchar_t* katalog) {
const wchar_t klucz[] =
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
CRejestr rejestr(HKEY_CURRENT_USER, KEY_READ,true);
if (rejestr.OtworzKlucz(klucz)) {
if (rejestr.CzyWartoscIstnieje(nazwa)) rejestr.CzytajString(nazwa,katalog);
else throw std::exception("Wartosc nie istnieje");
rejestr.ZamknijKlucz();
}
else throw std::exception("Klucz nie istnieje lub nie może być otwarty");
return katalog;
}
wchar_t* PobierzSciezkeDoKataloguMojeDokumenty(wchar_t* katalog) {
return PobierzSciezkeDoKataloguSpecjalnego(L"Personal",katalog);
}