powered by simpleCommunicator - 2.0.55     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / chr(10)/chr(13) какие-то непонятки
22 сообщений из 22, страница 1 из 1
chr(10)/chr(13) какие-то непонятки
    #37279233
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем есть параметр в реестре:
ab (REG_SZ)
Коварность в том что в нем может содержаться несколько значений через разделитель:
aaa<>bbb<>ccc...
В реестре WinXP разделитель отображается как квадратик (прямоугольничек), в Vista/Win7 вообще никак не отображается.
Надо этот параметр "прочесть" и разбить на значения aaa,bbb,ccc и т.д.
================
Способ1:
(1) С++ прога (не знаю как вытаскивает из реестра) сохраняет значение в файле:

Код: plaintext
1.
   if (args.HasOption("blablabla")) {
      fprintf(the_filename,"blablabla=" + args.GetOptionString("blablabla") + "\n");
(2) потом я читаю файл через VB
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Function ReadAllFile(FileName As String) As String
    Dim str As String
    Dim mychar
    str = ""
    Open FileName For Binary As # 1     ' Open file.
    Do While Not EOF( 1 )    ' Loop until end of file.
        mychar = Input( 1 , # 1 )   ' Get one character.
        If EOF( 1 ) Then
            Exit Do
        End If
        str = str & mychar
    Loop
    Close # 1     ' Close file.
    ReadAllFile = str
End Function
(3) нахожу там строчку ," blablabla= aaa<>bbb<>ccc"
(4) ну и по символу <> расщепляю на aaa bbb и сcc
Так вот, этим символом <> оказывается chr(13)
==========
Данный способ по ряду причин не удобен и абсолютно непрофессионален, а самое плохое что C++ модуль включает тормоза (в силу его архитектурных особенностей, кот. объяснять долго и лишне) и на запуск формы с параметрами уходит много времени (несколько секунд на современном компе).
Плюс мне известно где в реестре хранятся параметры,
и я умею работать с ним напрямую (м.б. несколько миллисекунд на считывание реестра).
Посему счас перехожу на "способ 2"
===========================
Способ2:
(1) Читаю параметр blablabla напрямую из реестра:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
       .blablabla = GetRegValue(HKEY_CURRENT_USER, _
          "SOFTWARE\...", _
          "blablabla", "", False)

Private Function GetRegValue(hKey As Long, lpszSubKey As String, _
    szKey As String, szDefault As String, reg64 As Boolean) As Variant

    On Error GoTo ErrorRoutineErr:
    
    Dim phkResult As Long
    Dim lResult As Long
    Dim szBuffer As String
    Dim lBuffSize As Long
    
    'Create Buffer
    szBuffer = Space( 255 )
    lBuffSize = Len(szBuffer)
    
    'Open the key
    If reg64 Then
        RegOpenKeyEx hKey, lpszSubKey,  0 ,  1  Or KEY_WOW64_64KEY, phkResult
    Else
        RegOpenKeyEx hKey, lpszSubKey,  0 ,  1 , phkResult
    End If
    
    'Query the value
    lResult = RegQueryValueEx(phkResult, szKey,  0 , _
         0 , szBuffer, lBuffSize)
    
    'Close the key
    RegCloseKey phkResult
    
    'Return obtained value
    If lResult = ERROR_SUCCESS Then
        GetRegValue = Left(szBuffer, lBuffSize -  1 )
    Else
        GetRegValue = szDefault
    End If
    Exit Function
    
ErrorRoutineErr::
    'MsgBox "ERROR #" & str$(Err) & " : " & Error & Chr(13) _
    '     & "Please exit and try again."
    GetRegValue = ""
End Function

(2) имею aaa<>bbb<>ccc

(3) ну и по символу <> расщепляю на aaa bbb и сcc
Так вот, этим символом <> оказывается chr(10)

Т.е. один и тот же <> интерпретируется как chr(10) вместо chr(13).
Мне не сложно заменить в последующем коде работы с параметрами chr(13) -> на chr(10)
но меня это несколько смущает: вдруг где-то что-то не так сработает.
Хочу получить комментарий/объяснение/успокоение почему так.

====
И еще сразу:

Код: plaintext
1.
Private Function GetRegValue
szBuffer = Space( 255 )
Длина "blablabla" может быть много больше 255. Я смогу своей GetRegValue прочитать корректно длинный параметр?
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37279328
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Т.е. один и тот же <> интерпретируется как chr(10) вместо chr(13).
Нет. В реестре - CHR(10). При записи в файл он заменяется на CHR(13).

Дмитрий77Длина "blablabla" может быть много больше 255. Я смогу своей GetRegValue прочитать корректно длинный параметр?Нет. Следует зарезервировать минимум столько, сколько надо для помещения всего значения. Больше - можно.
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37279329
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий77,
авторДлина "blablabla" может быть много больше 255. Я смогу своей GetRegValue прочитать корректно длинный параметр?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
' Obtain requared buffer size
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)

if lResult = ERROR_SUCCESS then
' Create buffer
    szBuffer = Space(lBuffSize)
' Query the value
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , szBuffer, lBuffSize)
else
 ' error handling
