Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   Регфайл, синтаксис. (http://forum.oszone.net/showthread.php?t=143253)

semiono 22-06-2009 20:17 1149226

Регфайл, синтаксис.
 
Думаю пора обсудить написание валидных регфайлов средствами AutoIt3.
Хочется объединить всё вместе, как некое знание и рассмотреть все встречающиеся особенности записи различных типов параметров.

Сразу же хочеться отметить различие реестров x86 и x64, и в то же время рег синтакс исключающий записи вида HKLM/HKCU и т.п.

Здесь могут быть полезными выключатели
Код:

Switch @OSArch
    Case 'x86'
        $sRegKey = 'HKLM\Software\RegKey'
    Case 'x64'
        $sRegKey = 'HKLM\Software\Wow6432Node\RegKey'
EndSwitch

Запись в файл может определяться переменной как

Код:

$sFileContent = _
    'Windows Registry Editor Version 5.00' & @CRLF & @CRLF & _
    '[' & $sRegKey & ']' & @CRLF & _
    '"ValueName"=' & $sSerialResult & & @CRLF & @CRLF

Но при этом нельзя забывать, что имя куста должно быть полное, например $sRegKey = "HKEY_LOCAL_MACHINE\...", здесь нельзя использовать HKLM\

Однако, большую сложность думаю представляет запись значений параметров в валидном виде для регфалов!

Например, все типы кроме REG_SZ и REG_DWORD имеют запись вида = hex(2):
Причём, понятно что REG_EXPAND_SZ содержит юникод, экспортирующийся в виде шеснадцетиричного кода разделённого запятыми в регфайл. Закрывается строка нуевым символом, то-есть двумя байтами нулей ',00,00' (впрочем это так же актуально и для multisz и для binary)
Несмотря на то, что строки могут быть размещены без переносов, и это работает, однако майкрософт придумала способ записи разделяемой слеш, для переноса строки. Это красиво и хотелось бы тоже этому следовать.

Длина строк в такой записи содержит 25 байт разделённых запятыми, строки начинается с двух пробелов и заканчивается слеш, если нужен перенос
Код:

  61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,\
Однако первая строка имеет не постоянную длину относительно имени переменной.
Минимальная строка содержит 22 байта разделённых запятыми, и начинает убавляться на один байт при увеличении длины имени переменной на 4 символа.
Код:

"1"=hex(2):61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,\
"12"=hex(2):61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,\
"123"=hex(2):61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,\
"1234"=hex(2):61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,00,61,\ < строка стала короче

Тоже самое по поводу dword, запись имеет свою особенность.
"zzz"=dword:0001e240

И другие (zero-lenth-binary-value)
"value1"=hex(0):

У меня просьба, сделайте свои предложения по поводу кода autoit, и быть может это соберёться в некий включаемый файлик?

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

Ещё проще вопрос, как записать запятую через каждые два символа, заранее неизвестной строки...
aa,bb,ab,ac,....

FlatX007 23-06-2009 09:44 1149548

Простите а зачем это нужно ???

proxy 23-06-2009 10:23 1149582

FlatX007, а дело в том, что вот такая ситуация:

Задача: необходимо создать файл типа .reg, который будет записывать (или обновлять) данные в реестре велечины типа REG_EXPAND_SZ.
В реестре это будет выглядеть так:

Цитата:

Имя величины: SN
Значение величины: VMKJGNDIDNWLDMKJGNDIDNWLD
Тип величины: REG_EXPAND_SZ

А вот в .reg файле это будет выглядеть так:
Цитата:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\DashSignature\Knagalis]
"SN"=hex(2):56,00,4d,00,4b,00,4a,00,47,00,4e,00,44,00,49,00,44,00,4e,00,57,00,4c,00,44,00,4d,00,4b,0 0,4a,00,47,00,4e,00,44,00,49,00,44,00,4e,00,57,00,4c,00,44,00,00,00

Дело в том, что значения в .reg файле записываются следующим образом:
Цитата:

REG_NONE - hex(0)
REG_BINARY - hex(3) или hex
REG_DWORD - hex(4) или dword
REG_SZ - hex(1) или отсутствие указателя типа
REG_EXPAND_SZ - hex(2)
REG_MULTI_SZ - hex(7)
REG_RESOURCE_LIST - hex(8)
REG_FULL_RESOURCE_DESCRIPTOR - hex(9)

Если тип задан с использованием префикса "hex", то значение установки должно быть записано в виде последовательности чисел (от 0 до 255), разделённых запятыми. Если тип hex(4), то должно быть 4 числа, а в двойное слово они будут собраны в обратной последовательности (т.е. записаны они должны быть от младшего байта к старшему).

Если после префикса hex в скобках указано число 5,6,10 или большее 10, то считается, что тип установки REG_UNKNOWN, а её значение обрабатывается как REG_BINARY. Например, Corel использует тип hex(80000001).

Если тип не указан, то значение установки трактуется как символьная строка и должно быть взято в кавычки.

