Здравствуйте!
Мне требуется реализовать программу, считывающую из системного реестра данные об установленных в операционной системе принтерах (для рабочей станции в целом и для каждого профиля пользователя). Информацию о принтерах выводить в файл (с помощью асинхронных файловых операций).
Итак..Прежде всего мне не ясно, как добраться до этой информации??
С помощью операции RegOpenKey открыть корневой ключ HKEY_USERS (случай для каждого профиля пользователя)? А как после добраться до нужной информации? И вообще, я хотя бы в том направлении думаю? И как быть со случаем "для рабочей станции"?
Объясните пожалуйста!
Для начала - в HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList лежит список пользователей (подпапки данного ключа), так что для начала надо открыть указанный ключ через RegOpenKeyEx, для него сделать перечисление всех дочерних веток с сипользованием RegEnumKey, в результате ты по поочередно получаешь ID пользователей, зарегистрированных в системе. А уж как получила ID - то открывать "HKEY_USERS\\" + ID + "\\Software\Microsoft\Windows NT\CurrentVersion\Devices" (здесь хранится список принтеров для каждого конкретного пользователя) и получать всю информацию, записанную там через RegEnumValue... То есть, будет что-то типа:
HKEY keyID = 0;(проверить не могу, я не под Windows сейчас...)
RegOpenKeyEx(
HKEY_LOCAL_MACHINE, L"software\\microsoft\\windows NT\\CurrentVersion\\ProfileList",
0, KEY_ALL_ACCESS, &keyID
);
for (int i = 0;; ++i) {
wchar_t IDname[256] = {};
LONG ret = RegEnumKey(keyID, i, IDname, 256);
if (ret != ERROR_SUCCESS) {
break; // Все, больше подпапок нет, выходим из цикла перечисления пользователей
}
// Здесь для каждого IDname открываешь его ветку HKU\...\Devices, и перечисляешь принтеры
// то есть, добавляется еще один цикл
} // всё, пользователи перечислены, выходим
RegCloseKey (IDkey); // и закрываем ключ реестра
// Здесь для каждого IDname открываешь его ветку HKU\...\Devices, и перечисляешь принтеры
HKEY keyUs = 0;
//RegOpenKeyEx(HKEY_USER,L"software\\microsoft\\windows NT\\CurrentVersion//\\Devices",0,KEY_ALL_ACCESS,&keyUs);
// а как сюда привязать IDname (ведь в путь я должна поставить, то что содержится в IDname...)
wchar_t reg_path[1024] = {0};
wsprintfW(reg_path, L"HKL_USERS\\%s\\software\\microsoft\\windows NT\\CurrentVersion\\Devices", IDname);
wsprintfW(reg_path, L"HKL_USERS\\%s\\software\\microsoft\\windows NT\\CurrentVersion\\Devices", IDname);
Я же говорю, все пишется прямо тут, без проверки... Цикл обработки очередного пользователя должен быть наподобие:
wchar_t reg_path[1024] = {0};
wsprintfW(reg_path, L"%s\\software\\microsoft\\windows NT\\CurrentVersion\\Devices", IDname);
RegOpenKeyEx(HKEY_USERS, reg_path, 0, KEY_ALL_ACCESS, &usrDevID);
// а теперь читаешь все принтеры пользователя IDname
for (int j = 0;; ++j) {
wchar_t AValue[MAX_VALUE_LEN] = {0}; // по-моему MAX_VALUE_LEN должно быть 2^14
DWORD nValue = MAX_VALUE_LEN;
LONG vret = RegEnumKey(usrDevID, j, AValue, &nValue, NULL, NULL, NULL, NULL);
if (vret != ERROR_SUCCESS) {
break; // Все, с очередным пользователем закончили
}
} // for j
RegCloseKey(usrDevID);
wchar_t reg_path[1024] = {0};
wsprintfW(reg_path, L"%s\\software\\microsoft\\windows NT\\CurrentVersion\\Devices", IDname);
RegOpenKeyEx(HKEY_USERS, reg_path, 0, KEY_ALL_ACCESS, &usrDevID);
// а теперь читаешь все принтеры пользователя IDname
for (int j = 0;; ++j) {
wchar_t AValue[MAX_VALUE_LEN] = {0}; // по-моему MAX_VALUE_LEN должно быть 2^14
DWORD nValue = MAX_VALUE_LEN;
LONG vret = RegEnumKey(usrDevID, j, AValue, &nValue, NULL, NULL, NULL, NULL);
if (vret != ERROR_SUCCESS) {
break; // Все, с очередным пользователем закончили
}
} // for j
RegCloseKey(usrDevID);
Это какому IDname соответствует? А в реестре смотрела, там действительно что-то есть для этого пользователя в ветке HKEY_USERS? Если нету, то так и должно быть.
Вроде разобралась...
for (int j = 0;; ++j) {
wchar_t AValue[MAX_VALUE_LEN] = {0};
DWORD nValue = MAX_VALUE_LEN;
LONG vret = RegEnumKey(usrDevID, j, AValue, &nValue, NULL, NULL, NULL, NULL);//Здесь заменила на RegEnumValue
.....
}
Да, вот я проверил в WinXP под Builder-ом:
, это точно работает, все принтеры перечисляются...
HKEY keyID = 0;
LONG L = RegOpenKeyExW(
HKEY_LOCAL_MACHINE, L"software\\microsoft\\windows NT\\CurrentVersion\\ProfileList",
0, KEY_ALL_ACCESS, &keyID);
for (int i = 0;; ++i) {
wchar_t IDname[256] = {0};
LONG ret = RegEnumKeyW(keyID, i, IDname, 256);
if (ret != ERROR_SUCCESS) {
break; // Все, больше подпапок нет, выходим из цикла перечисления пользователей
}
Memo1->Lines->Add(String("IDname = ") + IDname);
wchar_t reg_path[1024] = {0};
HKEY usrDevID = 0;
wsprintfW(reg_path, L"%s\\software\\microsoft\\windows NT\\CurrentVersion\\Devices", IDname);
LONG L1 = RegOpenKeyExW(HKEY_USERS, reg_path, 0, KEY_ALL_ACCESS, &usrDevID);
// а теперь читаем все принтеры пользователя IDname
for (int j = 0;; ++j) {
wchar_t AValue[MAX_VALUE_LEN] = {0}; // #define MAX_VALUE_LEN 16383
DWORD nValue = MAX_VALUE_LEN;
LONG vret = RegEnumValueW(usrDevID, j, AValue, &nValue, NULL, NULL, NULL, NULL);
if (vret != ERROR_SUCCESS) {
break; // Все, с очередным пользователем закончили
}
Memo1->Lines->Add(AValue);
} // for j
RegCloseKey(usrDevID);
} // всё, пользователи перечислены, выходим
RegCloseKey (keyID); // и закрываем ключ реестра
Спасибо!! У меня тоже всё перечисляется!
Ещё возник вопрос с записью в файл..
DWORD CountBytes=0;
hFile=CreateFile(L"C:\\Study\\Printers.txt",GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"software\\microsoft\\windows NT\\CurrentVersion\\ProfileList",
0,
KEY_ALL_ACCESS,
&keyID);
for (i = 0;; ++i)
{
wchar_t IDname[256] = {};
CountBytes=0;
LONG ret = RegEnumKey(keyID, i, IDname, 256);
if (ret != ERROR_SUCCESS)
{
break;// Все, больше подпапок нет, выходим из цикла перечисления пользователей
}
SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)IDname);
WriteFile(hFile,&IDname,wcslen(IDname),&CountBytes,NULL);
.....
}
Во-первых, чтобы корректно прочесть Блокнотом то, что записывается через WriteFile, надо добавить:
DWORD CountBytes=0;
hFile = CreateFile(L"C:\\Study\\Printers.txt", GENERIC_READ|GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, 0, NULL);
const char byteorder[2] = {-1, -2};
WriteFile(hFile,byteorder,2,&CountBytes,NULL); // <--- Вот это
WriteFile(hFile, &IDname, (wcslen(IDname) + 1) * sizeof(wchar_t), &CountBytes, NULL);
const char byteorder[2] = {-1, -2};
WriteFile(hFile,byteorder,2,&CountBytes,NULL); // <--- Вот это
WriteFile(hFile, &IDname, wcslen(IDname) * sizeof(wchar_t), &CountBytes, NULL);(хотя это нежелательно, все-таки завершающий ноль нужен), возможно Блокнот так реагирует на нулевые символы... Или ты пыталась добавить перевод строки?
WriteFile(hFile, &IDname, wcslen(IDname) * sizeof(wchar_t), &CountBytes, NULL);(хотя это нежелательно, все-таки завершающий ноль нужен), возможно Блокнот так реагирует на нулевые символы... Или ты пыталась добавить перевод строки?
wchar_t IDnameHelp[256]={0};
const char byteorder[2] = {-1,-2};
WriteFile(hFile,byteorder,2,&CountBytes,NULL);
wsprintf(IDnameHelp, L"Profile of User: %s\n", IDname);
WriteFile(hFile,&IDnameHelp,(wcslen(IDnameHelp)+1)*sizeof(wchar_t),&CountBytes,NULL);
Не знаю, что там творит VC, Билдер отрабатывает прекрасно:
wchar_t IDnameHelp[256]={0};:
wsprintfW(IDnameHelp, L"Profile of user: %s\r\n", IDname);
WriteFile(hFile, (LPVOID)IDnameHelp, wcslen(IDnameHelp) * sizeof(wchar_t), &CountBytes, NULL);
// цикл
wsprintfW(IDnameHelp, L"%s\r\n", AValue);
WriteFile(hFile, (LPVOID)IDnameHelp, wcslen(IDnameHelp)*sizeof(wchar_t), &CountBytes, NULL);
Ура! Отработало, ничего лишнего, на новую строку переводит!) Спасибо!
Меня интересует ещё один момент..всё о том же системном реестре..
Итак, приложение получает ин-цию о принтерах из реестра и записывает в файл..
И мне сказано по заданию, что настройки этого приложения должны храниться в реестре, в ветке HKCU\Software..
Это означает, что мне в этой ветке нужно создавать свой ключ, а для него какие-то параметры? И если да, то о каких настройках приложения может идти речь? Объясните пожалуйста!