end if
RegQueryValueEx Function
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37281634
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaДмитрий77Т.е. один и тот же <> интерпретируется как chr(10) вместо chr(13).
Нет. В реестре - CHR(10). При записи в файл он заменяется на CHR(13).
Ладно, с этим успокоили. Заменяем в Split-коде chr(13) -> chr(10), более не заморачиваемся и не паримся.

AkinaДмитрий77Длина "blablabla" может быть много больше 255. Я смогу своей GetRegValue прочитать корректно длинный параметр?Нет. Следует зарезервировать минимум столько, сколько надо для помещения всего значения. Больше - можно.
Да, уже увидел. На тестовой строке в 1000 символов.
У меня может быть разрешенная конструкция:
a(1)<>a(2)<>a(3)...<>a(N)
с неограниченным количеством слагаемых, длина каждого a(n) например по 100 символов.
Если "Следует зарезервировать минимум столько, сколько надо", то надо писать
Код: plaintext
1.
2.
szBuffer = Space( 10000 )
'или
szBuffer = Space( 20000 )
слишком большие "излишки производства", не так ли? ( большинство параметров и обычно же сильно меньше).
Причем теоретически "может и перехлестнуть", архитектуру этих разделителей поменять не могу.
Посему вариант:
скукотища
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
' Obtain requared buffer size
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)

if lResult = ERROR_SUCCESS then
' Create buffer
    szBuffer = Space(lBuffSize)
' Query the value
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , szBuffer, lBuffSize)
else
 ' error handling
end if
RegQueryValueEx Function
мне нравится больше.
Однако применив в лоб получил "ошибки памяти".

Обсудим?
Код: plaintext
1.
2.
' Obtain requared buffer size
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)
if lResult = ERROR_SUCCESS then
Условие ERROR_SUCCESS здесь (если с выделенным нулем) не срабатывает,хотя при этом lBuffSize заполняется корректным значением. Поэтому if lResult = ERROR_SUCCESS на этом этапе делать нельзя. Я прав?

Рабочим вариантом (вроде как) получился следующий:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
Private Function GetRegValue(hKey As Long, lpszSubKey As String, _
    szKey As String, szDefault As String, reg64 As Boolean) As Variant

    On Error GoTo ErrorRoutineErr:
    
    Dim phkResult As Long
    Dim lResult As Long
    Dim szBuffer As String
    Dim lBuffSize As Long
    
    'Open the key
    If reg64 Then
        RegOpenKeyEx hKey, lpszSubKey,  0 ,  1  Or KEY_WOW64_64KEY, phkResult
    Else
        RegOpenKeyEx hKey, lpszSubKey,  0 ,  1 , phkResult
    End If
    
    'Query lBuffSize
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)
    'Create buffer
    szBuffer = Space(lBuffSize)
    'Query the value
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , szBuffer, lBuffSize)
    
    'Close the key
    RegCloseKey phkResult
    
    'Return obtained value
    If lResult = ERROR_SUCCESS Then
        GetRegValue = Left(szBuffer, lBuffSize -  1 )
    Else
        GetRegValue = szDefault
    End If
    Exit Function
    
