Создание раздела реестра Windows без значения по умолчанию (НЕ пустого) с помощью AutoHotkey

Мне нужно создать новый раздел реестра со значением по умолчанию no с помощью AutoHotkey.

Тривиальным решением должно быть:

RegWrite, REG_SZ, HKCU, Environment\testkey

оставив поля имени и значения пустыми. К сожалению, это создает testkey со значением по умолчанию blank, то есть пустой строкой, чего я не хочу. Мне нужно значение по умолчанию с содержимым undefined, то есть то же самое, что происходит, когда я создаю новый ключ в RegEdit (извините за отсутствие терминологии, у меня итальянская локализованная ОС, поэтому я не знаю как значение "not set" отображается в английском языке).

Я нашел обходной путь, который заключается в удалении значения по умолчанию сразу после создания с помощью:

RegWrite, REG_SZ, HKCU, Environment\testkey
RegDelete, HKCU, Environment\testkey, AHK_DEFAULT

но это кажется грязным взломом и, возможно, повлияет на производительность, если мне придется создать много таких ключей.

Есть ли более чистый способ достичь той же цели (может быть, каким-то образом заставить RegWrite не создавать пустое значение по умолчанию, а просто создать ключ)?


person Lorenzo Donati -- Codidact.com    schedule 16.11.2014    source источник
comment
Возможно, стоит упомянуть, что мне нужно решение, работающее для WindowsXP и Windows7, хотя, вероятно, эта информация не очень актуальна.   -  person Lorenzo Donati -- Codidact.com    schedule 16.11.2014


Ответы (1)


Встроенная перезапись Autohotkeys, как вы сказали, не поддерживает пустой ключ.

Я провел небольшое тестирование, и вот что вы можете попробовать

Если вы оставите ValueName пустым, будет использоваться значение подраздела по умолчанию, если sValue опущено, используется пустое / нулевое значение.

#SingleInstance force
RegWrite("REG_SZ","HKCU","Environment\testkey","","")
return

RegWrite(Type, RKey, SKey, ValueName="",sValue="") 
{
    HKCR    := HKEY_CLASSES_ROOT    := 0x80000000   ; http://msdn.microsoft.com/en-us/library/aa393286.aspx 
    HKCU    := HKEY_CURRENT_USER    := 0x80000001 
    HKLM    := HKEY_LOCAL_MACHINE   := 0x80000002 
    HKU     := HKEY_USERS           := 0x80000003 
    HKCC    := HKEY_CURRENT_CONFIG  := 0x80000005 
    HKDD    := HKEY_DYN_DATA        := 0x80000006 
    REG_NONE                := 0                    ; http://msdn.microsoft.com/en-us/library/ms724884.aspx
    REG_SZ                  := 1
    REG_EXPAND_SZ           := 2
    REG_BINARY              := 3
    REG_DW := REG_DWORD     := 4
    REG_DWORD_BIG_ENDIAN    := 5
    REG_LINK                := 6
    REG_MULTI_SZ            := 7
    REG_RESOURCE_LIST       := 8

    if !(RKey := %RKey%)                            ; Dynamicaly assign the RootKey
        Return false                                ; A invalid rootkey was givven
    if !(Type := %Type%)                            ; Dynamicaly assign the DataType
        Return false                                ; A invalid Type was givven
    if DllCall("Advapi32.dll\RegCreateKeyEx","uint", RKey, "Str", SKey, "uint", 0   , "uint", 0 , "uint", 0, "uint",0xF003F, "uint", 0  , "uint *", hKey) { ; create the key
        Return false                                ; Error creating or opening the key 
        }       
    If (Type == REG_SZ or Type == REG_EXPAND_SZ)
                DllCall("Advapi32.dll\RegSetValueEx", "uint", hKey, "str", ValueName, "uint", 0, "uint", Type, "str", sValue, "uint", DataSize := (StrLen(sValue) + 1)*2)   ; write string
   else If (Type == REG_BINARY) {
      size:=StrLen(sValue)//2                       ; set the data to half, one byte=2 hex digits
      VarSetCapacity(Rbin, size,0)                  ; set the capacity
      loop,% size {
         StringLeft, bin, sValue,2                  ; get the left 2digits at the time
         NumPut("0x" Bin,Rbin,A_Index-1,"Char")     ; Store the data
         StringTrimLeft, sValue, sValue, 2          ; remove the to digits
         }
      DllCall("Advapi32.dll\RegSetValueEx","uint",hKey,"str",ValueName,"uint",0,"uint",Type,Uint,&Rbin,"uint",size)   ; write string
    } Else If (Type == REG_DWORD) {
        VarSetCapacity(RDW, 4,0)                    ; setthe capacity to 4 bytes
        NumPut(sValue,RDW,0)                        ; Store the data in itData
        DllCall("Advapi32.dll\RegSetValueEx","uint",hKey,"str",ValueName,"uint",0,"uint",Type,"uint",&RDW,"uint",4)   ; write dword ; a DWORD is a 32-bit (4 byte) number
        ; RDW := "" ; clear the variable
        }
        DllCall("Advapi32.dll\RegCloseKey", "uint", hKey)   ; Release the handle of the key
    return, true
}