Если указан тип dword, то значение установки трактуется как шестнадцатиричное число. Оно должно содержать только символы 0-9, a-f, A-F (без кавычек). Символов может быть от 1 до 8.

Соответсвенно появился интерес накатать функции, для форматирования/перекодировки значений реестового типа REG_BINARY, REG_DWORD, REG_SZ и т.д. в формат .reg файла hex(3), hex(4), hex(1) и т.д.
Для типа REG_EXPAND_SZ, ни чего умней не родилось, как это:
Код:

$sRegKey = 'HKEY_CURRENT_USER\Software\DashSignature\Knagalis'
$sSerial = RegRead($sRegKey, 'SN')

For $i=1 To StringLen($sSerial)
    $sSerialResult &= Hex(Asc(StringMid($sSerial, $i, 1)), 2) & ',00,'
Next
$sSerialResult = 'hex(2):' & $sSerialResult
If StringRight($sSerialResult, 1) == ',' Then $sSerialResult = StringTrimRight($sSerialResult, 1)

$sFileContent = _
    'Windows Registry Editor Version 5.00' & @CRLF & @CRLF & _
    '[' & $sRegKey & ']' & ',00,00' & @CRLF & _
    '"SN"=' & $sSerialResult & @CRLF & @CRLF



Вот и все, в этом и вопрос....осталось немного покодить ;)

FlatX007 23-06-2009 13:37 1149735

А что утилита ConvRegToAu3 - неумеет этого делать ?

proxy 23-06-2009 13:51 1149747

Цитата:

Цитата FlatX007
ConvRegToAu3 »

, благодраю, интересная утилитка .....НО - задача то другая ))

FlatX007, ээ-хеее-ххххххххх......стал бы я возиться если уже все есть? - нет конечно )) конечно может и есть уже, но пока не нашел ))

Задача - с помощью AutoIt создать reg файл. А не из reg файла RegWrite функци... ))

FlatX007 23-06-2009 18:21 1150055

А всё допёрло ... я сначало невкурил.

semiono 23-06-2009 20:27 1150135

FlatX007, ещё хочу напомнить то, что reg.exe expand /? имеет тоже ограничения.
Я бы хотел иметь замену reg.exe, так как утилита коммандной строки сама по себе хороша,
потому что можно использовать батники, а так же вызывать из InnoSetup,
но стандартная утилита не всё умеет, а жаль.

SyDr 23-06-2009 21:43 1150187

Дайте спецификацию .reg файлов. То есть как выглядит в нём каждый из указанных типов значений.
Для любого ли типа необходимо ковертить в hex? Какое условие переноса строки?

proxy 23-06-2009 23:05 1150247

Sylver Dragon, а мне дайте 7 миллионов долларов ))))))))))))))))))))))))))
И то есть, почему ни кто не приносит кофе мне в постел? ;)
Где моя любимая кока-кола?? Какие условия возврата d-link барахла? ))))))))))

Спецификацию файлов, типа которых разработан в Miscrosoft....что может быть проще? хотя и не совсем спецификация ((

Цитата:

Цитата Sylver Dragon
Какое условие переноса строки? »

По мойму, это для удобочитабельности, т.е., как автору интересней, так и расставляется ..

...ааагрррх, на самом деле форматирование выглядит вот так:
Код:

$sSerial = 'VMKJGNDIDNWLDMKJGNDIDNWLD'
MsgBox(0, $sSerial, Hex(StringToBinary($sSerial, 2), 7))

для других типов необходимо поментья length на соответсвующий типу в Hex......освобожусь, допишу func :)

semiono 24-06-2009 02:40 1150355

Перенос строки я посчитал, смотрите выше:
Цитата:

Цитата semiono
Минимальная строка содержит 22 байта разделённых запятыми, и начинает убавляться на один байт »

Мне кажется это встроенно в регэдит и не меняется, и скорее всего все типы кроме REG_SZ и DWORD,
будут записываться одинакого, в том числе и переносы. Так как вроде бы нет причины их записывать
иначе. И для переноса строк в MULTI_SZ в самом регфайле ничего не будет предусмотренно,
так как это выполняется самим кодом, а это значит, что там в закрытии строк будут какие-то нули...
два байта или четыре, не знаю... 00,00,00,00 типа того! То-есть само оформление будет обычным,
но байт-контент надо уже контролировать... В InnoSetup переносы в multisz выполняет {break}

Характерные примеры multisz (WinXP)
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager
BootExecute =
Код:

autocheck autochk /k:D /k:E /k:F /k:G /k:H /k:I /k:J /k:K /k:L /k:M /k:N /k:O /k:P /k:Q /k:R /k:S /k:T /k:U /k:V /k:W /k:X /k:Y /k:Z *
pgdfgsvc C 1

Вторая строка - запись от Sysinternals PageDefrag утилиты. :)


Я как-то возился над PendingFileRenameOperating так и не понял ничего, запарился его тестить
перезагрузками :)

proxy 24-06-2009 03:17 1150362

Получается следующий результат:

Код:

$sSerial = 'VMKJGNDIDNWLDMKJGNDIDNWLD'
MsgBox(0, 'Строка для reg-файла', _StringToRegFileFormat($sSerial, 'REG_EXPAND_SZ'))

Func _StringToRegFileFormat($sData, $sType, $iSlash=10)
    Local $sHex, $iHexLength, $aData, $sDataResult, $i, $j=4
    If $iSlash < 0 OR ($iSlash > 0 AND $iSlash < 4) Then $iSlash = 4

    Switch $sType
        Case 'REG_DWORD'
            Return 'dword:' & Hex($sData, 8)
        Case 'REG_BINARY'
            $sType = 'hex:'
            $iHexLength = 3
        Case 'REG_EXPAND_SZ'
            $sType = 'hex(2):'
            $iHexLength = 2
        Case 'REG_MULTI_SZ'
            $sType = 'hex(7):'
            $iHexLength = 7
        Case Else
            Return
'"' & $sData & '"'
    EndSwitch

    $sData = StringLower(Hex(StringToBinary($sData, 2), $iHexLength))
    For $i=1 To StringLen($sData) Step 2
        $sDataResult &= StringMid($sData, $i, 2) & ','
        If $j == $iSlash Then
            $j = 0
            $sDataResult &= '\' & @CRLF
        EndIf
        $j += 1
    Next

    Return
$sType & $sDataResult & '00,00'
EndFunc

вариант без слешей:
Код:

_StringToRegFileFormat($sSerial, 'REG_EXPAND_SZ', 0)
Тип: REG_SZ записывается как есть, в кавычках:
Цитата:

"Name Value"="Value Data"

SyDr 24-06-2009 12:12 1150559

Цитата:

Цитата semiono
Минимальная строка содержит 22 байта разделённых запятыми, и начинает убавляться на один байт »

Откуда инфа? Вручную? У меня тогда немного по другому это сформулировано:
Если длина строки более 76 символов - выполняется перенос. Следующая строка содержит в начале два пробела.


Вроде что-то написал :) Работает вроде правильно. Пока проблемка с нулевым значением. Да и сам код выглядит громоздко.

proxy 24-06-2009 12:27 1150569

Цитата:

Вроде что-то написал Работает вроде правильно. Пока проблемка с нулевым значением. Да и сам код выглядит громоздко.
а код чего? на тему топик-стартера?

SyDr 24-06-2009 12:31 1150574

Да.
Изменил немного. Стало меньше. Но всё равно много (хотя, в принципе, знаю как ещё больше можно уменьшить):
Код:

Func RegValueReadAndConvert($KeyName, $ValueName)
    Local $Data = RegRead($KeyName, $ValueName)
    Local $Type = @extended
    Local $Return = '"' & $ValueName & '"='
    Local $Temp = ""
    Local $ArrT[1]

    Switch $Type

        Case $REG_SZ
            Return $Return & '"' & $Data & '"'

        Case $REG_EXPAND_SZ
            $Data
= StringReplace(StringToBinary($Data, 2), "0x", "")
            $Temp = $Return & "hex(2):"
            $Length = StringLen($Data) / 2
            For $i = 1 To $Length + 3
                If $I < $Length + 1 Then
                    $Temp &= StringMid($Data, $I * 2 - 1, 2) & ","
                Else
                    $Temp &= "00"
                    If $I < $Length + 3 Then $Temp &= ","
                EndIf
                $ArrT = StringSplit($Temp, @LF)
                If StringLen($ArrT[$ArrT[0]]) > 76 Then $Temp &= "\" & @CRLF & "  " ; два пробела
            Next
            Return $Temp

        Case $REG_BINARY
            $Data = StringReplace($Data, "0x", "")
            $Temp = $Return & "hex:"
            For $i = 1 To StringLen($Data) / 2 - 1
                $Temp &= StringMid($Data, $I * 2 - 1, 2) & ","
                $ArrT = StringSplit($Temp, @LF)
                If StringLen($ArrT[$ArrT[0]]) > 76 Then $Temp &= "\" & @CRLF & "  " ; два пробела
            Next
            $Temp &= StringMid($Data, StringLen($Data) - 1, 2)
            Return $Temp

        Case $REG_DWORD
            Return $Return & "dword:" & Hex($Data)

        Case $REG_MULTI_SZ
            $Data = StringReplace(StringToBinary($Data, 2), "0x", "")
            $Temp = $Return & "hex(2):"
            $Length = StringLen($Data) / 2
            For $i = 1 To $Length + 4
                If $I < $Length + 1 Then
                    $Temp &= StringMid($Data, $I * 2 - 1, 2) & ","
                Else
                    $Temp &= "00"
                    If $I < $Length + 4 Then $Temp &= ","
                EndIf
                $ArrT = StringSplit($Temp, @LF)
                If StringLen($ArrT[$ArrT[0]]) > 76 Then $Temp &= "\" & @CRLF & "  " ; два пробела
            Next
            Return $Temp

    EndSwitch
EndFunc


proxy 24-06-2009 14:30 1150669

+ мой вариант:
Код:

#region: - Options
    Opt('MustDeclareVars',      1)
    Opt('TrayIconDebug',        1)
    Opt('TrayIconHide',        0)
#endregion

Local $sFilePath    = 'd:\reg.reg'
Local $sRegKey      = 'HKEY_LOCAL_MACHINE\SYSTEM'
Local $sValueName  = 'SN'
Local $sValueType  = 'REG_EXPAND_SZ'
Local $fAllInKey    = 1
Local $iSlash      = 10

_CreatRegFile($sFilePath, $sRegKey, $sValueName, $sValueType, $fAllInKey, $iSlash)

Func _CreatRegFile($sFilePath, $sRegKey, $sValueName, $sValueType, $fAllInKey=0, $iSlash=10)
    Local Const $REG_SZ        = 1
    Local Const $REG_EXPAND_SZ  = 2
    Local Const $REG_BINARY    = 3
    Local Const $REG_DWORD      = 4
    Local Const $REG_MULTI_SZ  = 7

    Local $hFile, $i=1
    Local $sFileContent = 'Windows Registry Editor Version 5.00'
    $sRegKey = StringRegExpReplace($sRegKey, '\\+$', '')

    While 1
        If $fAllInKey Then
            $sValueName = RegEnumVal($sRegKey, $i)
            If @error <> 0 Then ExitLoop

            Switch
@extended
                Case $REG_SZ
                    $sValueType
= 'REG_SZ'
                Case $REG_EXPAND_SZ
                    $sValueType
= 'REG_EXPAND_SZ'
                Case $REG_BINARY
                    $sValueType
= 'REG_BINARY'
                Case $REG_DWORD
                    $sValueType
= 'REG_DWORD'
                Case $REG_MULTI_SZ
                    $sValueType
= 'REG_MULTI_SZ'
            EndSwitch
        EndIf


        $sFileContent &=  @CRLF & @CRLF & '[' & $sRegKey & ']' & @CRLF & _StringToRegFileFormat($sValueName, RegRead($sRegKey, $sValueName), $sValueType, $iSlash)
        If NOT $fAllInKey Then ExitLoop
        $i += 1
    WEnd

    $hFile = FileOpen($sFilePath, 8+2)
    FileWrite($hFile, $sFileContent)
    FileClose($hFile)
EndFunc

Func
_StringToRegFileFormat($sName, $sData, $sType, $iSlash=10)
    Local  $sHex, $iHexLength, $iNameLen, $iStartLen, $aResult, $sResult, $i

    Switch $sType
        Case 'REG_DWORD'
            Return 'dword:' & Hex($sData, 8)
        Case 'REG_BINARY'
            $sType = 'hex:'
            $iHexLength = 3
        Case 'REG_EXPAND_SZ'
            $sType = 'hex(2):'
            $iHexLength = 2
        Case 'REG_MULTI_SZ'
            $sType = 'hex(7):'
            $iHexLength = 7
        Case Else
            Return
'"' & $sData & '"'
    EndSwitch

    $iNameLen =  Floor(StringLen($sName & $sType) / 2)
    $sResult = StringLower(Hex(StringToBinary($sData, 2), 2))  & '0000'

    If StringLen($sResult)+(StringLen($sResult)/2)-1 > 76 Then $iSlash = 10

    If $iNameLen > $iSlash Then
        $iStartLen = 0
    Else
        $iStartLen = $iSlash - $iNameLen + 6
    EndIf

    If
StringLen($sResult)+(StringLen($sResult)/2)-1 < StringLen($sName & $sType) Then $iSlash = 0

    If $iNameLen < $iStartLen Then $iStartLen = $iSlash - $iNameLen + $iSlash-4
    If Mod($iStartLen, 2) <> 0 Then $iStartLen += 1

    Dim $aResult[2]
    $aResult[0] = StringLeft($sResult, $iStartLen)
    $aResult[1] = StringMid($sResult,  $iStartLen+1)

    For $i=0 To 1
        $aResult[$i] = StringRegExpReplace($aResult[$i], '([a-z0-9]{2,2})', '\1,')
        If $i Then
            If
$iSlash Then $aResult[$i] = '\' & @CRLF & StringRegExpReplace($aResult[$i], '(.{' & ($iSlash*3)-1 & '},)', '\1\\' & @CRLF)
            $aResult[$i] = StringRegExpReplace($aResult[$i], ',+$', '')
        EndIf
    Next


    $sResult = $aResult[0] & $aResult[1]

    Return '"' & $sName & '"=' & $sType & $sResult & @CRLF
EndFunc

Можно считывать как отдельную величину, так и все имеющиеся величины в ключе.
Учтено: длина строки < 76, и @CRLF в конце.
Уже лучше расставляются слеши, вся разбивка на StringRegExpReplace.

proxy 24-06-2009 14:56 1150693

Sylver Dragon:
Код:

Local Const $REG_SZ        = 1
Local Const $REG_EXPAND_SZ  = 2
Local Const $REG_BINARY    = 3
Local Const $REG_DWORD      = 4
Local Const $REG_MULTI_SZ  = 7

потерялись?



Hex конвертацию можно упростить:
Код:

$sSerial = 'VMKJGNDIDNWLDMKJGNDIDNWLD'
MsgBox(0, $sSerial, Hex(StringToBinary($sSerial, 2), 7))



Расстановка запятых, так не проще?
Код:

$sData = 'VMKJGNDIDNWLDMKJGNDIDNWLD'
For $i=1 To StringLen($sData) Step 2
    $sDataResult &= StringMid($sData, $i, 2) & ','
Next
MsgBox(0, $sData, $sDataResult)



Расстановка запятых + слеши:
Код:

$sData = 'VMKJGNDIDNWLDMKJGNDIDNWLD'
$iSlash = 10
For $i=1 To StringLen($sData) Step 2
    If $j == $iSlash Then
        $j = 0
        $sDataResult &= '\' & @CRLF
    EndIf
    $j += 1
    $sDataResult &= StringMid($sData, $i, 2) & ','
Next
MsgBox(0, $sData, $sDataResult)


SyDr 24-06-2009 15:08 1150706

Разве всё надо в hex конвертить?

Цитата:

Цитата proxy
Расстановка запятых, так не проще? »

Проще. Но ещё есть "закрывающие" нули и в конце строки запятая не нужна и также разделение на строки (If StringLen > 76). Возвращаемое функцией значение соответсвует тому, что я вижу в .reg файле (без конечного @CRLF).


Цитата:

Цитата proxy
потерялись? »

Я только функцию копировал. Константы были в основном скрипте.

proxy 24-06-2009 17:44 1150840

Цитата:

Цитата Sylver Dragon
Проще. Но ещё есть "закрывающие" нули и в конце строки запятая не нужна »

ну это само собой, в скрипте, выше получается так:
Цитата:

$sData = StringLower(Hex(StringToBinary($sData, 2), $iHexLength)) & '0000'
For $i=1 To StringLen($sData) Step 2
If $j == $iSlash Then
$j = 0
$sDataResult &= '\' & @CRLF
EndIf
$j += 1
$sDataResult &= StringMid($sData, $i, 2) & ','
Next

Return '"' & $sName & '"=' & $sType & StringRegExpReplace($sDataResult, ',+$', '')


Закрывающие нули:
Цитата:

$sData = StringLower(Hex(StringToBinary($sData, 2), $iHexLength)) & '0000'

Удаление запятой:
Цитата:

StringRegExpReplace($sDataResult, ',+$', '')


Цитата:

(If StringLen > 76)
вот это упустил из виду ....76 с учетом запятых?



Цитата:

(без конечного @CRLF).
специально его убрал, а так принципиально нужен?


...обновил..

SyDr 24-06-2009 18:27 1150867

StringRegExpReplace($TempValue, "([^,]{2})", "$0,") - расстановка запятых после каждого второго символа (в конце тоже будет).
Цитата:

Цитата proxy
вот это упустил из виду ....76 с учетом запятых? »

76 с учётом всего. И пробелов в начале и названия ключа. Ну, или другими словами если 77, 78 или 79 символов.
Цитата:

Цитата proxy
специально его убрал, а так принципиально нужен? »

Ну. Если FileWriteLine - то не нужно.
Плюс, после каждого раздела следует ещё один @CRLF

proxy 24-06-2009 18:52 1150883

Цитата:

Цитата Sylver Dragon
StringRegExpReplace($TempValue, "([^,]{2})", "$0,") »

ааагггррххх..... :up: Круть!!

semiono 24-06-2009 19:52 1150918

:o Молодцы! Приставить к награде пора! Я в восторге!

proxy 24-06-2009 20:45 1150942

7 миллионов доллоров, semiono, 7 миллионов :yahoo:

+ еще обновление:
Цитата:

Можно считывать как отдельную величину, так и все имеющиеся величины в ключе.
Учтено: длина строки < 76, и @CRLF в конце.
Уже лучше расставляются слеши, вся разбивка на StringRegExpReplace. »
эть, не чем же заняться в свободное время ... :nhl_check

amel27 25-06-2009 09:21 1151209

коль пошла такая пьянка, кину и свой вариант :)
Код:

$hFile = FileOpen("C:\TEST\TEST.reg", 8+2)

_RegValSave($hFile, "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\USBSTOR","DisplayName|Start|ImagePath")
_RegValSave($hFile, "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion","DevicePath|ProgramFilesDir", 1)
_RegValSave($hFile, "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Streams\0","ViewView2", 1)

Func _RegValSave($file, $key, $vals = "", $iAdd = 0)
    Local $val, $txt = ""
    If Not(IsArray($vals)) Then $vals = StringSplit($vals,",;|",2)
    For $i=0 To UBound($vals)-1
        $val = RegRead($key, $vals[$i])
        If @error Then ContinueLoop
        $txt &= _RegValFormat($vals[$i], $val, @extended) &@CRLF
    Next
    If
$txt == "" Then Return SetError(1, 0, 0)

    If IsString($file) Then $file = FileOpen($file, 8+2)
    If $file = -1 Then Return SetError(2, 0, 0)
    If $iAdd =0 Then FileWrite($file,'Windows Registry Editor Version 5.00'&@CRLF)
    Return FileWrite($file, @CRLF&"["& $key &"]"&@CRLF& $txt)
EndFunc

Func
_RegValFormat($sVal, $xData, $iType = 1)
    If $iType=1 Then Return '"'& $sVal &'"="'& $xData &'"' ; REG_SZ
    If $iType=4 Then Return '"'& $sVal &'"=dword:'& Hex(Int($xData),8) ; REG_DWORD

    Local $sLeft='"'& $sVal &'"=hex('& $iType &'):', $sData, $iData, $iWrap=80
    If $iType=2 Then $xData=StringToBinary($xData & Chr(0), 2) ; REG_EXPAND_SZ
    If $iType=3 Then $sLeft='"'& $sVal &'"=hex:' ; REG_BINARY
    If $iType=7 Then $xData=StringToBinary(StringRegExpReplace($xData &@LF,"[\n\r]+",Chr(0)) &Chr(0), 2) ; REG_MULTI_SZ
    If Not(IsBinary($xData)) Then $xData = Binary(StringRegExpReplace($xData,"^(?i:\s*0x)?((?:[[:xdigit:]]{2})+)$","0x\1"))
    $xData = StringTrimRight(StringRegExpReplace(Hex($xData),"(..)", "\1,"), 1)

    While StringLen($sLeft)+StringLen($xData)>$iWrap
        $iData
= Int(($iWrap-StringLen($sLeft)-1)/3)*3
        $sData&= $sLeft & StringLeft($xData, $iData) &"\" &@CRLF
        $xData = StringMid($xData, $iData+1)
        $sLeft="  "
    WEnd
    Return
$sData & $sLeft  & $xData
EndFunc

Цитата:

Цитата proxy
эть, не чем же заняться в свободное время ... »

честно говоря, не пойму чем semiono не устроил батник

proxy 25-06-2009 10:35 1151263

Цитата:

Цитата amel27
коль пошла такая пьянка, кину и свой вариант »

:up:, и как всегда все жуууутко замудренно и за рег-экспанно )))

Цитата:

semiono, нормальные герои всегда идут в обход (c)
;) ;) ;)

пора, semiono, тему завершать?

semiono 26-06-2009 04:23 1152003

Завершение уже не зависит от моего решения :)
Однако я нажал. +1

semiono 27-06-2009 21:26 1153366

Чтоб это доброе дело продолжалось, было б, зделать утиль regEx.exe которая читает ввод командой строки,
например, # regex /export HKLM\Microsoft\'Windows NT\.la -la-la' C:\'.my reg.reg' и делает это. ? :)

amel27 29-06-2009 11:47 1154520

Цитата:

Цитата semiono
зделать утиль regEx.exe которая читает ввод командой строки »

сколько угодно, только тестируйте :)
Код:

Global $KEY, $VAL, $ADD = False, $OUT=StringRegExpReplace(@ScriptFullPath,".[^.]+$", ".reg")

Global $aParms = StringRegexp($CmdLineRaw, '/(\w+)(?:[\s:]+(?:"([^"]+)"|([^\s/"]+)))?', 4)
If @error Then Exit -1 ; Ошибка: не указано ни одного параметра
For $aParm In $aParms
    If UBound($aParm)=2 Then Assign($aParm[1], True)
    If UBound($aParm)>2 Then Assign($aParm[1], $aParm[UBound($aParm)-1])
Next

Global
$iMode=8+2
If $ADD Then $iMode = 1

If $VAL=="*" Then $VAL = _RegEnumVals($KEY)
_RegValSave($OUT, $KEY, $VAL, $iMode)
Exit @error ; ошибки выполнения _RegValSave()

; =============================================================================
; _RegEnumVals($key)
; -----------------------------------------------------------------------------
; Перечисление всех параметров заданного ключа реестра
; $key        : имя ключа реестра
;
; При успехе  : возвращает массив имен параметров со счетчиком
; При неудаче : возвращает пустой массив
; =============================================================================

Func _RegEnumVals($key)
    Local $aRes[1]=[-1],$sVal=0
    Do
        $aRes[0] +=1
        ReDim $aRes[$aRes[0]+1]
        $aRes[$aRes[0]] = $sVal
        $sVal
= RegEnumVal($key, $aRes[0]+1)
    Until @error
    Return $aRes
EndFunc ; ==> _RegEnumVals

; =============================================================================
; _RegValSave($file, $key, [$vals, [, $mode]])
; -----------------------------------------------------------------------------
; Сохранение заданных параметров в REG-файл
;
; $file      : имя файла или хэндл
; $key        : имя ключа реестра
; $vals      : одно или несколько имен параметров, разделенных ",|;"
 ;            : или массив элементов со счетчиком