ErrorRoutineErr::
    GetRegValue = ""
End Function

Сойдет? Или что-то не так? (P.S. последний параметр ф-ции в обычном 100%-32битном случае всегда false, внимание обращать не надо; true - чтоб залезть в 64-битный реестр из нашего 32-битного приложения)
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37281751
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий77Условие ERROR_SUCCESS здесь (если с выделенным нулем) не срабатывает
Из первоисточника :
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 enables an application to determine the best way to allocate a buffer for the value's data.
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37283261
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
скукотища Из первоисточника :
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 enables an application to determine the best way to allocate a buffer for the value's data.
Я охотно верю (и вижу ) что там так написано, но участок моего кода (+ добавленный debug)
Код: plaintext
1.
2.
3.
4.
5.
6.
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)
    Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize
    'Create buffer
    szBuffer = Space(lBuffSize)
    'Query the value
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , szBuffer, lBuffSize)
    Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize
дает мне следующее:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
........
lResult= 234 ;lBuffSize= 20 
lResult= 0 ;lBuffSize= 20 
lResult= 234 ;lBuffSize= 12 
lResult= 0 ;lBuffSize= 12 
lResult= 234 ;lBuffSize= 26 
lResult= 0 ;lBuffSize= 26 
lResult= 234 ;lBuffSize= 17 
lResult= 0 ;lBuffSize= 17 
lResult= 234 ;lBuffSize= 8 
lResult= 0 ;lBuffSize= 8 
lResult= 2 ;lBuffSize= 0 
lResult= 2 ;lBuffSize= 0 
lResult= 234 ;lBuffSize= 6 
lResult= 0 ;lBuffSize= 6 
....
Ну т.е.
Код: plaintext
1.
    'Query lBuffSize
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)
дает либо
lResult=234;lBuffSize=20
Const ERROR_MORE_DATA = 234&

По утверждению что вы привели должен быть 0=error seccess

либо сразу
lResult=2;lBuffSize=0
(нету в реестре этого параметра)

Как я уже сказал, с моим кодом (ф-ция целиком выше) жить вроде можно. А можно ли?
Но все же, если не так то что делаю: м.б. 0 с амперсандом надо писать или с ByVal/ByRef где непонятки.
Поправьте, что не так.
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37283305
Ципихович Эндрю
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,
не подскажите, хочу сделать это
Закрыть средствами системного реестра возможность копирования информации с ПК на любой флеш-накопитель
Есть скрипт?
что-то вставляю в ВБА
5 констант:
Const HKEY_CLASSES_ROOT = -2147483648 (&H80000000)
Const HKEY_CURRENT_USER = -2147483647 (&H80000001)
Const HKEY_LOCAL_MACHINE = -2147483646 (&H80000002)
Const HKEY_PERFORMANCE_DATA = -2147483644 (&H80000004)
Const HKEY_USERS = -2147483645 (&H80000003)

все выделены красным цветом, что за ересь?
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37283308
Ципихович Эндрю
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37283313
Ципихович Эндрю
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
понял, видимо так нужно:
Код: plaintext
1.
2.
3.
4.
Private Const HKEY_CLASSES_ROOT = - 2147483648 # '(&H80000000)
 Private Const HKEY_CURRENT_USER = - 2147483647  '(&H80000001)
 Private Const HKEY_LOCAL_MACHINE = - 2147483646  '(&H80000002)
 Private Const HKEY_PERFORMANCE_DATA = - 2147483644  '(&H80000004)
 Private Const HKEY_USERS = - 2147483645  '(&H80000003)
так, да??
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37283460
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ципихович Эндрю,

