Автор Тема: Дополнительные функции для работы с реестром  (Прочитано 34614 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379
  • Репутация: 2695
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
На досуге написал пару функций для работы с реестром. Обе используют рекурсивные вызовы и требуют наличие библиотеки WinAPIEx.au3.

_RegEnumValues() - создает список всех разделов со своими переменными, их значениями и всеми подразделами любой вложенности для указанного раздела реестра. Другими словами, создает структуру раздела реестра. Функция возвращает строку, разделителем в которой является символ с кодом 160 (Unicode) - ChrW(160). Каждая запись в этой строке имеет следующий вид:

относительный путь к разделу\\параметр=(тип)значение

Если параметр имеет строковое значение, то добавляются кавычки:

относительный путь к разделу\\параметр=(тип)"значение"

Каждый раздел начинается с его пути и заканчивается символом "\":

относительный путь к разделу\

Пример для раздела "HKEY_CLASSES_ROOT\.txt":
@=(1)"txtfile"
PerceivedType=(1)"text"
Content Type=(1)"text/plain"
Mac Comment=(1)"ASCII File (SimpleText)"
Mac Type=(1)"TEXT"
Mac Creator=(1)"ttxt"
PersistentHandler\
PersistentHandler\\@=(1)"{5e941d80-bf96-11cd-b579-08002b30bfeb}"
ShellNew\
ShellNew\\NullFile=(1)""

Для чего это нужно? Ну во-первых, вы получаете сразу структуру всего раздела за относительно небольшое время. Во-вторых, это очень удобно для сравнения двух разделов реестра на идентичность.

Замечание. Если к какому-нибудь разделу реестра в пределах заданной ветки будет отказано в доступе на чтение, то функция завершится с ошибкой.

Код:
(нажмите для показа/скрытия)

_RegEnumTimes() - возвращает уникальный идентификатор, основанный на времени последней модификации указанного раздела реестра и всех его подразделов любой вложенности. Если вы измените что-нибудь в указанном разделе или в любом из его подразделов и т.д., то значение, возвращаемое этой функцией изменится. Эта функция на порядок быстрее _RegEnumValues(). Смысловой нагрузки значение идентификатора никакой не несет, важен лишь факт его изменения. Это очень удобно для отслеживания факта изменения раздела реестра.

Так же, как и в предыдущей функции, _RegEnumTimes() завершится с ошибкой при отказе в доступе на чтение к любому подразделу указанного раздела реестра.

Код:
(нажмите для показа/скрытия)

Жду отзывов.

:)
« Последнее редактирование: Октябрь 08, 2010, 11:45:36 от Yashied »


Думай, прежде чем говорить.

Русское сообщество AutoIt

Дополнительные функции для работы с реестром
« Отправлен: Сентябрь 08, 2010, 22:01:31 »

Оффлайн madmasles [?]

  • Глобальный модератор
  • *
  • Сообщений: 7790
  • Репутация: 2317
  • Пол: Мужской
  • Награды За модерирование форума
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #1, Отправлен: Сентябрь 08, 2010, 22:34:56 »
Yashied,
Спасибо! Очень полезные функции. _RegEnumValues() практически мгновенно сделала копию раздела. Я результат в файл записал - несколько не привычный формат записи, но это не страшно :). А с помощью _RegEnumTimes() можно, например раздел автозагрузки периодически проверять, что тоже очень полезно. ИМХО, обе функции надо в WinAPIEx.au3 добавлять.
 :IL_AutoIt_1::thumbs_up:

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379

  • Автор темы
  • Репутация: 2695
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #2, Отправлен: Сентябрь 08, 2010, 23:51:48 »
Спасибо! Очень полезные функции.

Пожалуйста.

:)

..несколько не привычный формат записи, но это не страшно.

Можно и в .reg формате сделать, но там будут длиннее строки, что отразится на скорости + не очень удобно будет анализировать записи ("dword" и т.д.), в случае построения дерева раздела. Записать раздел в файл можно и с помощью regedit.exe. Здесь у меня задача стояла именно в сравнении нескольких веток в HKEY_CLASSES_ROOT с целью их дальнейшего отсеивания.

