Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RusFAQ.ru: Программирование на Basic / VBA


Информационный Канал Subscribe.Ru


RusFAQ.ru: Программирование на Basic / VBA

Выпуск № 010
от 13.06.2002, 20:10

Администратор:
Имя: Калашников О.А.
URL: Информационный ресурс
ICQ: 68951340
Россия, Москва
О рассылке:
Задано вопросов: 15
Отправлено ответов: 26
Активность: 173.3 %
[Задать вопрос >>][Регистрация эксперта >>]
[Поиск в базе]


 Список экспертов, ответы которых опубликованы в данном выпуске

Dim
Статус: Начальный
Общий рейтинг: 138.46
[Подробней >>]
masquer
Статус: Профессиональный
Общий рейтинг: 161.28
[Подробней >>]


 Краткий перечень вопросов

Вопрос № 14. Пытаюсь обратиться к реестру, но проблеска выходит: RegQueryValueEx возвращает строку, состоящую из... (ответов: 2)

Вопросов: 1, ответов: 2


 Вопрос № 14

Пытаюсь обратиться к реестру, но проблеска выходит:
RegQueryValueEx возвращает строку, состоящую из нулей(пустую), хотя длину передает верную. RegEdit - работает, пути заданы верно, права имеются полные, а читать не хочет.
При попытке задать какое-либо значение в RetSize(последний параметр) VB улетает польностью (память какая-то не может быть "read" или "written".
regSetValueEx работает верно!
PS. Пути указаны верно, тип параметра - строка(верно), сижу под Win2000 SP2SRP1 c VB6SP5.



Вопрос отправлен: 10.06.2002, 20:07
Отправитель: pin

[Следующий вопрос >>] [Список вопросов]

Отвечает Dim

Привет, pin!
Ты не привел кусок кода, но я подозреваю, что ты сделал очень распространенную ошибку (все с нее начинали :) при передаче поинтера на строку.
Поэтому не возражаешь, если я начну с ликбеза? :) Просто работа со строками в ВБ несколько э-э-э... хитро завернута.
Итак: хотим юзать функцию RegQueryValueEx.
Открываем Platform SDK (а это musthave для ЛЮБОГО программиста под Windows) и набираем в индексной строке нашу функцию. Читаем (пропускаю тут то, что у тебя скорее всего не вызвало ошибки)
...
LONG RegQueryValueEx(
HKEY hKey, // handle to key
LPCTSTR lpValueName, // value name
LPDWORD lpReserved, // reserved
LPDWORD lpType, // type buffer
LPBYTE lpData, // data buffer
LPDWORD lpcbData // size of data buffer
);
...
lpData - [in, out] Pointer to a buffer that receives the value's data. This parameter can be NULL if the data is not required.
lpcbData - [in/out] Pointer to a variable that specifies the size, in bytes, of the buffer pointed to by the lpData parameter. When the function returns, this variable contains the size of the data copied to lpData.
If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, then lpcbData will also include the size of the terminating null character or characters.
The lpcbData parameter can be NULL only if lpData is NULL.
If the buffer specified by lpData parameter is not large enough to hold the data, the function returns the value ERROR_MORE_DATA, and stores the required buffer size, in bytes, into the variable pointed to by lpcbData. In this case, the contents of the lpValue buffer are undefined.
If lpData is NULL, and lpcbData is non-NULL, the function returns ERROR_SUCCESS, and stores the size of the data, in bytes, in the variable pointed to by lpcbData. This lets an application determine the best way to allocate a buffer for the value's data.
(Кстати, в последних строчках Microsoft дает совет как заранее определить размер буфера под lpData, думаю, мы им воспользуемся, чтобы не вывалиться по ERROR_MORE_DATA)
Так вот, параметр lpData - это ССЫЛКА на первый байт буфера (твоей строки) в памяти процесса. А что такое строка в ВБ? Это уже и есть ССЫЛКА (pointer)! И если в декларации функции не стоит ByVal, значит при использовании функции мы должны установить этот ByVal "насильно". А что произойдет в противном случае?
Бейсик "просмотрев" декларацию функции понимает, что следующий параметр (lpData) будет передан по ссылке (в стек будет закинут адрес этой переменной) и, функция, нисколько не сомневаясь, читает первые четыре байта по переданному адресу. А там? Вместо адреса на строку лежит сама строка "Здесь был pin". Вот в адрес, который сформировался из ascii кодов "Здес" и начнется запись из реестра. Хорошо, если это неиспользуемая (пока) область программы, а если по этому адресу лежит исполняемый сейчас код? Наверняка нас ждет крах программы и знакомое "Программа выполнила недопустимую операцию..."
Что делать? Если видим в декларации функции ByVal lpszSomeString - при использовании функции спокойно ставим переменную (или даже саму строку в кавычках) или StrPtr MyString. Если надо передать таким образом ссылку на массив, то обязательно указываем VarPtr MyArray(FirstElement). А если в декларации функции стоит ByRef lpszSomeString, то здесь наоборот, с массивом проще (пишем MyArray(FirstElement)), а вот со строкой - обязательно указываем ByVal MyString, и тогда мы уверены, что функция получит именно то что хотела - ссылку на строку.
Ну ладно. От теории к делу.
Возвращаемся к Platform SDK и декларируем функцию, переводя ее с С на ВБ:
Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" ( _
ByVal hKey As Long, _
ByVal lpValueName As String, _
ByVal lpReserved As Long, _
lpType As Long, _
lpData As Any, _
lpcbData As Long _
) As Long
(Тут бейсик не врубился, когда я стал передавать ему указатель на массив. В таких случаях всегда выручает As Any. Важно помнить, что функция В ЛЮБОМ случае ожидает от этого параметра 4 байта адреса)
Public Const LONG_NULL As Long = &H0
Далее, где то в форме:
'Получаем длину данных
retval = RegQueryValueEx(hKey, sValueName, LONG_NULL, LONG_NULL, LONG_NULL, lBufSize)
If (retval <> LONG_NULL) And (retval <> 234) Then
'Облом. Чего-то не так. Посмотрим, что даст объект Err
Debug.Print "Error#";CStr(Err.Number), Err.Description; " GetLastError:"; & Err.LastDllError
Call ErrorHandler() 'Аварийное завершение программы. Джентельмены извиняются и корректно уходят.
Else
'Все ОК
Debug.Print "RegQueryValueEx:OK"
End If
'Подготавливаем буфер
sBuffer = Space(lBufSize)
'Читаем данные:
retval = RegQueryValueEx(hKey, sValueName, LONG_NULL, LONG_NULL, ByVal sBuffer, lBufSize)
If (retval <> LONG_NULL) Or Len(sBuffer) <> lBufSize Then
Debug.Print "Опять облом. Ret="; retval
Call ErrorHandler()
Else
If lBufSize > 1 Then
Debug.Print "RegQueryValueEx:OK. BufSize = "; lBufSize
Else
'Да блин достало!
MsgBox "Do you want shutdown Microsoft Web Server?", vbYesNoPofig
End If
End If
Попробуй. Работает? Ну вот и enjoy! :))