Обычно пишут так
Код: plaintext
1.
2.
3.
Private Const HKEY_CLASSES_ROOT = &H80000000
Private Const HKEY_CURRENT_USER = &H80000001
Private Const HKEY_LOCAL_MACHINE = &H80000002
Private Const HKEY_USERS = &H80000003
Хотя не совсем понимаю какое это имеет отношение к моему вопросу про размер буфера для параметра реестра, а тем более к chr(10)/chr(13)
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37283708
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий77Как я уже сказал, с моим кодом (ф-ция целиком выше) жить вроде можно. А можно ли?
Но все же, если не так то что делаю: м.б. 0 с амперсандом надо писать или с ByVal/ByRef где непонятки.
Поправьте, что не так.
Вроде бы нашёл, "дэ собака порывся":
RegQueryValueEx возвращает ERROR_MORE_DATA если lBuffSize меньше размера запрашиваемых данных,
независимо от того, просим мы вернуть данные или нет ( передаем ссылку на szBuffer или Null )
Помогло такое:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
' Obtain requared buffer size
    lBuffSize = - 1 
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)

if lResult = ERROR_SUCCESS then
' Create buffer
    szBuffer = Space(lBuffSize)
' Query the value
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , szBuffer, lBuffSize)
else
 ' error handling
end if
объявления функций
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Declare Function RegOpenKeyEx& Lib "advapi32" Alias "RegOpenKeyExA" ( _
        ByVal hKey&, _
        ByVal lpSubKey$, _
        ByVal ulOptions%, _
        ByVal samDesired&, _
        phkResult&)

Declare Function RegCloseKey& Lib "advapi32" (ByVal hKey&)

Declare Function RegQueryValueEx& Lib "advapi32" Alias "RegQueryValueExA" ( _
        ByVal hKey&, _
        ByVal lpValueName$, _
        ByVal lpReserved%, _
        lpType&, _
        ByVal lpData$, _
        lpcbData&)
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37283972
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
скукотищаПомогло такое:
Код: plaintext
1.
2.
' Obtain requared buffer size
    lBuffSize = - 1 
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)

скукотища,
добавление lBuffSize = -1 действительно трансформирует ERROR_MORE_DATA в ERROR_SUCCESS
но при запросе "-цать" параметров на каком-нибудь обязательно будет VB-crash и memory не может быть read.
Почему не знаю.
Декларации ф-ций у нас одинаковы.
Ну, приведите ваш вариант Private Function GetRegValue целиком, я попробую посмотреть что будет при запросе моих "много параметров".

За что собственно боремся? за ERROR_SUCCESS?

Дмитрий77Ну т.е.
Код: plaintext
1.
    'Query lBuffSize
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)
дает либо
lResult=234;lBuffSize=20
Const ERROR_MORE_DATA = 234&

А не наплевать ли нам на него? Нам ведь нужно lBuffSize=20 !!!
Чем не нравится мой код, приведенный целиком выше?
Ну да, есть издержка:
lResult=2;lBuffSize=0
и все равно запускаю RegQueryValueEx второй раз, но издержка никогда не даст ERROR_SUCCESS на втором шаге (когда уже прошу реальное значение), так что ничем не рискую.

Ну хорошо. Будем чуть более аккуратны:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
Private Function GetRegValue(hKey As Long, lpszSubKey As String, _
    szKey As String, szDefault As String, reg64 As Boolean) As Variant

    On Error GoTo ErrorRoutineErr:

    Dim phkResult As Long
    Dim lResult As Long
    Dim szBuffer As String
    Dim lBuffSize As Long

    'Open the key
    If reg64 Then
        RegOpenKeyEx hKey, lpszSubKey,  0 ,  1  Or KEY_WOW64_64KEY, phkResult
    Else
        RegOpenKeyEx hKey, lpszSubKey,  0 ,  1 , phkResult
    End If

    'Query lBuffSize
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)
    Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize
    If lResult = ERROR_MORE_DATA Then
        'Create buffer
        szBuffer = Space(lBuffSize)
        'Query the value
        lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , szBuffer, lBuffSize)
        Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize

        'Close the key
        RegCloseKey phkResult

        'Return obtained value
        If lResult = ERROR_SUCCESS Then
            GetRegValue = Left(szBuffer, lBuffSize -  1 )
        Else
            GetRegValue = szDefault
        End If
    Else
        'Close the key
        RegCloseKey phkResult
        GetRegValue = szDefault
    End If
    Exit Function

ErrorRoutineErr::
    GetRegValue = ""
End Function
Такой вариант нормальный? ERROR_MORE_DATA == Успех!!! в данном случае.
Хотя вот честно от греха подальше оставил бы свой предыдущий вариант без проверки этого этапа, т.е. с издержками безусловным запуском
Код: plaintext
1.
 'Query the value
        lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , szBuffer, lBuffSize)
Вдруг там что-то кроме ERROR_MORE_DATA может означать успех? (когда с нулем!!!)
Что скажете?
---
Еще кстати несколько смущает
Код: plaintext
lResult= 2 ;lBuffSize= 0 
(если ключа не существует).
Во всяких документациях на эту тему не нашел ошибки за номером 2 !!!
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37283988
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий77,
>но при запросе "-цать" параметров на каком-нибудь обязательно будет VB-crash и memory не может быть read.
всего лишь предположение - VB пробует выполнять Ваш код в несколько потоков, хотя Вы об этом его не просите. Как пресечь - не знаю.

>Ну, приведите ваш вариант...
функцию не писал, обошелся "наколенной" процедурой с заданием параметров константами в последей
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
Option Explicit

' ******************************************************
' чтение параметра типа REG_SZ из реестра
' ******************************************************

'LONG RegOpenKeyEx(
'    HKEY hKey,  // дескриптор указанного ключа
'    LPCTSTR lpSubKey,   // адрес имени открываемого подключа
'    DWORD ulOptions,    // зарезервировано
'    REGSAM samDesired,  // маска доступа безопасности
'    PHKEY phkResult     // адрес дескриптора открытого ключа
');

'LONG WINAPI RegCloseKey(
'  __in  HKEY hKey
');

'LONG WINAPI RegQueryValueEx(
'  __in         HKEY hKey,
'  __in_opt     LPCTSTR lpValueName,
'  __reserved   LPDWORD lpReserved,
'  __out_opt    LPDWORD lpType,
'  __out_opt    LPBYTE lpData,
'  __inout_opt  LPDWORD lpcbData
');

Private Declare Function RegOpenKeyEx& Lib "advapi32" Alias "RegOpenKeyExA" ( _
        ByVal hKey&, _
        ByVal lpSubKey$, _
        ByVal ulOptions%, _
        ByVal samDesired&, _
        phkResult&)

Private Declare Function RegCloseKey& Lib "advapi32" (ByVal hKey&)

Private Declare Function RegQueryValueEx& Lib "advapi32" Alias "RegQueryValueExA" ( _
        ByVal hKey&, _
        ByVal lpValueName$, _
        ByVal lpReserved%, _
        lpType&, _
        ByVal lpData$, _
        lpcbData&)

Private Const HKLM& = &H80000002        '0x80000002
Private Const KEY_READ& = &H20019       '0x20019
Private Const ERROR_SUCCESS& =  0         '0x0
Private Const ERROR_FILE_NOT_FOUND& =  2  '0x2
Private Const ERROR_INVALID_HANDLE& =  6  '0x6
Private Const ERROR_MORE_DATA& =  234     '0xEA


Sub readreg()
Const S_SubKey$ = "SOFTWARE\Microsoft\Windows\CurrentVersion\Control Panel\Cpls"
Const S_KeyName$ = "Speech"
Dim sValue$, sSubKey$, lResult&, lType&, lDataLen&
Dim sKeyName$, lPHK&

sSubKey = S_SubKey & Chr( 0 )
sKeyName = S_KeyName & Chr( 0 )