...обе функции надо в WinAPIEx.au3 добавлять.

Нет, не буду. Это довольно специфические функции, а WinAPIEx и так уже раздулся почти до мегабайта.

Оффлайн assch [?]

  • Новичок
  • *
  • Сообщений: 166
  • Репутация: 4
    • Награды
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #3, Отправлен: Сентябрь 09, 2010, 01:09:25 »
Уважаемый Yashied

А если стоит задача сделать снимок всего реестра, потом что нибудь добавить и сделать второй снимок.
потом их сравнить и выявить изменения, и записать в файл.
Чтобы потом эти изменения можно было бы внести обратно (при их отсутствии)
например с помощью regedit.exe.
Как это делает Тотал юнистал.
Эти функции не помогут?
И вообще такой алгоритм  трудно сделать силами Autoit?


« Последнее редактирование: Сентябрь 09, 2010, 01:27:33 от assch »

Русское сообщество AutoIt

Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #3 Отправлен: Сентябрь 09, 2010, 01:09:25 »

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379

  • Автор темы
  • Репутация: 2695
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #4, Отправлен: Сентябрь 09, 2010, 01:37:24 »
А если стоит задача сделать снимок всего реестра, потом что нибудь добавить и сделать второй снимок.
потом их сравнить и выявить изменения, и записать в файл.
Чтобы потом эти изменения можно было бы внести обратно (при их отсутствии)
например с помощью regedit.exe.
Как это делает Тотал юнистал.
Эти функции не помогут?
И вообще такой алгоритм  трудно сделать силами Autoit?

Можно, но ждать, когда отработает функция придется вечность.

:)

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379

  • Автор темы
  • Репутация: 2695
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #5, Отправлен: Сентябрь 09, 2010, 04:21:43 »
Вот простая функция для экспорта раздела реестра в файл или в переменную при помощи regedit.exe.

Код: AutoIt [Выделить]
#Include <WinAPIEx.au3>

ConsoleWrite(_RegExport('HKCR\AutoIt3Script') & @CR)

