Что нового

_WinAPI_RegSaveKey& _WinAPI_RegRestoreKey - дает синий экран после reboot

saavaage

Знающий
Сообщения
171
Репутация
17
Суть проблемы: необходимо провести сохранение ветки HCR перед работой с реестром с возможностью последующего восстановления (на всякий пожарный случай).
Применил следующий код:
Код:
Func _SaveRegNew() ; бэкап ветки реестра
     $hKey = _WinAPI_RegOpenKey($HKEY_CLASSES_ROOT, '')
   _WinAPI_RegSaveKey($hKey, @HomeDrive & '\hcr.reg')
   _WinAPI_RegCloseKey($hKey)
   MsgBox(0, '', '"Ветка HKEY_CLASSES_ROOT успешна сохранена в hcr.reg', 3)
EndFunc

Func _RestoreRegNew() ; восстановление из бэкапа ветки реестра
	$hKey = _WinAPI_RegCreateKey($HKEY_CLASSES_ROOT, '')
    _WinAPI_RegRestoreKey($hKey, @HomeDrive & '\hcr.reg')
 _WinAPI_RegCloseKey($hKey)
	MsgBox(0, '', '"Ветка HKEY_CLASSES_ROOT успешно восстановлена из hcr.reg".', 3)
EndFunc


Итог - после перезагрузки системы выскакивает синий экран смерти с указанием на Registry Error.

PS WinXp SP3, библиотека WinApiEx версия 2.7, в системе установлен тяжелый софт (Photoshop, Lingvo, прочее)



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

Применение другого скрипта для экспорта ветки HCR (от того же Yashied), после запуска полученного reg-файла приводит к появлению окна -уведомления (см. аттач), но синего экрана после ребута уже нет.
Такое ощущение, что требуется перед сохранением/восстановлением давать полный доступ к ветке (с рекурсией) на запись...

Код 2-ого скрипта:

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

$sReg = _RegExportEx('HKEY_CLASSES_ROOT', 'hcr.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
    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
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Хех, ну да, вы ребята попробуйте запустите этот код, а потом напишите, у вас тоже синий экран или нет?

[box title=ВНИМАНИЕ]НЕ ЗАПУСКАТЬ ПЕРВЫЙ ПРИМЕР ИЗ ПРЕДЫДУЩЕГО ПОСТА!!![/box]

Эти функции не предназначены для сохранения целых кустов. _WinAPI_RegSaveKey() не сохраняет ключи, которые были созданы с параметром REG_OPTION_VOLATILE. И кроме того, в отличии от regedit.exe, функция _WinAPI_RegRestoreKey() не добавляет информацию из файла, а полностью очищает указанный ключ и затем уже записывает туда все данные из файла. Таким образом, если какие-либо ключи не были записаны в hcr.reg (кстати, здесь не .reg формат), то при восстановлении, они будут удалены из реестра.

В твоем случае лучше использовать regedit.exe или _RegExport() (без "Ex").

P.S

А еще необходимо проверять ошибки. Что у тебя показывает следующий код?

Код:
#Include <WinAPIEx.au3>

$hKey  = _WinAPI_RegOpenKey($HKEY_CLASSES_ROOT, '')
_WinAPI_RegSaveKey($hKey, 'reg.dat')
If @error Then
	MsgBox(0, '', 'Error: ' & @extended)
Else
	MsgBox(0, '', 'OK')
EndIf
_WinAPI_RegCloseKey($hKey)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Тогда при восстановлении нужно давать права на запись всем разделам HKCR и их подразделам и т.д., а затем восстанавливать их (права) в изначальное состояние. Это нетривиальная задача. Используй лучше RegExport(). А еще лучше Acronis True Image.
 
Автор
S

saavaage

Знающий
Сообщения
171
Репутация
17
Yashied, насколько для этих целей подойдет Восстановление Системы: создание точки восстановления и затем, в случае краха, восстановление из нее? Это надежно в плане манипуляций с реестром?

PS Вот и код для подобной манипуляции (создание точки восстановления системы):

Код:
Run(@COMSPEC & ' /c WMIC /Namespace:\\root\default Path SystemRestore Call CreateRestorePoint "Restore_Point_SmartXP", 100, 12', '', @SW_HIDE)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
ХА! Я только что запустил твой код и перезагрузил систему. Как видишь, все OK, т.к. я пишу это сообщение.

;D

Правда у меня Windows 7 x86.

saavaage сказал(а):
Вот и код для подобной манипуляции (создание точки восстановления системы)...

Можно и так, но я этому не доверяю. IMHO самый надежный способ - Acronis True Image.
 
Автор
S

saavaage

Знающий
Сообщения
171
Репутация
17
Yashied, не совсем понял последнее сообщение. Т.е. сначала создал точку восстановления, потом запустил глючный код (из шапки) и все нормально откатилось? или как? :wacko:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Запустил _WinAPI_RegSaveKey(), сделал небольшие изменения (для проверки), а затем запустил _WinAPI_RegRestoreKey(). Все изменения были восстановлены в исходное состояние, и после перезагрузки компьютера у меня ничего не повисло, и не было никаких BSOD'ов.
 
Автор
S

saavaage

Знающий
Сообщения
171
Репутация
17
Мда... У меня тоже раз-на-раз не приходится (иногда в вирталке крах .иногда на реальной... уже таким образом 3 раза переустанавливал XP... эдак, прийдется опять ставить acronis и лепить образы) . Вообщем, подключу для таких случаев Восстановление, а для отдельных ключей (не групповых) буду пользовать связку твоих функций (WinApiEx) + regperm.

Тему, думаю, можно закрывать

Thanks a lot!
 
Верх