; $mode      : режим открытия файла (см. FileOpen)
;
; При успехе  : возвращает 1
;
; При неудаче : возвращает 0
;            :  @error=0, неверный режим открытия
;            :  @error=1, не обнаружено ни одного из заданных параметров
;            :  @error=2, ошибка открытия файла
; =============================================================================

Func _RegValSave($file, $key, $vals = "", $mode = 10)
    Local $dat, $txt = ""
    If Not(IsArray($vals)) Then $vals = StringSplit($vals,",;|")
    For $i=1 To $vals[0]
        $dat = RegRead($key, $vals[$i])
        If @error Then ContinueLoop
        $txt &= _RegValFormat($vals[$i], $dat, @extended) &@CRLF
    Next
    If
$txt=="" Then Return SetError(1, 0, 0)
    If IsString($file) Then
        $file = FileOpen($file, $mode)
        If $file = -1 Then Return SetError(2, 0, 0)
        If BitAND($mode,2) Then FileWrite($file,'Windows Registry Editor Version 5.00'&@CRLF)
    EndIf
    $key = StringRegExpReplace($key, "^HKLM\\", "HKEY_LOCAL_MACHINE\\")
    $key = StringRegExpReplace($key, "^HKCU\\", "HKEY_CURRENT_USER\\")
    $key = StringRegExpReplace($key, "^HKCR\\", "HKEY_CLASSES_ROOT\\")
    $key = StringRegExpReplace($key, "^HKU\\" , "HKEY_USERS\\")
    $key = StringRegExpReplace($key, "^HKCC\\", "HKEY_CURRENT_CONFIG\\")

    Return FileWrite($file, @CRLF&"["& $key &"]"&@CRLF& $txt)
EndFunc ; ==> _RegValSave

; =============================================================================
; _RegValFormat($sVal, $xData[, $iType])
; -----------------------------------------------------------------------------
; Вывод значения параметра реестра в формате REG-файла
;
; $sVal  : имя параметра
; $xData  : значение параметра, поддерживаемые комбинации тип+значение:
;            $iType=1, $xData - текстовая строка
;            $iType=2, $xData - текстовая строка
;            $iType=3, $xData - HEX или бинарная строка
;            $iType=4, $xData - целое 32-х битное число
;            $iType=7, $xData - одна или несколько текстовых строк
;        : при несоответствии, параметр преобразуется к требуемому типу
; $iType  : тип параметра
;            $iType=1 - REG_SZ
;            $iType=2 - REG_EXPAND_SZ
;            $iType=3 - REG_BINARY
;            $iType=4 - REG_DWORD
;            $iType=7 - REG_MULTI_SZ
;        : все другие значения $iType форматируются как REG_BINARY
; =============================================================================

Func _RegValFormat($sVal, $xData, $iType = 1)
    Local $sData='"'& $sVal &'"=hex('& $iType &'):', $iWidth
    If $sVal=="" Then $sVal="@"

    If $iType=1 Then Return '"'& $sVal &'"="'& $xData &'"' ; REG_SZ
    If $iType=2 Then $xData=StringToBinary($xData & Chr(0), 2) ; REG_EXPAND_SZ
    If $iType=3 Then $sData='"'& $sVal &'"=hex:' ; REG_BINARY
    If $iType=4 Then Return '"'& $sVal &'"=dword:'& Hex(Int($xData),8) ; REG_DWORD
    If $iType=7 Then $xData=StringToBinary(StringRegExpReplace($xData &@LF,"[\n\r]+",Chr(0)) &Chr(0), 2) ; REG_MULTI_SZ

    If Not(IsBinary($xData)) Then $xData = Binary(StringRegExpReplace($xData,"^(?i:\s*0x)?((?:[[:xdigit:]]{2})+)$","0x\1"))
    $xData = StringTrimRight(StringRegExpReplace(Hex($xData),"(..)", "\1,"), 1)

    $iWidth = 80-StringLen($sData)
    While StringLen($xData) > $iWidth
        $sData
&= StringLeft($xData, Int(($iWidth-1)/3)*3) &"\"&@CRLF&"  "
        $xData = StringTrimLeft ($xData, Int(($iWidth-1)/3)*3)
        $iWidth = 78
    WEnd
    Return
$sData & $xData
EndFunc ; _RegValFormat

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

@Echo Off

RegSave /OUT:C:\TEST\TEST.reg /KEY:HKLM\SYSTEM\CurrentControlSet\Services\USBSTOR /VAL:DisplayName,Start,ImagePath
RegSave /OUT:C:\TEST\TEST.reg /KEY:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion /VAL:DevicePath,ProgramFilesDir /ADD
RegSave /OUT:C:\TEST\TEST.reg /KEY:HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Streams\0 /VAL:* /ADD


semiono 22-01-2010 19:55 1327225