Func _RegExport($sKey, $sFile = '')

    Local $PID, $Path, $Root, $Text, $Data = 0

    $Path = _WinAPI_PathSearchAndQualify('regedit.exe')
    If Not FileExists($Path) Then
        Return 0
    EndIf
    $Text = StringSplit($sKey, '\', 2)
    If IsArray($Text) Then
        $Text = $Text[0]
    Else
        $Text = $sKey
    EndIf
    Switch $Text
        Case 'HKEY_CLASSES_ROOT', 'HKEY_CURRENT_USER', 'HKEY_LOCAL_MACHINE', 'HKEY_USERS', 'HKEY_CURRENT_CONFIG'
            $Root = $Text
        Case 'HKCR'
            $Root = 'HKEY_CLASSES_ROOT'
        Case 'HKCU'
            $Root = 'HKEY_CURRENT_USER'
        Case 'HKLM'
            $Root = 'HKEY_LOCAL_MACHINE'
        Case 'HKU'
            $Root = 'HKEY_USERS'
        Case 'HKCC'
            $Root = 'HKEY_CURRENT_CONFIG'
        Case Else
            Return 0
    EndSwitch
    $sFile = StringStripWS($sFile, 3)
    If Not $sFile Then
        Do
            For $i = 1 To 4
                $sFile &= Chr(Random(97, 122, 1))
            Next
            $sFile = StringRegExpReplace(@TempDir & '\~reg' & $sFile & '.tmp', '\\+', '\\')
        Until Not FileExists($sFile)
        $Data = 1
    Else
        If (FileExists($sFile)) And (Not FileDelete($sFile)) Then
            Return 0
        EndIf
    EndIf
    $PID = Run($Path & ' /e /s "' & $sFile & '" "' & StringReplace($sKey, $Text, $Root, 1) & '"')
    If @error Then
        Return 0
    EndIf
    ProcessWaitClose($PID)
    If Not $Data Then
        $Data = FileExists($sFile)
    Else
        $Data = StringRegExpReplace(FileRead($sFile), '\A[^[]*|' & '[' & @LF & ',' & @CR & ']*\Z', '')
        FileDelete($sFile)
        If Not $Data Then
            $Data = 0
        EndIf
    EndIf
    Return $Data
EndFunc   ;==>_RegExport

« Последнее редактирование: Сентябрь 10, 2010, 00:20:22 от Yashied »

Оффлайн assch [?]

  • Новичок
  • *
  • Сообщений: 166
  • Репутация: 4
    • Награды
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #6, Отправлен: Сентябрь 09, 2010, 22:56:39 »
Уважаемый Yashied

При запуске этой функции Func _RegExport($sKey, $sFile = '') в консоле выводится просто '0'
Честно говоря не могу разобраться (вы уж извините)
Подскажете пожалуйста как именно с помощью этой функции
скопировать например весь раздел реестра HKEY_CURRENT_USER
и записать всё это  например в 1.txt

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379

  • Автор темы
  • Репутация: 2695
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #7, Отправлен: Сентябрь 10, 2010, 00:25:28 »
Эх, я почему-то думал, что в FileExists() не обязательно нужно передавать полный путь. Это моя ошибка, поправил функцию.

Код: AutoIt [Выделить]
_RegExport('HKCU', '1.txt')


Русское сообщество AutoIt

Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #7 Отправлен: Сентябрь 10, 2010, 00:25:28 »

Оффлайн assch [?]

  • Новичок
  • *
  • Сообщений: 166
  • Репутация: 4
    • Награды
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #8, Отправлен: Сентябрь 10, 2010, 01:37:34 »
Yashied  [?]
Цитировать
_RegEnumTimes() - возвращает уникальный идентификатор, основанный на времени последней модификации указанного раздела реестра и всех его подразделов любой вложенности. Если вы измените что-нибудь в указанном разделе или в любом из его подразделов и т.д., то значение, возвращаемое этой функцией изменится. Эта функция на порядок быстрее _RegEnumValues(). Смысловой нагрузки значение идентификатора никакой не несет, важен лишь факт его изменения. Это очень удобно для отслеживания факта изменения раздела реестра.

Если задействовать этот  идентификатор то с помощью какой конструкции можно отследить и записать последние изменения например в ветки - HKCR
« Последнее редактирование: Сентябрь 10, 2010, 02:40:43 от Yashied »

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379

  • Автор темы
  • Репутация: 2695
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #9, Отправлен: Сентябрь 10, 2010, 02:27:22 »
assch, я не понял вопроса.

:wacko:

Идентификатор предназначен только для сравнения его с полученным ранее идентификатором. Если они различаются, то это однозначно свидетельствует о том, что в данной ветки что-то изменилось. Достаточно удалить один параметр и создать на его месте точно такой же, чтобы идентификатор изменился, несмотря на то, что структура раздела осталась прежней. Для отслеживания непосредственно изменений корневых разделов целиком (HKCR, HKCU и т.д.), лучше использовать _RegExport() в переменную и затем парсить эти данные (задача не из простых).

Не нужно выделять и раскрашивать текст, я все прекрасно вижу.
« Последнее редактирование: Сентябрь 10, 2010, 02:45:00 от Yashied »

Оффлайн assch [?]

  • Новичок
  • *
  • Сообщений: 166
  • Репутация: 4
    • Награды
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #10, Отправлен: Сентябрь 10, 2010, 13:08:46 »
И ещё не подскажете почему если снять снимок ветки например - HKLM
то файл у меня получился весом 33.6 мб
А когда я снимаю снимок этой же ветки функцией из библиотеки ''Registry_UDFs.au3"
Которую я помню давно скачал с сайта CreatLab
то файл у меня получается 23.1 мб
Не подскажете почему?


Оффлайн assch [?]

  • Новичок
  • *
  • Сообщений: 166
  • Репутация: 4
    • Награды
Re: _RegEnumTimes() и _RegEnumValues() - работа с реестром
« Ответ #11, Отправлен: Сентябрь 10, 2010, 14:11:49 »
Я могу только догадыватся что парсить  данные из двух файлов
а потом записать результат изменений это не просто.
Интересно какими алгоритмами хотя бы примерно работают
программы подобной тематики.
например  Тотал юнистал для сравнения тратит не больше 5 секунд
и после сравнения у него можно взять регфайл установки и удаления.
Просто я как и все надеюсь что мир не без добрых людей
кто нибудь что нибудь и подскажет.
В разделе для новичков я открыл тему
 "Как можно выявить изменения произошедшие на локальном диске"
Не без помощи других уже есть начало этой темы.
в частности две функции одна снимает снимок файловой системы (как правило диск С)
а другая ищет изменения, правда уходит на это около 2 минут.
Интересно что если сделать Батник - fc 1.txt 2.txt >> Inf.txt
то результат выведиться в файл  Inf.txt за долю секунды.
Но для больших сравнений она не подходит.
Она без труда (доля секунды) пропарсит два файла размером скажем около 2 мб каждый
но результат выведит в файл не больше 64 кб, то есть если произошли большие изменения
то она покажет соответственно обрезанную информацию.
Я интересовался почему и мне сказали что это функция из досовского наследия поэтому 64кб и всё.
А жалко очень быстрая функция.
Хотя для сравнения эти функции наверно не подойдут так как у регфайлов своеобразный
 стиль написания, если только как нибудь смодифицировать функцию.
Ну ладно, сами понимаете Попытка не пытка будем искать.
Буду признателен любой информации.
 


« Последнее редактирование: Сентябрь 10, 2010, 16:37:19 от assch »

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379

  • Автор темы
  • Репутация: 2695
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Написал функцию _RegExportEx() для экспорта данных из реестра в переменную или файл в формате .reg. В отличии от _RegExport(), эта функция не использует ни regedit.exe, ни каких-либо временных файлов. IMHO для AutoIt, это самое быстрое, что только можно было придумать (если у кого-нибудь получится быстрее, пожалуйста поделитесь здесь). Файлы размером в несколько тысяч строк создает почти мгновенно. Для файлов, количество строк в которых измеряется десятками тысяч, возможно будет целесообразнее использовать _RegExport(). Например на экспорт раздела "HKEY_CLASSES_ROOT\CLSID" (> 72000) у меня ушло ~10 секунд, _RegExport() справляется за 2-3 секунды. Но если необходимо экспортировать кучу отдельных веток реестра (с последующим их объединением), то тут _RegExportEx() вне конкуренции.

Код: AutoIt [Выделить]
#Include <Constants.au3>
#Include <WinAPIEx.au3>

$sReg = _RegExportEx('HKEY_CLASSES_ROOT\AutoIt3Script')
If @error Then
    ConsoleWrite(_WinAPI_GetErrorMessage(@extended) & @CR)
Else
    ConsoleWrite($sReg & @CR)
EndIf

Func _RegExportEx($sKey, $sFile = '', $fAssurance = 0)

    Local $aData = StringSplit(StringUpper($sKey), '\', 2)
    Local $tData, $hRoot, $sRoot, $sReg = ''
    Local $Error = 1

    If Not IsArray($aData) Then
        Return SetError(1, 0, '')
    EndIf

    Switch $aData[0]
        Case 'HKEY_CLASSES_ROOT', 'HKEY_CURRENT_USER', 'HKEY_LOCAL_MACHINE', 'HKEY_USERS', 'HKEY_CURRENT_CONFIG'
            $sRoot = $aData[0]
        Case 'HKCR'
            $sRoot = 'HKEY_CLASSES_ROOT'
        Case 'HKCU'
            $sRoot = 'HKEY_CURRENT_USER'
        Case 'HKLM'
            $sRoot = 'HKEY_LOCAL_MACHINE'
        Case 'HKU'
            $sRoot = 'HKEY_USERS'
        Case 'HKCC'
            $sRoot = 'HKEY_CURRENT_CONFIG'
        Case Else
            Return SetError(1, 0, '')
    EndSwitch
    $sKey = StringTrimLeft($sKey, StringLen($aData[0]) + 1)
    Do
        $hRoot = _WinAPI_RegOpenKey(Eval($sRoot), $sKey, BitOR($KEY_ENUMERATE_SUB_KEYS, $KEY_QUERY_VALUE))
        If @error Then
            ExitLoop
        EndIf
        $tData = DllStructCreate('byte[1048576]')
        If Not _RegEnumProc($hRoot, StringRegExpReplace($sRoot & '\' & $sKey, '\\*\Z', ''), $fAssurance, $sReg, $tData) Then
            ExitLoop
        EndIf
        $Error = 0
    Until 1
    If $Error Then
        Switch @extended
            Case 0
                $Error = -1
            Case Else
                $Error = @extended
        EndSwitch
    EndIf
    If $hRoot Then
        _WinAPI_RegCloseKey($hRoot)
    EndIf
    If $Error Then
        Return SetError(2, $Error, '')
    EndIf
    If $sFile Then
        $hFile = FileOpen($sFile, 2 + 32)
        If $hFile = -1 Then
            Return SetError(3, 0, '')
        EndIf
        If Not FileWrite($hFile, 'Windows Registry Editor Version 5.00' & @CRLF & @CRLF & $sReg) Then
            $Error = 1
        EndIf
        FileClose($hFile)
        If $Error Then
            Return SetError(3, 0, '')
        EndIf
        Return 1
    EndIf
    Return $sReg
EndFunc   ;==>_RegExportEx

Func _RegEnumProc($hRoot, $sRoot, $fAssurance, ByRef $sData, ByRef $tData, $sParam = 0)

    Local $hKey, $sKey, $sVal, $Pos, $Size, $Type
    Local $pData = DllStructGetPtr($tData)
    Local $Count = 0, $Error = 0

    If $sParam Then
        $sData &= @CRLF & '[' & $sRoot & '\' & $sParam & ']' & @CRLF
    Else
        $sData = '[' & $sRoot & ']' & @CRLF
    EndIf
    While 1
        $sVal = _WinAPI_RegEnumValue($hRoot, $Count)
        If @error Then
            Switch @extended
                Case 259 ; ERROR_NO_MORE_ITEMS
                    ExitLoop
                Case Else
                    Return SetError(1, @extended, 0)
            EndSwitch
        EndIf
        $Size = _WinAPI_RegQueryValue($hRoot, $sVal, $tData)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        $Type = @extended
        If $sVal Then
            $sVal = '"' & StringReplace(StringReplace($sVal, '\', '\\'), '"', '\"') & '"='
        Else
            $sVal = '@='
        EndIf
        If Not $Size Then
            Switch $Type
                Case 1 ; REG_SZ
                    $sVal &= '""'
                Case Else
                    Switch $Type
                        Case 3 ; REG_BINARY
                            $sVal &= 'hex:'
                        Case Else
                            $sVal &= 'hex(' & StringLower(Hex($Type, 1)) & '):'
                    EndSwitch
            EndSwitch
        Else
            Switch $Type
                Case 1 ; REG_SZ
                    $sVal &= '"' & StringReplace(StringReplace(DllStructGetData(DllStructCreate('wchar[' & $Size & ']', $pData), 1), '\', '\\'), '"', '\"') & '"'
                Case 4 ; REG_DWORD
                    $sVal &= 'dword:' & StringLower(Hex(Number(DllStructGetData(DllStructCreate('dword', $pData), 1))))
                Case Else
                    Switch $Type
                        Case 3 ; REG_BINARY
                            $sVal &= 'hex:'
                        Case Else
                            $sVal &= 'hex(' & StringLower(Hex($Type, 1)) & '):'
                    EndSwitch
                    $sVal &= StringTrimRight(StringRegExpReplace(StringLower(StringTrimLeft(DllStructGetData(DllStructCreate('byte[' & $Size & ']', $pData), 1), 2)), '(.{2})', '\1,'), 1)
                    $Pos = StringInStr($sVal, ',', 0, 1, 77)
                    If $Pos Then
                        $sVal = StringLeft($sVal, $Pos) & '\' & @CRLF & '  ' & StringRegExpReplace(StringTrimLeft($sVal, $Pos), '(.{75})', '\1\\' & @CRLF & '  ')
                    EndIf
            EndSwitch
        EndIf
        $sData &= $sVal & @CRLF
        $Count += 1
    WEnd
    $Count = 0
    While 1
        $sKey = _WinAPI_RegEnumKey($hRoot, $Count)
        If @error Then
            Switch @extended
                Case 259 ; ERROR_NO_MORE_ITEMS
                    ExitLoop
                Case Else
                    Return SetError(1, @extended, 0)
            EndSwitch
        EndIf
        $hKey = _WinAPI_RegOpenKey($hRoot, $sKey, BitOR($KEY_ENUMERATE_SUB_KEYS, $KEY_QUERY_VALUE))
        If @error Then
            If $fAssurance Then
                Return SetError(1, @extended, 0)
            EndIf
        Else
            If $sParam Then
                _RegEnumProc($hKey, $sRoot, $fAssurance, $sData, $tData, $sParam & '\' & $sKey)
            Else
                _RegEnumProc($hKey, $sRoot, $fAssurance, $sData, $tData, $sKey)
            EndIf
            If @error Then
                Switch @extended
                    Case 0
                        $Error = -1
                    Case Else
                        $Error = @extended
                EndSwitch
            EndIf
        EndIf
        If $hKey Then
            _WinAPI_RegCloseKey($hKey)
        EndIf
        $Count += 1
        If $Error Then
            ExitLoop
        EndIf
    WEnd
    If $Error Then
        Return SetError(1, $Error, 0)
    Else
        Return 1
    EndIf
EndFunc   ;==>_RegEnumProc

« Последнее редактирование: Октябрь 08, 2010, 15:36:58 от Yashied »

Оффлайн assch [?]

  • Новичок
  • *
  • Сообщений: 166
  • Репутация: 4
    • Награды
Отличная функция  Yashied 
Я занимаюсь темой выявления изменений в реестре Пока работаю по такому алгоритму:
Снимаю снимок ключей (одних ключей без их значений) скажем ветки HKEY_CLASSES_ROOT функцией:
Код: AutoIt [Выделить]
#Include <File.au3>
#include <Array.au3>

Global $Array
Global $key = "HKEY_CLASSES_ROOT"
Global $p = 0
_KeyList($key)

FileWrite("1.txt", $Array)
FileClose("1.txt")

Func _KeyList($key)
$i = 1
While 1
$var = RegEnumKey($key, $i)
If @error <> 0 then ExitLoop
$Array &= $key&"\"&$var & @CRLF
If $i = 1 then  
$p += 1
EndIf
$i = $i + 1
_KeyList($key&"\"&$var)            
WEnd  
EndFunc

Вроде бы простенькая функция ничего лишнего но она затрачивает на это 58 секунд.
Потом второй снимок, потом сравнение ну и соответственно из получившегося списка
добавленых ключей делаю Регфайл. (ваша функция для этого подойдёт наверное просто идеально)
Но интересная деталь - Если вашей функцией сделать снимок ветки HKEY_CLASSES_ROOT
а ваша функция помимо всех ключей ещё и значения к ним добавляет то у меня ушло на это всего 26 секунд.
Выходит ваша функция даже с большим объёмом работает быстрее чем та.
Интересно что нужно подправить в вашей функции чтобы применить её к моему первому этапу
снятия снимка только одних ключей этой ветки, ведь если на всю информацию с ключами и значениями
она затрачивает 26 секунд то по логики на информацию только одних ключей она должна затратить ещё меньше. 

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379

  • Автор темы
  • Репутация: 2695
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Интересно что нужно подправить в вашей функции чтобы применить её к моему первому этапу...

Просто закомментировать часть кода. Получится в ~2 раза быстрее.

Код: AutoIt [Выделить]
#Include <Constants.au3>
#Include <WinAPIEx.au3>

$sReg = _RegExportEx('HKEY_CLASSES_ROOT', 'r.reg')
If @error Then
    ConsoleWrite(_WinAPI_GetErrorMessage(@extended) & @CR)
Else
;    ConsoleWrite($sReg & @CR)
EndIf

Func _RegExportEx($sKey, $sFile = '', $fAssurance = 0)

    Local $aData = StringSplit(StringUpper($sKey), '\', 2)
    Local $tData, $hRoot, $sRoot, $sReg = ''
    Local $Error = 1

    If Not IsArray($aData) Then
        Return SetError(1, 0, '')
    EndIf

    Switch $aData[0]
        Case 'HKEY_CLASSES_ROOT', 'HKEY_CURRENT_USER', 'HKEY_LOCAL_MACHINE', 'HKEY_USERS', 'HKEY_CURRENT_CONFIG'
            $sRoot = $aData[0]
        Case 'HKCR'
            $sRoot = 'HKEY_CLASSES_ROOT'
        Case 'HKCU'
            $sRoot = 'HKEY_CURRENT_USER'
        Case 'HKLM'
            $sRoot = 'HKEY_LOCAL_MACHINE'
        Case 'HKU'
            $sRoot = 'HKEY_USERS'
        Case 'HKCC'
            $sRoot = 'HKEY_CURRENT_CONFIG'
        Case Else
            Return SetError(1, 0, '')
    EndSwitch
    $sKey = StringTrimLeft($sKey, StringLen($aData[0]) + 1)
    Do
        $hRoot = _WinAPI_RegOpenKey(Eval($sRoot), $sKey, BitOR($KEY_ENUMERATE_SUB_KEYS, $KEY_QUERY_VALUE))
        If @error Then
            ExitLoop
        EndIf
        $tData = DllStructCreate('byte[1048576]')
        If Not _RegEnumProc($hRoot, StringRegExpReplace($sRoot & '\' & $sKey, '\\*\Z', ''), $fAssurance, $sReg, $tData) Then
            ExitLoop
        EndIf
        $Error = 0
    Until 1
    If $Error Then
        Switch @extended
            Case 0
                $Error = -1
            Case Else
                $Error = @extended
        EndSwitch
    EndIf
    If $hRoot Then
        _WinAPI_RegCloseKey($hRoot)
    EndIf
    If $Error Then
        Return SetError(2, $Error, '')
    EndIf
    If $sFile Then
        $hFile = FileOpen($sFile, 2 + 32)
        If $hFile = -1 Then
            Return SetError(3, 0, '')
        EndIf
        If Not FileWrite($hFile, 'Windows Registry Editor Version 5.00' & @CRLF & @CRLF & $sReg) Then
            $Error = 1
        EndIf
        FileClose($hFile)
        If $Error Then
            Return SetError(3, 0, '')
        EndIf
        Return 1
    EndIf
    Return $sReg
EndFunc   ;==>_RegExportEx

Func _RegEnumProc($hRoot, $sRoot, $fAssurance, ByRef $sData, ByRef $tData, $sParam = 0)

    Local $hKey, $sKey, $sVal, $Pos, $Size, $Type
    Local $pData = DllStructGetPtr($tData)
    Local $Count = 0, $Error = 0

    If $sParam Then
        $sData &= @CRLF & '[' & $sRoot & '\' & $sParam & ']' & @CRLF
    Else
        $sData = '[' & $sRoot & ']' & @CRLF
    EndIf

#cs

    While 1
        $sVal = _WinAPI_RegEnumValue($hRoot, $Count)
        If @error Then
            Switch @extended
                Case 259 ; ERROR_NO_MORE_ITEMS
                    ExitLoop
                Case Else
                    Return SetError(1, @extended, 0)
            EndSwitch
        EndIf
        $Size = _WinAPI_RegQueryValue($hRoot, $sVal, $tData)
        If @error Then
            Return SetError(1, @extended, 0)
        EndIf
        $Type = @extended
        If $sVal Then
            $sVal = '"' & StringReplace(StringReplace($sVal, '\', '\\'), '"', '\"') & '"='
        Else
            $sVal = '@='
        EndIf
        If Not $Size Then
            Switch $Type
                Case 1 ; REG_SZ
                    $sVal &= '""'
                Case Else
                    Switch $Type
                        Case 3 ; REG_BINARY
                            $sVal &= 'hex:'
                        Case Else
                            $sVal &= 'hex(' & StringLower(Hex($Type, 1)) & '):'
                    EndSwitch
            EndSwitch
        Else
            Switch $Type
                Case 1 ; REG_SZ
                    $sVal &= '"' & StringReplace(StringReplace(DllStructGetData(DllStructCreate('wchar[' & $Size & ']', $pData), 1), '\', '\\'), '"', '\"') & '"'
                Case 4 ; REG_DWORD
                    $sVal &= 'dword:' & StringLower(Hex(Number(DllStructGetData(DllStructCreate('dword', $pData), 1))))
                Case Else
                    Switch $Type
                        Case 3 ; REG_BINARY
                            $sVal &= 'hex:'
                        Case Else
                            $sVal &= 'hex(' & StringLower(Hex($Type, 1)) & '):'
                    EndSwitch
                    $sVal &= StringTrimRight(StringRegExpReplace(StringLower(StringTrimLeft(DllStructGetData(DllStructCreate('byte[' & $Size & ']', $pData), 1), 2)), '(.{2})', '\1,'), 1)
                    $Pos = StringInStr($sVal, ',', 0, 1, 77)
                    If $Pos Then
                        $sVal = StringLeft($sVal, $Pos) & '\' & @CRLF & '  ' & StringRegExpReplace(StringTrimLeft($sVal, $Pos), '(.{75})', '\1\\' & @CRLF & '  ')
                    EndIf
            EndSwitch
        EndIf
        $sData &= $sVal & @CRLF
        $Count += 1
    WEnd
    $Count = 0

#ce


    While 1
        $sKey = _WinAPI_RegEnumKey($hRoot, $Count)
        If @error Then
            Switch @extended
                Case 259 ; ERROR_NO_MORE_ITEMS
                    ExitLoop
                Case Else
                    Return SetError(1, @extended, 0)
            EndSwitch
        EndIf
        $hKey = _WinAPI_RegOpenKey($hRoot, $sKey, BitOR($KEY_ENUMERATE_SUB_KEYS, $KEY_QUERY_VALUE))
        If @error Then
            If $fAssurance Then
                Return SetError(1, @extended, 0)
            EndIf
        Else
            If $sParam Then
                _RegEnumProc($hKey, $sRoot, $fAssurance, $sData, $tData, $sParam & '\' & $sKey)
            Else
                _RegEnumProc($hKey, $sRoot, $fAssurance, $sData, $tData, $sKey)
            EndIf
            If @error Then
                Switch @extended
                    Case 0
                        $Error = -1
                    Case Else
                        $Error = @extended
                EndSwitch
            EndIf
        EndIf
        If $hKey Then
            _WinAPI_RegCloseKey($hKey)
        EndIf
        $Count += 1
        If $Error Then
            ExitLoop
        EndIf
    WEnd
    If $Error Then
        Return SetError(1, $Error, 0)
    Else
        Return 1
    EndIf
EndFunc   ;==>_RegEnumProc


Русское сообщество AutoIt

Re: Дополнительные функции для работы с реестром
« Ответ #14 Отправлен: Октябрь 08, 2010, 15:40:31 »

 

Похожие темы

  Тема / Автор Ответов Последний ответ
16 Ответов
12787 Просмотров
Последний ответ Май 24, 2015, 00:16:05
от WSWR
5 Ответов
5481 Просмотров
Последний ответ Апрель 27, 2011, 15:15:41
от anonymous7
14 Ответов
9710 Просмотров
Последний ответ Март 21, 2011, 20:06:47
от Kalisnik
9 Ответов
5353 Просмотров
Последний ответ Март 09, 2011, 00:48:18
от JimmyN
6 Ответов
3396 Просмотров
Последний ответ Апрель 01, 2012, 13:29:22
от Garrett
0 Ответов
1837 Просмотров
Последний ответ Апрель 01, 2012, 00:16:10
от CreatoR
14 Ответов
13375 Просмотров
Последний ответ Март 21, 2014, 22:32:34
от Garrett
2 Ответов
3645 Просмотров
Последний ответ Сентябрь 27, 2013, 09:23:06
от black1
1 Ответов
1024 Просмотров
Последний ответ Ноябрь 08, 2014, 21:52:13
от winstan
10 Ответов
2690 Просмотров
Последний ответ Декабрь 22, 2016, 10:03:04
от chaos-13