Чтение и запись из/в реестр в VBA

Я видел эту строку на С# и пытаюсь адаптировать ее к VBA:

Microsoft.Win32.Registry.SetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR", "Start", 4,Microsoft.Win32.RegistryValueKind.DWord);

Я совершенно потерялся здесь с некоторой ошибкой:

Время выполнения: 5 - недопустимый вызов процедуры)

Когда я использую строку i_Type по умолчанию «REG_SZ» вместо «Start», я получаю ошибку, связанную с regkey:

Время выполнения - -2147024891[80070005] неверный корень

Мой код:

Dim i_RegKey As String, i_Value As String, i_Type As String
Dim myWS As Object
i_Type = "REG_SZ"  ' Optional
'access Windows scripting
Set myWS = CreateObject("WScript.Shell")
'write registry key
i_RegKey = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Start"
i_Value = "4"
i_Type = "REG_DWORD"
myWS.RegWrite i_RegKey, i_Value, i_Type

person jony    schedule 02.09.2015    source источник
comment
Эквивалент VBA должен быть .RegWrite "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Start", 4, "REG_DWORD". Но это будет работать только в том случае, если пользователь, который запускает VBA, имеет права на изменение реестра в HKEY_LOCAL_MACHINE.   -  person Axel Richter    schedule 02.09.2015
comment
Интересное чтение для вас....   -  person Siddharth Rout    schedule 02.09.2015
comment
Алекс: Я изменил свой код, чтобы отразить ваш вклад в этот вопрос. Но я все еще получаю недопустимую корневую ошибку -2147024891[80070005]. Это потому, что сценарий VBA не работает с повышенными правами? Как пользователь я имею право изменять реестр. Может быть, вместо этого я должен использовать ShellExecute для отправки команды.... ...я не в своей лиге, так что извините меня, если я говорю глупости.   -  person jony    schedule 03.09.2015
comment
Сиддарт: Я прочитал ее, и она дала мне некоторое представление о том, что я на самом деле делаю.   -  person jony    schedule 03.09.2015
comment
Сиддарт и Аксель: Думаю, теперь я понимаю, почему я получаю эту ошибку. В USBSTOR нет записи реестра с именем Start, только одна с именем Count.   -  person jony    schedule 03.09.2015
comment
Используя count, я все еще получаю ту же ошибку...   -  person jony    schedule 03.09.2015
comment
Обновление: не обращайте внимания на этот счет ... Я понял: start - это NameValue в папке USBSTOR. Поэтому, используя cmd, я набрал › /k %windir%\System32\reg.exe ADD HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR /f /v Start /t REG_DWORD /d 4 /f, C:\, 1 И, резка короче говоря: я все еще получаю сообщение об ошибке....   -  person jony    schedule 03.09.2015
comment
Аксель: Ваш ответ кажется правильным (я думаю, макросу просто не хватает необходимых разрешений).   -  person jony    schedule 03.09.2015
comment
Аксель и Сиддарт, спасибо вам обоим за помощь. Теперь этот вопрос решен.   -  person jony    schedule 03.09.2015


Ответы (3)


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

Дополнительные сведения см. на этой странице. Я мог бы просто прочитать значение ключа, используя объект WScript:

Debug.Print CreateObject("WScript.Shell").RegRead("HKLM\SYSTEM\CurrentControlSet\Services\USBSTOR\Start")

Чтобы написать (это должно работать, если у вас есть разрешения):

CreateObject("WScript.Shell").RegWrite "HKLM\SYSTEM\CurrentControlSet\Services\USBSTOR\Start", 4, "REG_DWORD"

Как я заставил его работать (поскольку мой скрипт, похоже, не имеет необходимых разрешений):

ShellExecute 0, "runas", "C:\Windows\System32\cmd.exe", "/k %windir%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Services\USBSTOR /f /v Start /t REG_DWORD /d 4", "C:\", 0

В этом последнем примере пользователю будет предложено предоставить необходимое разрешение.