****
Регистр букв я сам исправил! Надеюсь правильно
If $iType=4 Then Return '"'& $sVal &'"=dword:'& StringLower(Hex(Int($xData),8)) ; REG_DWORD
...
$xData = StringTrimRight(StringRegExpReplace(StringLower(Hex($xData)),"(..)", "\1,"), 1)

Добавил ещё один &@CRLF в конец reg-файла, чтоб как у M$ было идентично. :)

1. Нашёл и более серьёзную проблему!!! =)
В именах пробелы нельзя использовать!
Хорошо что /key: double-quoted поддерживается:
"HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager" ,
но c "Value Name" облом :( ???!!!

2. Где в скрипте добавить ConsoleWrite() чтобы Success... выводилось согласно логике?

semiono 25-01-2010 04:40 1329069

Оказывается наполовину работает! Вообщем такое срабатывает /val "New Value #1"
Проблемма возникает при перечислении: /val "New Value #1","New Value #2", даже если один из параметров не имеет пробелов.
Причём, точки /val: можно не указывать, как я заметил.
Ну и всякие трансцендентальные типы REG_DWORD_BIG_ENDIAN скрипт не пережёвывает, впрочем это хорошо. :)

хух! нашёл "недокументированные возможности", можно так вбивать:
/val "New Value #2,New Value #1" — это валидно для работы RegSave* скрипта!

---
(!) есть небольшое различие в hex(7): записи пустых параметров.
regedit.exe "ExcludeFromKnownDlls"=hex(7):00,00
regsave.exe "ExcludeFromKnownDlls"=hex(7):00,00,00,00

--- я добавил вывод в консоль, для приличия :) похоже, что логично работает...
Код:

Global $aParms = StringRegexp($CmdLineRaw, '/(\w+)(?:[\s:]+(?:"([^"]+)"|([^\s/"]+)))?', 4)
If @error Then
ConsoleWrite("2001-2005 GmbH, Semiono. Coded by Amel27." & @CRLF & @CRLF)
ConsoleWrite(" //xregs.exe synops: ..." & @CRLF & @CRLF)
ConsoleWrite(@TAB & '{/val: "value1,value2,value3,etc."}|{/val:*}|{/add}...' & @CRLF)
ConsoleWrite(@TAB & '{/key: "[HKCR,HKCU,HKLM,HKU,HKCC]\Subkey"}' & @CRLF)
ConsoleWrite(@TAB & '{/reg: "[Drive:]\PATH\File.reg"}' & @CRLF) ; /out я переделал в $REG
        Exit -1 ; Ошибка: не указано ни одного параметра
EndIf

For $aParm In $aParms
    If UBound($aParm)=2 Then Assign($aParm[1], True)
    If UBound($aParm)>2 Then Assign($aParm[1], $aParm[UBound($aParm)-1])
Next

Global $iMode=8+2
If $add Then $iMode = 1

If $val=="*" Then $val = _RegEnumVals($key)
_RegValSave($reg, $key, $val, $iMode)

If @error = 1 Then
ConsoleWrite(@CRLF & "2001-2005 GmbH, Semiono. Coded by Amel27." & @CRLF)
ConsoleWrite("Failed! ..." & @CRLF)
        Exit @error ; ошибки выполнения _RegValSave()
EndIf

If @error = 0 Then
ConsoleWrite(@CRLF & "2001-2005 GmbH, Semiono. Coded by Amel27." & @CRLF)
ConsoleWrite("Success! ..." & @CRLF)
EndIf

----

А почему Func _RegValSave($file, $key, $vals = "", $mode = 42) не даёт юникод файл?
Или это от BitAND() операций ещё зависит в данном скрипте?

----
Я ещё кое что на-бета тестил...
Вот проблемма:
[HKEY_LOCAL_MACHINE\Software\Classes\WinRAR\shell\open\command]
"@"="C:\I\Apps\WinRAR\WinRAR.exe "%1""

Должно быть:
[HKEY_LOCAL_MACHINE\Software\Classes\WinRAR\shell\open\command]
@="C:\\I\\Apps\\WinRAR\\WinRAR.exe \"%1\""

И ещё очень не хватает опции сохранения всех субключей...
Я попытался запустить без /val: свитчера, чтобы сохранить следущее:
xregs.exe /key: "HKLM\Software\Classes\.rar" /reg: "c:\file.reg"
xregs.exe /key: "HKLM\Software\Classes\WinRAR\DefaultIcon" /reg: "c:\file.reg" /add
xregs.exe /key: "HKLM\Software\Classes\WinRAR\shell\open\command" /reg: "c:\file.reg" /add
Но они затирают по-моему друг друга. Вообщем что-то там непонятное было...

Мне пришла идея! Может лучше зделать другие разделители для коммандной строки?
Чтобы вообще это не противоречило скрипту, и чтоб не надо было экранировать.

Ещё одна косметичиская фишка если не трудно, надо чтобы при /add не добавлялись @CRLF & @CLRF
перед каждым субкейем, но это я сам виноват, я к концу регфайла же дописал & @CLRF,
правда в конце файла это уместно.


Время: 02:13.

Время: 02:13.
© OSzone.net 2001-