lResult = RegOpenKeyEx(HKLM, sSubKey,  0 , KEY_READ, lPHK)
If lResult = ERROR_SUCCESS Then
        lDataLen = - 1 
        lResult = RegQueryValueEx(lPHK, sKeyName,  0 ,  0 ,  0 , lDataLen)
        
        If lResult = ERROR_SUCCESS Then
                sValue = Space(lDataLen)
                lResult = RegQueryValueEx(lPHK, sKeyName,  0 ,  0 , sValue, lDataLen)
                If lResult = ERROR_SUCCESS Then
                        sValue = trimnullch(sValue)
                        MsgBox "key='" & sValue & "'"
                Else:   Debug.Print "err read: " & Hex(lResult)
                End If
        Else:   Debug.Print "error query len: " & Hex(lResult)
        End If
Else:   Debug.Print "open key res: " & Hex(lResult)
End If

If lPHK <>  0  Then lResult = RegCloseKey(lPHK): Debug.Print "closing key: " & Hex(lResult)

End Sub

Function trimnullch$(s$)
Dim k&
k = InStrRev(s, vbNullChar)
If k >  0  Then
        trimnullch = Left(s, k -  1 )
Else:   trimnullch = s
End If
End Function

>За что собственно боремся? за ERROR_SUCCESS?
Да, за него, родимого. Можно и наплевать. Необходимый размер буфера получили. Чего же боле?(с)

>Еще кстати несколько смущает
> lResult=2;lBuffSize=0
Ничего аномального: If the function fails, the return value is a system error code
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37283994
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ЗЫ:
>Еще кстати несколько смущает
> lResult=2;lBuffSize=0
Наверное правильнее было бы интерпретировать этот ответ так:
If the lpValueName registry value does not exist, the function returns ERROR_FILE_NOT_FOUND
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37285869
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
скукотищаДмитрий77,
>но при запросе "-цать" параметров на каком-нибудь обязательно будет VB-crash и memory не может быть read.
всего лишь предположение - VB пробует выполнять Ваш код в несколько потоков, хотя Вы об этом его не просите. Как пресечь - не знаю.
>Ну, приведите ваш вариант...
функцию не писал, обошелся "наколенной" процедурой с заданием параметров константами в последей
Я вставил вашу Sub в тест-проект (в приложении).
1)Запустите в VB среде
2) Нажмите Command1 -в debug получите результат
3) Остановите проект.
4) Закройте проект (vb среду)

На шаге (4) будет
1) vb-crash
2) возможно память не может быть read

Думаю природа собаки таже.
(с реальными параметрами у меня этот crash получается еще на этапе выполнения проги)


скукотища>За что собственно боремся? за ERROR_SUCCESS?
Да, за него, родимого. Можно и наплевать. Необходимый размер буфера получили. Чего же боле?(с)

Вот я тоже думаю использовать свой код и не париться боле, ибо он не дает crash.
Беспокоит одно: не гавкнет ли зарытая собака и с моим кодом тоже при каких-то обстоятельствах?
Проблема возникает тогда, когда пытаетесь заранее инициализировать буфер (lDataLen =X особенно с -1), а потом его переигрываете через запрос с нулевым параметром. Если lDataLen не инициализировать перед запросом с нулем, то вроде как не гавкает.
Чего вы там проверяете/высчитываете потом это неважно.
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37286322
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий77,
нравится мне ERROR_SUCCESS :)
Поменял в выложенном Вами проекте объявление функции RegQueryValueEx и первый её вызов (получение размера). Падения прикратились.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Private Declare Function RegQueryValueEx& Lib "advapi32" Alias "RegQueryValueExA" ( _
        ByVal hKey&, _
        ByVal lpValueName$, _
        ByVal lpReserved%, _
        lpType&, _
        Optional ByVal lpData$, _
        Optional lpcbData&)


...
        lDataLen = - 1 
        lResult = RegQueryValueEx(lPHK, sKeyName,  0 ,  0 , , lDataLen)
...

ЗЫ:
Сачала пробовал поменять объявление на такое
Код: plaintext
1.
2.
3.
4.
5.
6.
Private Declare Function RegQueryValueEx& Lib "advapi32" Alias "RegQueryValueExA" ( _
        ByVal hKey&, _
        ByVal lpValueName$, _
        ByVal lpReserved%, _
        lpType&, _
        ByVal lpData&, _
        lpcbData&)
Падения, как и следовало ожидать прекратились. Но при получении значения
Код: plaintext
                lResult = RegQueryValueEx(lPHK, sKeyName,  0 ,  0 , sValue, lDataLen)
получалось дикое недоразумение с длиной строки sValue и кодировкой символов. "Спасался" так
Код: plaintext
                        sValue = StrConv(sValue, vbUnicode)
, плюс ещё поменял функцию trimnullch на поиск первого вхождения vbNullChar

Решение показалось черезчур диким. Пришлось включать мозг
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37286333
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
поправочъка к "ЗЫ":

...
Падения, как и следовало ожидать прекратились. Но при получении значения
Код: plaintext
1.
                lResult = RegQueryValueEx(lPHK, sKeyName,  0 ,  0 , StrPtr(sValue), lDataLen)
получалось ...
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37286466
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
скукотищаПоменял в выложенном Вами проекте объявление функции RegQueryValueEx и первый её вызов (получение размера). Падения прикратились.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Private Declare Function RegQueryValueEx& Lib "advapi32" Alias "RegQueryValueExA" ( _
        ByVal hKey&, _
        ByVal lpValueName$, _
        ByVal lpReserved%, _
        lpType&, _
        Optional ByVal lpData$, _
        Optional lpcbData&)


...
        lDataLen = - 1 
        lResult = RegQueryValueEx(lPHK, sKeyName,  0 ,  0 , , lDataLen)
...

Да, падения в моем рабочем (с реальными данными и в процессе их получения) также прекратились если этим воспользоваться. С одной стороны разумно.
lDataLen = -1 кстати лишнее (и ничем не обосновано), проверьте. Если убрать + Optional в декларациях + передавать пустой предпоследний параметр вместо нуля, то будет ERROR_SUCCESS все равно.

скукотищаДмитрий77,
нравится мне ERROR_SUCCESS :)
Может это правда только Ваша прихоть, не более?
Ведь первоисточник гласит:
первоисточник
If the buffer specified by lpData parameter is not large enough to hold the data, the function returns ERROR_MORE_DATA and stores the required buffer size in the variable pointed to by lpcbData. In this case, the contents of the lpData buffer are undefined.
--
If the lpData buffer is too small to receive the data, the function returns ERROR_MORE_DATA.
Это в общем то согласуется с моим рабочим вариантом как бы, не так ли?
При передаче нуля в lpData (szBuffer), он по определению всегда будет too small и никогда не будет large enough to hold the data, и всегда будет возвращать ERROR_MORE_DATA, ну кроме случая 2=Not Found, естественно.

А с другой стороны..да действительно, в оригинале 3 последние параметра Opt.

Как все-таки правильно то оставить?
I. Вариант мой первый:
Код: plaintext
1.
2.
3.
4.
5.
    'Query lBuffSize
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)
    'Create buffer
    szBuffer = Space(lBuffSize)
    'Query the value
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , szBuffer, lBuffSize)
==============================================
II. Вариант мой второй:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
    'Query lBuffSize
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 ,  0 , lBuffSize)
    Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize
    If lResult = ERROR_MORE_DATA Then
        'Create buffer
        szBuffer = Space(lBuffSize)
        'Query the value
        lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , szBuffer, lBuffSize)
        Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize
===============================================
III. Или вариант аля-Ваш:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
 Declare Function RegQueryValueEx& Lib "advapi32" Alias "RegQueryValueExA" ( _
        ByVal hKey&, _
        ByVal lpValueName$, _
        ByVal lpReserved%, _
        lpType&, _
        Optional ByVal lpData$, _
        Optional lpcbData&)