Ответ отправлен: 10.06.2002, 22:17
Отправитель: Dim


Отвечает masquer

Добрый день, pin!
key = "SOFTWARE......" - вместо точек твой путь
r = RegOpenKey(HKEY_CURRENT_USER, key, keyhand)
lResult = RegQueryValueEx(keyhand, "registered", 0&, REG_DWORD, isreg, 4)
RegCloseKey keyhand

Ответ отправлен: 10.06.2002, 22:44
Отправитель: masquer



Форма отправки вопроса

Внимание!
Форма может работать некорректно в почтовых программах "Microsoft Outlook" и "Microsoft Outlook Express". В программе The Bat! подобные формы не работают вообще!
После нажатия на кнопку "Отправить", будет открыто второе окно. Заметьте, что в некоторых браузерах могут стоять запреты на открытие других окон, а также "чрезмерное" кэширование данных, при этом факт отправки Вашего вопроса стоит под сомнением.
Мы рекомендуем открывать рассылку в программе Internet Explorer 5.0+ или отправлять вопросы с сайта по адресу: http://rusfaq.ru/cgi-bin/Message.cgi.

© 2002 Команда RusFAQ.ru.

 Персональные данные

Ваше имя:

Ваш e-mail:

Опубликовать мой e-mail в рассылке


 Вопрос и дополнение

Ваш вопрос:


Приложение (если необходимо):


Получить ответов:


 Выбор рассылки

Программисту
Assembler (51)
C / C++ (30)
Perl (9)
Delphi (14)
Pascal (26)
Basic / VBA (15)
Java / JavaScript (6)
PHP (7)
MySQL / MSSQL (6)
Пользователю
Windows 95/98/Me (48)
Windows NT/2000/XP (34)
"Железо" (40)
Поиск информации (20)
Администратору
Windows NT/2000/XP (15)
Linux / Unix (9)
Юристу
Гражданское право (11)
Семейное право (5)
Трудовое право (6)
КоАП (3)

Отправить вопрос всем экспертам выбранной рассылки.




be number one Яндекс цитирования

© 2002 Россия, Москва. Авторское право: RusFAQ.ru

http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное