Что нового

Дополнительные функции для работы с реестром

Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Потому что в последней версии WinAPEx эти константы уже присутствуют. Просто удали следующие строки:

Код:
Global Const $REG_NOTIFY_CHANGE_NAME = 0x01
Global Const $REG_NOTIFY_CHANGE_ATTRIBUTES = 0x02
Global Const $REG_NOTIFY_CHANGE_LAST_SET = 0x04
Global Const $REG_NOTIFY_CHANGE_SECURITY = 0x08
 

araneon

Новичок
Сообщения
59
Репутация
0
Ок, спасибо. И функцию тоже нужно было удалить ;)
 

araneon

Новичок
Сообщения
59
Репутация
0
У меня тут вопросик маленький возник, только сильно не пинайте за тупость, просто я с инглишем не дружу, да и знаний в Autoit`e маловато :'(
Подскажите, а как сделать, если мне нужно сохранить в файл несколько разных значений реестра, допустим

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\Explorer\Run


То есть нужно записать в файл ВСЕ, что храниться в каждой ветке, типа

===========================================================================
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run]

"uTorrent"="\"C:\\Program Files\\uTorrent\\utorrent.exe\""
"USB Safely Remove"="C:\\Program Files\\USB Safely Remove\\USBSafelyRemove.exe /startup"
===========================================================================
и т.д
Вот как-то, так что бы получалось.

За ранее СПАСИБО!!! ;) ;) ;)
 

BoaConstrictor-FENIX

Новичок
Сообщения
11
Репутация
1
Доброго времени суток!
Попытался использовать функцию _RegEnumValues() из первого поста
Код:
#Include <Array.au3>
#Include <Constants.au3>
#Include <WinAPIEx.au3>

;~Global Const $REG_BINARY = 3
;~Global Const $REG_DWORD = 4
;~Global Const $REG_DWORD_BIG_ENDIAN = 5
;~Global Const $REG_DWORD_LITTLE_ENDIAN = 4
;~Global Const $REG_EXPAND_SZ = 2
;~Global Const $REG_LINK = 6
;~Global Const $REG_MULTI_SZ = 7
;~Global Const $REG_NONE = 0
Global Const $REG_QWORD = 11
;~Global Const $REG_QWORD_LITTLE_ENDIAN = 11
;~Global Const $REG_SZ = 1

Global $hKey, $Hive

$hKey = _WinAPI_RegOpenKey($HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall')
_RegEnumValues($hKey, $Hive)
_WinAPI_RegCloseKey($hKey)

$Hive = StringSplit($Hive, ChrW(160))

_ArrayDisplay($Hive)

Func _RegEnumValues($hRoot, ByRef $sData, $iLevel = -1, $iLenght = 0, $iParam = 0, $sParam = 0)

    If (($iLevel > -1) And ($iParam > $iLevel)) Or (($iLenght) And (StringLen($sData) > $iLenght)) Then
        Return SetError(1, -1, 0)
    EndIf

    If Not $iParam Then
        $sData = ''
    EndIf

    $iParam += 1

    Local $hKey, $sKey, $aKey, $sVal, $aText, $sText, $Quotes, $Size, $Struct, $Type, $Sep = ChrW(160), $Error = 0
    Local $tData = DllStructCreate('byte[1048576]')
    Local $pData = DllStructGetPtr($tData)

    If $sParam Then
        $sData &= $sParam & '\' & $Sep
    EndIf
    $aKey = _WinAPI_RegQueryInfoKey($hRoot)
    If @error Then
        Return SetError(1, @extended, 0)
    EndIf
    For $i = 0 To $aKey[2] - 1
        $sVal = _WinAPI_RegEnumValue($hRoot, $i)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        $Size = _WinAPI_RegQueryValue($hRoot, $sVal, $tData)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        $Type = @extended
        If Not $sVal Then
            $sVal = '@'
        EndIf
        If Not $Size Then
            $sText = ''
        Else
            Switch $Type
                Case $REG_MULTI_SZ
                    $sText = ''
                    $aText = _WinAPI_StructToArray($pData)
                    If @error Then
                        Return SetError(1, -1, 0)
                    EndIf
                    For $j = 1 To $aText[0] - 1
                        $sText &= $aText[$j] & @LF
                    Next
                    If $aText[0] Then
                        $sText &= $aText[$aText[0]]
                    EndIf
                    $Quotes = 1
                Case Else
                    $Quotes = 0
                    Switch $Type
                        Case $REG_DWORD, $REG_DWORD_BIG_ENDIAN
                            $Struct = 'dword'
                        Case $REG_QWORD
                            $Struct = 'uint64'
                        Case $REG_SZ, $REG_EXPAND_SZ
                            $Struct = 'wchar[' & $Size & ']'
                            $Quotes = 1
                        Case Else
                            $Struct = 'byte[' & $Size & ']'
                    EndSwitch
                    $sText = DllStructGetData(DllStructCreate($Struct, $pData), 1)
                    If $Quotes Then
                        $sText = '"' & $sText & '"'
                    EndIf
            EndSwitch
        EndIf
        If $sParam Then
            $sData &= $sParam & '\\'
        EndIf
        $sData &= $sVal & '=(' & $Type & ')' & $sText & $Sep
    Next
    For $i = 0 To $aKey[0] - 1
        $sKey = _WinAPI_RegEnumKey($hRoot, $i)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        $hKey = _WinAPI_RegOpenKey($hRoot, $sKey, $KEY_READ)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        If $sParam Then
            _RegEnumValues($hKey, $sData, $iLevel, $iLenght, $iParam, $sParam & '\' & $sKey)
        Else
            _RegEnumValues($hKey, $sData, $iLevel, $iLenght, $iParam, $sKey)
        EndIf
        If @error Then
            $Error = @extended
            If Not $Error Then
                $Error = -1
            EndIf
        EndIf
        _WinAPI_RegCloseKey($hKey)
        If $Error Then
            ExitLoop
        EndIf
    Next
    If $iParam = 1 Then
        If Not $Error Then
            $sData = StringRegExpReplace($sData, $Sep & '*\Z', '')
        Else
            $sData = ''
        EndIf
    EndIf
    Return SetError($Error <> 0, $Error, $Error = 0)
EndFunc   ;==>_RegEnumValues
[/box]


В итоге выдает в консоль
Код:
>"C:\Program Files\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "C:\Новая папка (6)\test13.au3"
C:\????? ????? (6)\test13.au3 (22) : ==> Variable used without being declared.:
$hKey = _WinAPI_RegOpenKey($HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall')
$hKey = _WinAPI_RegOpenKey(^ ERROR
>Exit code: 1    Time: 0.414

Добавил
#Include <APIConstants.au3>
и закоментировал строку
Global Const $REG_QWORD = 11

В итоге скрипт отрабатывается но массив на выходе состоит только из одной ячейки "1".

Подскажите где я туплю пожалуйста.

И заодно подскажите, эта функция значения параметров DWORD выводит в 16-ричном представлении или в 10-чном.

Заранее благодарен.



Версия Autoit 3.3.8.1
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
BoaConstrictor-FENIX
у тебя наверное винда х64, а ты скрипт запускаешь как х86(32-битный). у меня так же..запускаю как х86 - возвращает массив с 1. а если как х64, то возвращает массив значений
 

erlik

Продвинутый
Сообщения
317
Репутация
84
BoaConstrictor-FENIX
Если все как написал joiner - windows 64-бит, а скрипт запускаешь как 32-битный, то для _WinAPI_RegOpenKey нужно использовать дополнительный флаг $KEY_WOW64_64KEY.
 

BoaConstrictor-FENIX

Новичок
Сообщения
11
Репутация
1
joiner, erlik
Спасибо, за советы, в дальнейшей разработке обязательно пригодятся, но прикол в том что Win 7 x86 стоит)
меня терзают смутные сомнения, что он не может найти константу $HKEY_LOCAL_MACHINE.
пытался найти WinAPIReg.au3 в инете, но ничего не нашел...
на всякий случай заново выкачал WinAPIEx_3.8_3380
отсюда -> http://autoit-script.ru/index.php?topic=47.0
не помогло...


Добавлено:
Сообщение автоматически объединено:

Обновил Autoit до 3.3.10.2 теперь не ругается на отсутствие константы, но в массиве попрежнему "1".
_RegEnumValues($hKey, $Hive) возвращает "Fasle".
 

erlik

Продвинутый
Сообщения
317
Репутация
84
BoaConstrictor-FENIX
Ты, наверно, удивишься, но у меня (на 3.3.8.1 win 7 x86) она оказывается тоже возвращает массив с 1. :scratch:
В общем нужно разбираться.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
3.3.10.2

Код:
#include <APIRegConstants.au3>
#include <Array.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIDiag.au3>
#include <WinAPIReg.au3>

Local $hKey = _WinAPI_RegOpenKey($HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', $KEY_READ)
If @error Then
    MsgBox(BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), @extended, _WinAPI_GetErrorMessage(@extended))
    Exit
EndIf
Local $Count = _WinAPI_RegQueryInfoKey($hKey)
Local $aKey[$Count[0]]
For $i = 0 To UBound($aKey) - 1
    $aKey[$i] = _WinAPI_RegEnumKey($hKey, $i)
Next

_WinAPI_RegCloseKey($hKey)

_ArrayDisplay($aKey, '_WinAPI_RegEnumKey')
 

BoaConstrictor-FENIX

Новичок
Сообщения
11
Репутация
1
erlik
Вообще не удивлюсь )

inververs
_RegEnumValues() - создает список всех разделов со своими переменными, их значениями и всеми подразделами любой вложенности для указанного раздела реестра. Другими словами, создает структуру раздела реестра.
Собственно этого хочется :smile:
Причем DWORD ключи должны переводиться в 10-чный вид...
 

erlik

Продвинутый
Сообщения
317
Репутация
84
BoaConstrictor-FENIX
DWORD ключи она переводит в 10-тичный вид. Проблема с невозвратом значений только в правах на чтение - если хоть одна ветка недоступна, то функция завершает работу.
Можешь проверить как она работает на любом мелком подразделе, где гарантировано есть все права на чтение.
 

BoaConstrictor-FENIX

Новичок
Сообщения
11
Репутация
1
erlik
благодарствую, сейчас буду тестить )
Еще кстати замечена тенденция, что "1" функция возвращает на настройках по умолчанию.
От балды выставил
_RegEnumValues($hKey, $Hive, 2,0,1,0 )
Вернул массив хоть с какими-то данными...
Пока что выводит только первый подраздел указанного раздела... фигня какая-то - :wall_brake:
 

erlik

Продвинутый
Сообщения
317
Репутация
84
По моему зря автор сделал прекращение возврата в случае ошибки доступа.
Я заменил в скрипте, в циклах
Код:
If @error Then 
       Return SetError(1, -1, 0)
EndIf

на
Код:
If @error Then ContinueLoop

И вернулся нормальный массив. Пусть там не все параметры и ветки, но это лучше чем ничего.
 

BoaConstrictor-FENIX

Новичок
Сообщения
11
Репутация
1
я просто удалил строки 125, 126, 127 )
Код:
If $Error Then
     ExitLoop
EndIf



и параметры выставил
_RegEnumValues($hKey, $Hive,-1,0,1)

в итоге получился рабочий вариант )

Код:
#Include <Array.au3>
#Include <Constants.au3>
#Include <WinAPIEx.au3>

Global $hKey, $Hive

$hKey = _WinAPI_RegOpenKey($HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion')
_RegEnumValues($hKey, $Hive, -1,0,1)
_WinAPI_RegCloseKey($hKey)

$Hive = StringSplit($Hive, ChrW(160))

_ArrayDisplay($Hive)

Func _RegEnumValues($hRoot, ByRef $sData, $iLevel = -1, $iLenght = 0, $iParam = 0, $sParam = 0)

    If (($iLevel > -1) And ($iParam > $iLevel)) Or (($iLenght) And (StringLen($sData) > $iLenght)) Then
        Return SetError(1, -1, 0)
    EndIf

    If Not $iParam Then
        $sData = ''
    EndIf

    $iParam += 1

    Local $hKey, $sKey, $aKey, $sVal, $aText, $sText, $Quotes, $Size, $Struct, $Type, $Sep = ChrW(160), $Error = 0
    Local $tData = DllStructCreate('byte[1048576]')
    Local $pData = DllStructGetPtr($tData)

    If $sParam Then
        $sData &= $sParam & '\' & $Sep
    EndIf
    $aKey = _WinAPI_RegQueryInfoKey($hRoot)
    If @error Then
        Return SetError(1, @extended, 0)
    EndIf
    For $i = 0 To $aKey[2] - 1
        $sVal = _WinAPI_RegEnumValue($hRoot, $i)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        $Size = _WinAPI_RegQueryValue($hRoot, $sVal, $tData)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        $Type = @extended
        If Not $sVal Then
            $sVal = '@'
        EndIf
        If Not $Size Then
            $sText = ''
        Else
            Switch $Type
                Case $REG_MULTI_SZ
                    $sText = ''
                    $aText = _WinAPI_StructToArray($pData)
                    If @error Then
                        Return SetError(1, -1, 0)
                    EndIf
                    For $j = 1 To $aText[0] - 1
                        $sText &= $aText[$j] & @LF
                    Next
                    If $aText[0] Then
                        $sText &= $aText[$aText[0]]
                    EndIf
                    $Quotes = 1
                Case Else
                    $Quotes = 0
                    Switch $Type
                        Case $REG_DWORD, $REG_DWORD_BIG_ENDIAN
                            $Struct = 'dword'
                        Case $REG_QWORD
                            $Struct = 'uint64'
                        Case $REG_SZ, $REG_EXPAND_SZ
                            $Struct = 'wchar[' & $Size & ']'
                            $Quotes = 1
                        Case Else
                            $Struct = 'byte[' & $Size & ']'
                    EndSwitch
                    $sText = DllStructGetData(DllStructCreate($Struct, $pData), 1)
                    If $Quotes Then
                        $sText = '"' & $sText & '"'
                    EndIf
            EndSwitch
        EndIf
        If $sParam Then
            $sData &= $sParam & '\\'
        EndIf
        $sData &= $sVal & '=(' & $Type & ')' & $sText & $Sep
    Next
    For $i = 0 To $aKey[0] - 1
        $sKey = _WinAPI_RegEnumKey($hRoot, $i)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        $hKey = _WinAPI_RegOpenKey($hRoot, $sKey, $KEY_READ)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        If $sParam Then
            _RegEnumValues($hKey, $sData, $iLevel, $iLenght, $iParam, $sParam & '\' & $sKey)
        Else
            _RegEnumValues($hKey, $sData, $iLevel, $iLenght, $iParam, $sKey)
        EndIf
        If @error Then
            $Error = @extended
            If Not $Error Then
                $Error = -1
            EndIf
        EndIf
        _WinAPI_RegCloseKey($hKey)

    Next
    If $iParam = 1 Then
        If Not $Error Then
            $sData = StringRegExpReplace($sData, $Sep & '*\Z', '')
        Else
            $sData = ''
        EndIf
    EndIf
    Return SetError($Error <> 0, $Error, $Error = 0)
EndFunc   ;==>_RegEnumValues


Хотя ощущение, что это не совсем правильно...


Добавлено:
Сообщение автоматически объединено:

Что делают параметры функции _RegEnumValues, кстати, до сих пор не понимаю...
 

erlik

Продвинутый
Сообщения
317
Репутация
84
В общем методом ненаучного тыка выяснил, что камень преткновения - строчка
Код:
$aText = _WinAPI_StructToArray($pData)

если после нее оставить вот так
Код:
If @error Then ContinueLoop

то остальные строчки можно оставлять как есть - все работает и возвращается полный массив всех данных. Я сравнивал буквально каждый параметр и похоже, что возврат идет полный. То есть не понятно, а есть ли вообще какие то проблемы с правами на доступ.
 

erlik

Продвинутый
Сообщения
317
Репутация
84
joiner
Он об аргументах, которые действительно автором никак не прокомментированы.
 

BoaConstrictor-FENIX

Новичок
Сообщения
11
Репутация
1
Действительно... когда $pData имеет значение вида 0x03CD0020
_WinAPI_StructToArray($pData) валится в ошибку...

Итог, мож пригодится кому...

Код:
#Include <Array.au3>
#Include <Constants.au3>
#Include <WinAPIEx.au3>

Global $hKey, $Hive
$hKey = _WinAPI_RegOpenKey($HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall')

_RegEnumValues($hKey, $Hive)
_WinAPI_RegCloseKey($hKey)

$Hive = StringSplit($Hive, ChrW(160))

_ArrayDisplay($Hive)


Func _RegEnumValues($hRoot, ByRef $sData, $iLevel = -1, $iLenght = 0, $iParam = 0, $sParam = 0)

    If (($iLevel > -1) And ($iParam > $iLevel)) Or (($iLenght) And (StringLen($sData) > $iLenght)) Then
        Return SetError(1, -1, 0)
    EndIf

    If Not $iParam Then
        $sData = ''
    EndIf

    $iParam += 1

    Local $hKey, $sKey, $aKey, $sVal, $aText, $sText, $Quotes, $Size, $Struct, $Type, $Sep = ChrW(160), $Error = 0
    Local $tData = DllStructCreate('byte[1048576]')
    Local $pData = DllStructGetPtr($tData)

    If $sParam Then
        $sData &= $sParam & '\' & $Sep
    EndIf
    $aKey = _WinAPI_RegQueryInfoKey($hRoot)
    If @error Then
        Return SetError(1, @extended, 0)
    EndIf
    For $i = 0 To $aKey[2] - 1
        $sVal = _WinAPI_RegEnumValue($hRoot, $i)
        If @error Then
			            Return SetError(1, @extended, 0)
        EndIf
        $Size = _WinAPI_RegQueryValue($hRoot, $sVal, $tData)
        If @error Then
			            Return SetError(1, @extended, 0)
        EndIf
        $Type = @extended
        If Not $sVal Then
            $sVal = '@'
        EndIf
        If Not $Size Then
            $sText = ''
        Else
            Switch $Type
                Case $REG_MULTI_SZ
                    $sText = ''
                    $aText = _WinAPI_StructToArray($pData)		
					If @error Then ContinueLoop
                    For $j = 1 To $aText[0] - 1
                        $sText &= $aText[$j] & @LF
                    Next
                    If $aText[0] Then
                        $sText &= $aText[$aText[0]]
                    EndIf
                    $Quotes = 1
                Case Else
                    $Quotes = 0
                    Switch $Type
                        Case $REG_DWORD, $REG_DWORD_BIG_ENDIAN
                            $Struct = 'dword'
                        Case $REG_QWORD
                            $Struct = 'uint64'
                        Case $REG_SZ, $REG_EXPAND_SZ
                            $Struct = 'wchar[' & $Size & ']'
                            $Quotes = 1
                        Case Else
                            $Struct = 'byte[' & $Size & ']'
                    EndSwitch
                    $sText = DllStructGetData(DllStructCreate($Struct, $pData), 1)
                    If $Quotes Then
                        $sText = '"' & $sText & '"'
                    EndIf
            EndSwitch
        EndIf
        If $sParam Then
            $sData &= $sParam & '\\'
        EndIf
        $sData &= $sVal & '=(' & $Type & ')' & $sText & $Sep
    Next
    For $i = 0 To $aKey[0] - 1
        $sKey = _WinAPI_RegEnumKey($hRoot, $i)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        $hKey = _WinAPI_RegOpenKey($hRoot, $sKey, $KEY_READ)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        If $sParam Then
            _RegEnumValues($hKey, $sData, $iLevel, $iLenght, $iParam, $sParam & '\' & $sKey)
        Else
            _RegEnumValues($hKey, $sData, $iLevel, $iLenght, $iParam, $sKey)
        EndIf
        If @error Then
            $Error = @extended
            If Not $Error Then
                $Error = -1
            EndIf
        EndIf
        _WinAPI_RegCloseKey($hKey)
        If $Error Then
						MsgBox(0,"",$Error)
            ExitLoop
        EndIf
    Next
    If $iParam = 1 Then
        If Not $Error Then
            $sData = StringRegExpReplace($sData, $Sep & '*\Z', '')
        Else
            $sData = ''
        EndIf
    EndIf
    Return SetError($Error <> 0, $Error, $Error = 0)
EndFunc   ;==>_RegEnumValues
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
BoaConstrictor-FENIX,
Попробуйте в функции _RegEnumValues() заменить строку
Код:
$aText = _WinAPI_StructToArray($pData)
на
Код:
$aText = _WinAPI_StructToArray($tData)
 

erlik

Продвинутый
Сообщения
317
Репутация
84
madmasles
Действительно, помогло. Теперь в массиве на 4 значения больше возвращается.
 
Верх