Page 1 of 1

Как получить путь к установленной проги через реестр?

Posted: Tue Jun 18, 2019 8:50 pm
by AZJIO
Я хочу допустим запустить скрипт для AutoIt3, но указывать не прямой путь или не через относительный путь по отношению к AkelPad, а взять непосредственно с реестра.

у KDJ есть пара скриптов:
PluginText.js
ScreenView.js
содержащих RegQueryValueExW, поиском по скриптам нашёл, ну кроме этого видел варианты с помощью объектов ActiveXObject("WScript.shell"), но адаптировать пока не получилось.

Взял отсюда и переделал немного:

Code: Select all

var hEditWnd = AkelPad.GetEditWnd();
var oSys = AkelPad.SystemFunction();

// var HKEY_CLASSES_ROOT = 0x80000000;
// var HKEY_CURRENT_USER = 0x80000001;
// var HKEY_LOCAL_MACHINE = 0x80000002;
// var HKEY_USERS = 0x80000003;
// var HKEY_CURRENT_CONFIG = 0x80000005;
var sPath = ReadRegistry(0x80000001, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", "AppData");
AkelPad.MessageBox(hEditWnd, sPath, "Путь", 0);


function ReadRegistry(nRoot, sKeyName, sValName) {
    var DT_UNICODE = 1; // тип данных при чтении копировании памяти
    var DT_DWORD = 3;
    var KEY_QUERY_VALUE = 0x0001; // тип доступа: запрос значения
    var REG_SZ = 1; // строка
    var REG_EXPAND_SZ = 2; // в строке есть сжатые переменные типа %temp%
    // var REG_BINARY        = 3; // бинарные
    // var REG_DWORD        = 4; // число
    // var REG_MULTI_SZ        = 7; // мультистрока
    var ERROR_SUCCES = 0;
    var ERROR_MORE_DATA = 234;

    var lpSubKey = MakeString(sKeyName);
    var lpValue = MakeString(sValName);
    var lpKey = AkelPad.MemAlloc(4);
    var lpType = AkelPad.MemAlloc(4);
    var lpDataSize = AkelPad.MemAlloc(4);
    var lpData;
    var sPath = "";
    var hKey;
    var nDataSize;
    var nType;
    var nError;

    nError = oSys.Call("advapi32::RegOpenKeyEx" + _TCHAR,
        nRoot, // Корневой раздел реестра
        lpSubKey, // Указатель на  строку подраздел реестра
        0, // Зарезервировано. должно быть 0
        KEY_QUERY_VALUE, // Тип доступа к реестру (запрос значения)
        lpKey) // Указатель, куда возвращается итоговый ключ
    if (nError == ERROR_SUCCES) // Если нет ошибки в вызове (раздел существует)
    {
        hKey = AkelPad.MemRead(lpKey, DT_DWORD);

        // первый вызов чтобы получить размер данных
        nError = oSys.Call("advapi32::RegQueryValueEx" + _TCHAR,
            hKey, // Раздел реестра
            lpValue, // Указатель на строку параметра, значение которого нужно получить
            0,
            lpType, // Указатель, куда возвращается тип значения: в нашем случае будет 1 или 2, то есть REG_SZ или REG_EXPAND_SZ
            0,
            lpDataSize) // Указатель, куда возвращается размер буфера, чтобы данные могли уместиться
        if (nError == ERROR_SUCCES) // Если нет ошибки в вызове (подраздел существует)
        {
            nDataSize = AkelPad.MemRead(lpDataSize, DT_DWORD) // получаем число (размер данных) из указателя
            nType = AkelPad.MemRead(lpType, DT_DWORD) // получаем тип данных (REG_SZ или REG_EXPAND_SZ) из указателя, что бы  знать как с ними поступать
            lpData = AkelPad.MemAlloc(nDataSize); // Выделяем память нужного размера
            if ((nType == REG_SZ || nType == REG_EXPAND_SZ) && // Если тип данных REG_SZ или REG_EXPAND_SZ (путь с переменной)
                (nDataSize >= 4)) // Реальный полученный размер данных в буфере не менее 4-х байтов
            {
                // второй вызов чтобы получить данные, если первый был успешен
                nError = oSys.Call("advapi32::RegQueryValueEx" + _TCHAR,
                    hKey, // Раздел реестра
                    lpValue, // Указатель на строку параметра, значение которого нужно получить
                    0, // должно быть NULL
                    0, // нет смысла получать тип второй раз
                    lpData, // Указатель на буфер, куда возвращается значение, ради которого сделана эта функция
                    lpDataSize) // Указатель, куда возвращается размер буфера, чтобы данные могли уместиться
                if (nError == ERROR_SUCCES) // Если нет ошибки в вызове
                {
                    sPath = AkelPad.MemRead(lpData, DT_UNICODE);
                }
            }
        }
        oSys.Call("advapi32::RegCloseKey", hKey);
    }

    // освобождаем все указатели
    AkelPad.MemFree(lpDataSize);
    AkelPad.MemFree(lpData);
    AkelPad.MemFree(lpType);
    AkelPad.MemFree(lpKey);
    AkelPad.MemFree(lpValue);
    AkelPad.MemFree(lpSubKey);
    return sPath;
}

function MakeString(pStr) {
    var lpBuffer = AkelPad.MemAlloc((pStr.length + 1) * _TSIZE); // Выделяем память размером со строку
    AkelPad.MemCopy(lpBuffer, pStr, _TSTR); // Копируем строку в выделенную память
    return lpBuffer; // Возвращаем указатель на строку
}
, обновил 2 раза (улучшил логику, отступы и добавил комментарии)

Posted: Sun Jul 26, 2020 1:18 pm
by Eskander88
: : : 1
Результат работы скрипта выдал сообщение «%USERPROFILE%\AppData\Roaming». Так должно быть? Реальный же параметр в реестре имеет название «common AppData» - а если просто AppData?

: : : 2
вопрос делетанта: а что будет если память не очищать функцией AkelPad.MemFree(…)?