PS: HKLM — это сокращение от HKEY_LOCAL_MACHINE. Все остальные имена корневых ключей имеют аналогичные сокращения, с которыми можно ознакомиться в страница, упомянутая вверху.

В качестве практического примера я опубликую свое использование этих выражений для включения/отключения запоминающего устройства USB (когда включено, когда выключено):

Sub DoUSB_Control()
    If CreateObject("WScript.Shell").RegRead("HKLM\SYSTEM\CurrentControlSet\Services\USBSTOR\Start") = 3 Then
        ShellExecute 0, "runas", "C:\Windows\System32\cmd.exe", "/k %windir%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Services\USBSTOR /f /v Start /t REG_DWORD /d 4", "C:\", 0
    Else
        ShellExecute 0, "runas", "C:\Windows\System32\cmd.exe", "/k %windir%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Services\USBSTOR /f /v Start /t REG_DWORD /d 3", "C:\", 0
    End If
End Sub
person jony    schedule 03.09.2015

После слова Start в ключе реестра должен стоять \.

person mccordscvs    schedule 22.03.2021

Вот мой общий код VBA для работы с реестром Windows.

Public Function ReadRegKeyVal(RegKeyStr As String) As Integer
 ReadRegKeyVal = CreateObject("WScript.Shell").RegRead(RegKeyStr)
End Function

Public Function RegKeyExists(RegKeyStr As String) As Boolean

  On Error GoTo ErrorHandler
  CreateObject("WScript.Shell").RegRead (RegKeyStr)
  RegKeyExists = True
  Exit Function
  
ErrorHandler:
  RegKeyExists = False
End Function

Public Sub SaveRegKey(RegKeyStr As String, RegKeyDesiredStateInt As Integer, Optional RegKeyType As String = "REG_DWORD")
 CreateObject("WScript.Shell").RegWrite RegKeyStr, RegKeyDesiredStateInt, RegKeyType
 Debug.Print "Generated --> " & RegKeyStr & "," & RegKeyDesiredStateInt & "," & RegKeyType
End Sub

Пример вызова Sub:

Public Const DWordRegKeyEnabled As Integer = 1
Public Const DWordRegKeyDisabled As Integer = 0

Public RegKeyStr As String, RegKeyLocStr As String, RegKeyNameStr As String
Public RegKeyDesiredStateInt As Integer, RegKeyCurrentStateInt As Integer
Public RegKeyFoundBool As Boolean

Public Sub SetMinMaxEnabledInExcelStatusBar()

 RegKeyDesiredStateInt = DWordRegKeyEnabled
 
 RegKeyLocStr = "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\" & Application.Version & "\Excel\StatusBar\"
 RegKeyNameStr = "MaxValue"
 RegKeyStr = RegKeyLocStr & RegKeyNameStr
 Debug.Print "RegKeyStr = " & RegKeyStr
 Call SetRegKey(RegKeyStr, RegKeyDesiredStateInt)

End Sub

Public Sub SetRegKey(RegKeyStr As String, RegKeyDesiredStateInt As Integer)
 
 RegKeyFoundBool = RegKeyExists(RegKeyStr)
 Debug.Print "RegKeyFoundBool = " & RegKeyFoundBool
 
 If RegKeyFoundBool = False Then
  Debug.Print "RegKeyFoundBool = False"
  Call SaveRegKey(RegKeyStr, RegKeyDesiredStateInt)
 Else
  Debug.Print "RegKeyFoundBool = True"
  
  RegKeyCurrentStateInt = ReadRegKeyVal(RegKeyStr)
  Debug.Print "RegKeyCurrentStateInt = " & RegKeyCurrentStateInt
 
  If RegKeyCurrentStateInt <> RegKeyDesiredStateInt Then
   Debug.Print "RegKeyCurrentStateInt <> RegKeyDesiredStateInt"
   Call SaveRegKey(RegKeyStr, RegKeyDesiredStateInt)
  Else
   Debug.Print "RegKeyCurrentStateInt = RegKeyDesiredStateInt"
  End If
 End If

End Sub
person FreeSoftwareServers    schedule 01.07.2021