Показать полную графическую версию : Регфайл, синтаксис.
Думаю пора обсудить написание валидных регфайлов средствами 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
Простите а зачем это нужно ???
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,00,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
А что утилита ConvRegToAu3 - неумеет этого делать ?
ConvRegToAu3 », благодраю, интересная утилитка .....НО - задача то другая ))
FlatX007, ээ-хеее-ххххххххх......стал бы я возиться если уже все есть? - нет конечно )) конечно может и есть уже, но пока не нашел ))
Задача - с помощью AutoIt создать reg файл. А не из reg файла RegWrite функци... ))
FlatX007
23-06-2009, 18:21
А всё допёрло ... я сначало невкурил.
FlatX007, ещё хочу напомнить то, что reg.exe expand /? имеет тоже ограничения.
Я бы хотел иметь замену reg.exe, так как утилита коммандной строки сама по себе хороша,
потому что можно использовать батники, а так же вызывать из InnoSetup,
но стандартная утилита не всё умеет, а жаль.
Дайте спецификацию .reg файлов. То есть как выглядит в нём каждый из указанных типов значений.
Для любого ли типа необходимо ковертить в hex? Какое условие переноса строки?
Sylver Dragon, а мне дайте 7 миллионов долларов ))))))))))))))))))))))))))
И то есть, почему ни кто не приносит кофе мне в постел? ;)
Где моя любимая кока-кола?? Какие условия возврата d-link барахла? ))))))))))
Спецификацию файлов, типа которых разработан в Miscrosoft....что может быть проще? (http://support.microsoft.com/kb/310516/ru) хотя и не совсем спецификация ((
Какое условие переноса строки? »
По мойму, это для удобочитабельности, т.е., как автору интересней, так и расставляется ..
...ааагрррх, на самом деле форматирование выглядит вот так:
$sSerial = 'VMKJGNDIDNWLDMKJGNDIDNWLD'
MsgBox(0, $sSerial, Hex(StringToBinary($sSerial, 2), 7))
для других типов необходимо поментья length на соответсвующий типу в Hex......освобожусь, допишу func :)
Перенос строки я посчитал, смотрите выше:
Минимальная строка содержит 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 так и не понял ничего, запарился его тестить
перезагрузками :)
Получается следующий результат:
$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"
Минимальная строка содержит 22 байта разделённых запятыми, и начинает убавляться на один байт »
Откуда инфа? Вручную? У меня тогда немного по другому это сформулировано:
Если длина строки более 76 символов - выполняется перенос. Следующая строка содержит в начале два пробела.
Вроде что-то написал :) Работает вроде правильно. Пока проблемка с нулевым значением. Да и сам код выглядит громоздко.
Вроде что-то написал http://forum.oszone.net/images/smilies/new/smile.gif Работает вроде правильно. Пока проблемка с нулевым значением. Да и сам код выглядит громоздко.
а код чего? на тему топик-стартера?
Да.
Изменил немного. Стало меньше. Но всё равно много (хотя, в принципе, знаю как ещё больше можно уменьшить):
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
+ мой вариант:
#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.
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)
Разве всё надо в hex конвертить?
Расстановка запятых, так не проще? »
Проще. Но ещё есть "закрывающие" нули и в конце строки запятая не нужна и также разделение на строки (If StringLen > 76). Возвращаемое функцией значение соответсвует тому, что я вижу в .reg файле (без конечного @CRLF).
потерялись? »
Я только функцию копировал. Константы были в основном скрипте.
Проще. Но ещё есть "закрывающие" нули и в конце строки запятая не нужна »
ну это само собой, в скрипте, выше получается так:
$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).
специально его убрал, а так принципиально нужен?
...обновил (http://forum.oszone.net/post-1150669-15.html)..
StringRegExpReplace($TempValue, "([^,]{2})", "$0,") - расстановка запятых после каждого второго символа (в конце тоже будет).
вот это упустил из виду ....76 с учетом запятых? »
76 с учётом всего. И пробелов в начале и названия ключа. Ну, или другими словами если 77, 78 или 79 символов.
специально его убрал, а так принципиально нужен? »
Ну. Если FileWriteLine - то не нужно.
Плюс, после каждого раздела следует ещё один @CRLF
StringRegExpReplace($TempValue, "([^,]{2})", "$0,") »
ааагггррххх..... :up: Круть!!
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.