1

Тема: AHK v2: Функция перевода из hex в text

Здравствуйте всем.
Подскажите пожалуйста, почему этот код вываливает ошибку в ahk v2 "Error: Parameter #1 of Chr requires a Number, but received a String."? При этом в ahk v1 работает без ошибок.


#Requires AutoHotkey v2

Hex := "31,00,2d,00,45,00,6e,00,67,00,6c,00,69,00,73,00,68,00,00,00,32,00,2d,00,20,04,43,04,41,04,41,04,3a,04,38,04,39,04,00,00,00,00"

Hex := RegExReplace(Hex, "i)[^\da-f]") ; удалить запятые, пробелы и "\"
	Loop StrLen(Hex) /2 {
		Txt .= Chr("0x" SubStr(Hex, A_index *4 -1, 2) SubStr(Hex, A_index *4 -3, 2))
		}
		
MsgBox(Txt)

2

Re: AHK v2: Функция перевода из hex в text

Проверяйте так:


#Requires AutoHotkey v2

Hex := "31,00,2d,00,45,00,6e,00,67,00,6c,00,69,00,73,00,68,00,00,00,32,00,2d,00,20,04,43,04,41,04,41,04,3a,04,38,04,39,04,00,00,00,00"

Hex := RegExReplace(Hex, "i)[^\da-f]") ; удалить запятые, пробелы и "\"
	Loop StrLen(Hex) /2 {
        MsgBox "0x" SubStr(Hex, A_index *4 -1, 2) SubStr(Hex, A_index *4 -3, 2)
		Txt .= Chr("0x" SubStr(Hex, A_index *4 -1, 2) SubStr(Hex, A_index *4 -3, 2))
		}
		
MsgBox(Txt)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3 (изменено: bubblegum, 2025-07-26 02:43:45)

Re: AHK v2: Функция перевода из hex в text

teadrinker, спасибо за подсказку! Нашел Только почему-то русский шрифт перестал читать. В ahk v1 все работало.

4

Re: AHK v2: Функция перевода из hex в text

Попробуйте так:

#Requires AutoHotkey v2

hex_en := '31,00,2d,00,45,00,6e,00,67,00,6c,00,69,00,73,00,68,00'
hex_ru := '32,00,2d,00,20,04,43,04,41,04,41,04,3a,04,38,04,39,04'
buf_en := CryptStringToBinary(hex_en, 'CRYPT_STRING_HEX')
buf_ru := CryptStringToBinary(hex_ru, 'CRYPT_STRING_HEX')
MsgBox StrGet(buf_en) . '`n' . StrGet(buf_ru)

CryptStringToBinary(string, formatName := 'CRYPT_STRING_BASE64')
{
    static formats := { CRYPT_STRING_BASE64: 0x1,
                        CRYPT_STRING_HEX:    0x4,
                        CRYPT_STRING_HEXRAW: 0xC }
    fmt := formats.%formatName%
    chars := StrLen(string)
    if !DllCall('Crypt32\CryptStringToBinary', 'Str', string, 'UInt', chars, 'UInt', fmt
                                             , 'Ptr', 0, 'UIntP', &bytes := 0, 'UIntP', 0, 'UIntP', 0)
        throw OSError()
    outBuf := Buffer(bytes, 0)
    DllCall('Crypt32\CryptStringToBinary', 'Str', string, 'UInt', chars, 'UInt', fmt
                                         , 'Ptr', outBuf, 'UIntP', &bytes, 'UIntP', 0, 'UIntP', 0)
    return outBuf
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5 (изменено: bubblegum, 2025-08-03 03:50:34)

Re: AHK v2: Функция перевода из hex в text

teadrinker, спасибо за ответ - отлично работает! Давно не заходил на сайт и только заметил ответ. Говорят, вызов dll работает медленнее. Я уже сделал эту функцию немного по другому, без вызова dll - тоже работает с кириллицей. Она считывает данные из одного Edit DataIn и отправляет в другой Edit DataOut.


#Requires AutoHotkey v2

getTxt(){
	strHex := DataIn.Value
	strHex := RegExReplace(strHex, ',00(,00){4}$', ',00') ; удалить заключительный блок ,00,00,00,00,00 из REG_MULTI_SZ, чтобы не замещался на \n
	strHex := RegExReplace(strHex, ',00(,00){2}$', ',00') ; удалить заключительный блок ,00,00,00 из REG_EXPAND_SZ за ненадобностью
	strHex := RegExReplace(strHex, 'im),00,00,00,', ',00,0A,00,') ; символ перевода новой строки 00,00,00, (встречается только между строк в REG_MULTI_SZ) заменить на реальный \n = 0a,00
	strHex := RegExReplace(strHex, 'i)[^\da-f]') ; удалить запятые, пробелы и "\"
	Txt := ''
	hexLen := StrLen(strHex)
	Loop (hexLen /4){
		LowByteHex := SubStr(strHex, (A_Index -1) *4 +1, 2) 
		HighByteHex := SubStr(strHex, (A_Index -1) *4 +3, 2)
		CodePointHex := HighByteHex . LowByteHex 
		Txt .= Chr('0x' CodePointHex)
		}
	DataOut.Value := Txt
}

6

Re: AHK v2: Функция перевода из hex в text

bubblegum пишет:

Она считывает данные из Edit

В любом случае это не очень хорошая идея. Функция должна делать только то, для чего предназначена, в данном случае перекодировать HEX в текст. Ваша не будет работать, если отсутствует объект DataIn со свойством Value. Лучше считывать текст до вызова функции и передавать его параметром, полученный текст возвращать через return. Ещё вы не учитываете, что текст может быть в разных кодировках.
Что по скорости — не знаю, можно сравнить, если сделаете со входящим параметром и выводом. Но способ, который я привёл, это классический способ работы с HEX и base64, в любом серьёзном скрипте увидите именно такой вариант.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7 (изменено: bubblegum, 2025-08-01 16:52:02)

Re: AHK v2: Функция перевода из hex в text

teadrinker, ок, а как сделать подобную функцию с вызовом dll для перевода text to hex реестра windows? Я сделал подобие первой. Может будет лучше Ваш вариант? Только надо учитывать перевод новой строки в REG_MULTI_SZ Видимо, тоже нужно будет использовать RegExReplace?

8

Re: AHK v2: Функция перевода из hex в text

Скорее всего так:

#Requires AutoHotkey v2

text := '
(
Первая строка
Вторая строка
Третья строка
)'

MsgBox TextToREG_MULTI_SZ(text)

TextToREG_MULTI_SZ(text, delimiter := '`n', omit := '`r') {
    lines := StrSplit(text, delimiter, omit)
    total := 2
    for line in lines {
        total += StrPut(line, 'UTF-16')
    }
    buf := Buffer(total, 0), offset := 0
    for line in lines {
        offset += StrPut(line, buf.Ptr + offset, 'UTF-16')
    }
    return CryptBinaryToString(buf,, 'CRYPT_STRING_HEXRAW')
}


CryptBinaryToString(data, size?, formatName := 'CRYPT_STRING_BASE64', NOCRLF := true)
{
    static formats := { CRYPT_STRING_BASE64: 0x1,
                        CRYPT_STRING_HEX:    0x4,
                        CRYPT_STRING_HEXRAW: 0xC }
         , CRYPT_STRING_NOCRLF := 0x40000000

    sz := size ?? data.size
    fmt := formats.%formatName% | (NOCRLF ? CRYPT_STRING_NOCRLF : 0)
    if !DllCall('Crypt32\CryptBinaryToString', 'Ptr', data, 'UInt', sz, 'UInt', fmt, 'Ptr', 0, 'UIntP', &chars := 0)
        throw OSError()
    VarSetStrCapacity(&outString, chars)
    DllCall('Crypt32\CryptBinaryToString', 'Ptr', data, 'UInt', sz, 'UInt', fmt, 'Str', outString, 'UIntP', &chars)
    return outString
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

9 (изменено: bubblegum, 2025-08-01 17:32:40)

Re: AHK v2: Функция перевода из hex в text

teadrinker Нашел скрипт для теста скорости выполнения конвертации с вызовом dll и без, только для ahk v1


#Requires AutoHotkey v1

SetBatchLines -1
text := "The quick brown fox jumps over the lazy dog"
start := A_TickCount
loop 1000
	str2hex(text)
result .= "Format:`t" A_TickCount - start "ms`n"
start := A_TickCount
loop 1000
	crypt_str2hex(text)
result .= "Crypt:`t" A_TickCount - start "ms`n"
msgbox % result 
; Format:	47ms
; Crypt:	3375ms


crypt_str2hex(string)
{
    VarSetCapacity(bin, StrPut(string, "UTF-8")) && len := StrPut(string, &bin, "UTF-8") - 1 
    if !(DllCall("crypt32\CryptBinaryToString", "ptr", &bin, "uint", len, "uint", 0x4, "ptr", 0, "uint*", size))
        throw Exception("CryptBinaryToString failed", -1)
    VarSetCapacity(buf, size << 1, 0)
    if !(DllCall("crypt32\CryptBinaryToString", "ptr", &bin, "uint", len, "uint", 0x4, "ptr", &buf, "uint*", size))
        throw Exception("CryptBinaryToString failed", -1)
    return StrGet(&buf)
}

str2hex(str)
{
	loop, parse, str
		hex .= Format("{:x}", Asc(A_LoopField))
	return hex
}

10

Re: AHK v2: Функция перевода из hex в text

teadrinker, спасибо за эту функцию!

11

Re: AHK v2: Функция перевода из hex в text

Но именно для записи в реестр можно просто так:

text := 'Первая строка`nВторая строка`nТретья строка'
RegWrite text, 'REG_MULTI_SZ', 'HKCU\Software\MyApp', 'MyValue'
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

12

Re: AHK v2: Функция перевода из hex в text

teadrinker, нужна именно конвертация без записи в реестр. Спасибо, все работает

13

Re: AHK v2: Функция перевода из hex в text

bubblegum пишет:

скрипт для теста скорости

Ну, иногда универсальность важнее скорости.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14 (изменено: bubblegum, 2025-08-01 17:42:42)

Re: AHK v2: Функция перевода из hex в text

teadrinker, согласен. Потому и попросил другой пример с вызовом dll из text в hex. Ваши варианты лучше моих. Еще раз спасибо.

15

Re: AHK v2: Функция перевода из hex в text

Кроме того, тест не совсем корректный. Он в каждой итерации загружает библиотеку crypt32.dll. Надо так:

#Requires AutoHotkey v1

SetBatchLines -1
hLib := DllCall("LoadLibrary", "str", "crypt32.dll", "ptr")
text := "The quick brown fox jumps over the lazy dog"
start := A_TickCount
loop 1000
	str2hex(text)
result .= "Format:`t" A_TickCount - start "ms`n"
start := A_TickCount
loop 1000
	crypt_str2hex(text)
result .= "Crypt:`t" A_TickCount - start "ms`n"
msgbox % result


crypt_str2hex(string)
{
    VarSetCapacity(bin, StrPut(string, "UTF-8")) && len := StrPut(string, &bin, "UTF-8") - 1 
    if !(DllCall("crypt32\CryptBinaryToString", "ptr", &bin, "uint", len, "uint", 0x4, "ptr", 0, "uint*", size))
        throw Exception("CryptBinaryToString failed", -1)
    VarSetCapacity(buf, size << 1, 0)
    if !(DllCall("crypt32\CryptBinaryToString", "ptr", &bin, "uint", len, "uint", 0x4, "ptr", &buf, "uint*", size))
        throw Exception("CryptBinaryToString failed", -1)
    return StrGet(&buf)
}

str2hex(str)
{
	loop, parse, str
		hex .= Format("{:x}", Asc(A_LoopField))
	return hex
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16 (изменено: bubblegum, 2025-08-01 17:54:19)

Re: AHK v2: Функция перевода из hex в text

teadrinker, да, получается, что cript быстрее format работает в 2 раза! Впрочем, универсальность лучше, как Вы уже написали.

17

Re: AHK v2: Функция перевода из hex в text

bubblegum, тут зависит от длины текста.
Короткие фразы быстрее через str2hex.
Можете написать код для конвертации, например на c++, скомпилировать его и вызывать на ахк.
https://www.autohotkey.com/boards/viewtopic.php?t=32