Что нового

Быстрый поиск ключа в CLSID

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Подскажите, пожалуйста, можно ли осуществить поиск ключа в ветке реестра HKCR\CLSID иначе, чем с помощью RegEnumKey() в цикле?
Уж очень долго эта функция работает с таким большим количеством ключей...
 

Yashied

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

Код:
RegEnumVal('HKCR\CLSID\{A52BFCF1-6B91-4acc-9566-8F018C044E61}', 1)
If @error = 1 Then
	MsgBox(0, @error, 'CLSID not found.')
EndIf
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Yashied
У меня искомые ключи:
"?? ?? ?? ??-2520-40B4-8520-2980C53A1C05"
Первые 8 символов неизвестны...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
А ProgID известен?
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Yashied
В этих ключах формат не соблюден (даже нет {}-скобок), и я их ищу для удаления...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Тогда другого выхода нет (я думаю).
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Yashied
Утилита TRASHREG проверяет 10300 ключей за 2 секунды...
Скрипт AUTOIT обычным перебором проверяет около 2 минут...
Так много, потому что AUTOIT - интерпретатор?

Вот функция:
Код:
Func DELETEKEY()
  $COUNTER=1
  while true
   $KEY=RegEnumKey("HKCR\CLSID",$COUNTER)
   if @error <> 0 then ExitLoop
   if StringRight($KEY,28)="-2520-40B4-8520-2980C53A1C05" then
    RegDelete("HKCR\CLSID\"&$KEY)
    ContinueLoop
   endif
   $COUNTER+=1
  wend
 EndFunc

Может быть, ее можно оптимизировать?
 

o_nix

Новичок
Сообщения
35
Репутация
1
Незнаю насколько медленно работает RegEnumKey
может имеет смысл экспортировать всю нужную ветку реестра в файл а потом шустро обработать регуляркой приведя в удобный для использования вид ?

Экспорт ветки
regedit.exe -ea C:\reg_temp.reg "HKCR\CLSID"
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
o_nix
Ну, экспорт в файл ключа CLSID занял шесть секунд...
Насколько долго будет работать поиск подстроки в файле размером 2,8 МБ с примерно 70000 строк?
 

Latoid

Знающий
Сообщения
95
Репутация
11
Regexp'ом быстро. Точно время затрудняюсь назвать, но быстро
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Latoid
Хорошо... Попробую регулярными выражениями в файле искать...
 

Latoid

Знающий
Сообщения
95
Репутация
11
Что-то в этом духе. Однако теперь тормозит чтение файла в массив
Код:
#Include <File.au3>
#Include <Array.au3>
Dim $aRecords

_FileReadToArray ("111.reg", $aRecords)

_ArrayDisplay ($aRecords)
$s = ""
For $r=1 to $aRecords[0]
	$s &=$aRecords[$r]
Next
ConsoleWrite ("регэксп стартует" & @CRLF)
$aRecords2 = StringRegExp ($s, "\{?[A-z\d]{8}-2520-40B4-8520-2980C53A1C05\}?", 3)
_ArrayDisplay ($aRecords2)
 

o_nix

Новичок
Сообщения
35
Репутация
1
snoitaleR - здесь смысл в том что ненужно использовать доп ПО (трешрег)
Обработав грамотной регуляркой можно сразу получить готовый список в нужном формате для удаления и потом снести его ....

А вот скорость регекспа сильно будет зависеть от того как вы его составите тк методы и способы разные а приведут к конкретному одному результату... - сам посебе regexp это та ещё наука :smile: видел книжку более 300 стр ... так всю и неосилил :D

Latoid
А зачем читать файл в массив ?? просто подгрузи его как файл и потом регуляркой обработай ....
а уже полученные данные отправь в массив

Какого размера входной файл получается ?
 

Yashied

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

Код:
Func DELETEKEY()

	Local $Ret, $tData, $pData, $hKey, $Count = 0

	$Ret = DllCall('advapi32.dll', 'long', 'RegOpenKeyExW', 'ulong_ptr', 0x80000000, 'wstr', 'CLSID', 'dword', 0, 'dword', 0xF003F, 'ulong_ptr*', 0)
	If (@error) Or ($Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	$hKey = $Ret[5]
	$tData = DllStructCreate('wchar[1024]')
	$pData = DllStructGetPtr($tData)
	While 1
		$Ret = DllCall('advapi32.dll', 'long', 'RegEnumKeyW', 'ulong_ptr', $hKey, 'dword', $Count, 'ptr', $pData, 'dword', 1024)
		If (@error) Or ($Ret[0]) Then
			ExitLoop
		EndIf
		If StringRight(DllStructGetData($tData, 1), 28) = '-2520-40B4-8520-2980C53A1C05' Then
			DllCall('advapi32.dll', 'long', 'RegDeleteKeyW', 'ulong_ptr', $hKey, 'wstr', DllStructGetData($tData, 1))
		EndIf
		$Count += 1
	WEnd
	DllCall('advapi32.dll', 'long', 'RegCloseKey', 'ulong_ptr', $hKey)
	$tData = 0
EndFunc   ;==>DELETEKEY
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Yashied
Супер... +1 :smile:
WINAPI который раз выручает AUTOIT...


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

Latoid
Хотелось бы и твой вариант завершить...
Он быстрее стандартного, может, когда пригодится... :smile:
Однако функция _ArrayDisplay ($aRecords2), насколько я понял, выдала мне весь массив из 70000 строк...
То есть, не отфильтровала нужные ключи...

Точнее, _ArrayDisplay ($aRecords) выдала весь массив строк, а _ArrayDisplay ($aRecords2) ничего не выдала...
Хотя строки нужные точно есть в файле...

Кстати, размер строковой переменной 2147483647 символов...
А мой файл 2,8 МБ, что больше, поэтому строковая переменная могла переполниться...
 

Latoid

Знающий
Сообщения
95
Репутация
11
snoitaleR сказал(а):
Точнее, _ArrayDisplay ($aRecords) выдала весь массив строк, а _ArrayDisplay ($aRecords2) ничего не выдала...
Хотя строки нужные точно есть в файле...

Кстати, размер строковой переменной 2147483647 символов...
А мой файл 2,8 МБ, что больше, поэтому строковая переменная могла переполниться...

1. Поправил регэксп. См. выше. У меня нормально отрабатывает. Он раньше учитывал только цифры в первых восьми символах, теперь и буквы тоже
2. Из справки:
15. What are the current technical limits of AutoIt v3?
...
Maximum string length: 2,147,483,647 characters
....

Т.е. 2 Гб.
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Latoid
Да, действительно, теперь работает... :smile:
Спасибо... +1

Думаю, тему можно закрыть...
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied
Я тут попробовал также с WinAPI пронумирировать значения ключей (RegEnumValue), но у меня скрипт постоянно крашится, я видимо неправильно расшифровываю описание использования функций:

Код:
$nHKEY_LOCAL_MACHINE = 0x80000002
$sRegKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"

$aRet = DllCall('advapi32.dll', 'long', 'RegOpenKeyExW', 'ulong_ptr', $nHKEY_LOCAL_MACHINE, _
	'wstr', $sRegKey, 'dword', 0, 'dword', 0xF003F, 'ulong_ptr*', 0)
If @error Or $aRet[0] Then Exit

$hKey = $aRet[5]
$tData = DllStructCreate('char[1024]')
$pData = DllStructGetPtr($tData)

$i = 0

While 1
	$aRet = DllCall('advapi32.dll', 'long', 'RegEnumValue', 'ulong_ptr', $hKey, 'dword', $i, 'ptr', $pData, 'dword', 1024, 'ptr', 0)
	If @error Or $aRet[0] Then ExitLoop
	
	$sRegKey_Name = DllStructGetData($tData, 1)
	$i += 1
	
	ConsoleWrite($sRegKey_Name & @CRLF)
WEnd

DllCall('advapi32.dll', 'long', 'RegCloseKey', 'ulong_ptr', $hKey)


Есть идеи как это использовать корректно?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
CreatoR

Код:
DllCall('advapi32.dll', 'long', 'RegEnumValue', 'ulong_ptr', $hKey, 'dword', $i, 'ptr', $pData, 'dword*', 1024, 'ptr', 0, 'ptr', 0, 'ptr', 0, 'ptr', 0)


'dword*' - In/Out

Лучше пользоваться оффициальным MSDN.
 
Верх