Я использую 64-битную версию win 7, используя 32-битный Unicode ahk 1.1.16.05 из http://ahkscript.org

Это сработало в моих тестах, по крайней мере, для того, что, я думаю, вы пытаетесь сделать.

person blackholyman    schedule 18.11.2014
comment
+1 за реальные усилия, но я не приму его, потому что он действительно не отвечает на мой вопрос. Хотя это решение, я попросил более чистое решение, чем мое (и, возможно, более эффективное). Вы вызываете Win32 API, используя DllCall, что, судя по моему POV и варианту использования, гораздо больше, чем вызов RegDelete, как это делаю я. Более того, я опасаюсь, что это может быть хуже для производительности, поскольку оно включает в себя все хакерские действия, которые DllCall делает для создания подходящего кадра стека для вызова базовой функции C API (ваше решение включает три тяжелых DllCall вместо двух моих обычных вызовов функций). - person Lorenzo Donati -- Codidact.com; 18.11.2014
comment
Ладно! Но использование dllcall никоим образом не является хакерством, это то же самое, что и использование встроенных функций, только с большим контролем. и я не могу сказать, тяжелее ли dllcall'ы, чем вызовы функций, поскольку я не искал их в исходном коде C ++, но я действительно сомневаюсь в этом. - person blackholyman; 19.11.2014
comment
хмм, я только что просмотрел его, и здесь в источнике используются те же 3 вызова, см. для себя github.com/Lexikos/AutoHotkey_L/blob/master/source/ - person blackholyman; 19.11.2014
comment
Справедливо, я должен был поставить hack в кавычки; Я имел в виду не чистый. Что касается тяжести DllCall, даже если я не смотрел на его реализацию на C ++, это средство FFI (интерфейс внешних функций): для выполнения вызова вы должны указать типы C ++ в качестве строковых аргументов, и вся эта информация должна быть переведены во что-то, что может быть вызвано на C ++, но прототип функции C ++ не может быть синтезирован во время выполнения, поэтому это, вероятно, связано с довольно неприятными хитростями под капотом. Каждая библиотека FFI, которую я видел (например, libffi, Cinvoke, LuaJIT FFI), использует для этого сборку. - person Lorenzo Donati -- Codidact.com; 19.11.2014
comment
Я действительно не так много знаю о работе dllcall, чтобы сказать больше об этом, я могу просто сказать, что тогда я не знаю более чистого способа :) но мне было весело, пытаясь - person blackholyman; 19.11.2014
comment
Ага! Как я уже сказал, я оценил усилия :-) - person Lorenzo Donati -- Codidact.com; 19.11.2014