...........
    'Query lBuffSize
    lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , , lBuffSize)
    Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize
    If lResult = ERROR_SUCCESS Then
        'Create buffer
        szBuffer = Space(lBuffSize)
        'Query the value
        lResult = RegQueryValueEx(phkResult, szKey,  0 ,  0 , szBuffer, lBuffSize)
        Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37286483
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий77,
учитывая мою привязанность к ERROR_SUCCESS
я бы оставил третий вариант. И ещё бы поменял описание и вызовы функци RegQueryValueEx, чтобы добиться полного(?) соответствия описанию на msdn. Как результат - проще будет сопровождать код.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
 Declare Function RegQueryValueEx& Lib "advapi32" Alias "RegQueryValueExA" ( _
        ByVal hKey&, _
        ByVal lpValueName$, _
        ByVal lpReserved%, _
        Optional lpType&, _
        Optional ByVal lpData$, _
        Optional lpcbData&)
...........
    'Query lBuffSize
    lResult = RegQueryValueEx(phkResult, szKey,  0 , , , lBuffSize)
    Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize
    If lResult = ERROR_SUCCESS Then
        'Create buffer
        szBuffer = Space(lBuffSize)
        'Query the value
        lResult = RegQueryValueEx(phkResult, szKey,  0 , , szBuffer, lBuffSize)
        Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37286505
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
скукотища,

OK, спасибо, возможно воспользуюсь именно третьим вариантом. Подумаю об этом позже, когда закончу с рутиной.
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37291619
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
скукотищаДмитрий77,
учитывая мою привязанность к ERROR_SUCCESS
я бы оставил третий вариант. И ещё бы поменял описание и вызовы функци RegQueryValueEx, чтобы добиться полного(?) соответствия описанию на msdn. Как результат - проще будет сопровождать код.
+
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
 Declare Function RegQueryValueEx& Lib "advapi32" Alias "RegQueryValueExA" ( _
        ByVal hKey&, _
        ByVal lpValueName$, _
        ByVal lpReserved%, _
        Optional lpType&, _
        Optional ByVal lpData$, _
        Optional lpcbData&)
...........
    'Query lBuffSize
    lResult = RegQueryValueEx(phkResult, szKey,  0 , , , lBuffSize)
    Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize
    If lResult = ERROR_SUCCESS Then
        'Create buffer
        szBuffer = Space(lBuffSize)
        'Query the value
        lResult = RegQueryValueEx(phkResult, szKey,  0 , , szBuffer, lBuffSize)
        Debug.Print "lResult=" & lResult & ";lBuffSize=" & lBuffSize

Вставил этот вариант (в лоб с декларацией RegQueryValueEx& как написано) в рабочее приложение. Время на "тестирование" как бы есть, посмотрю не грохнется ли случайно.

Кстати, только сейчас обратил внимание:
& -наверно long, $ -наверно string, % -я в растерянности

А "по-человечески" (раз разбираетесь) можете записать с применением As Long, As String, As e.t.c ?
Если не сложно, чтоб случайно не ошибиться и все не угробить...
Или с $/&/% оставить?
...
Рейтинг: 0 / 0
chr(10)/chr(13) какие-то непонятки
    #37292628
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий77,
по человечески
Код: plaintext
1.
2.
3.
4.
5.
6.
 Declare Function RegQueryValueEx Lib "advapi32" Alias "RegQueryValueExA" ( _
        ByVal hKey As Long, _
        ByVal lpValueName As String, _
        ByVal lpReserved As Integer, _
        Optional lpType As Long, _
        Optional ByVal lpData As String, _
        Optional lpcbData As Long) As Long
% - сокращение для Integer ( есть в справке в описании типа данных )
! - Single, # - Double
Long и String Вы правильно идентифицировали.
авторИли с $/&/% оставить? Дело вкуса. Пишите, как Вам удобно.
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / chr(10)/chr(13) какие-то непонятки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]