none
Как добраться до реестра машины, не входящей в домен? RRS feed

  • Вопрос

  • Есть домен 2008 в лесу 2008. И есть несколько компьютеров (Windows XP, Windows7), не входящих в домен. Нужно на этих компьютерах получить/поменять одно из значений в реестре. Работать буду с машины, которая входит в домен. Имя и пароль пользователя с административными правами на недоменных машинах знаю. Сам вхожу в группу "Администраторы домена". Для достижения цели написал вот такой скрипт:

    Computers = Array("192.168.5.10") 
    strPassword = "xxxxxx" 
    
    For Each strComputer In Computers 
    	Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator") 
    	Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, "root\cimv2", "COMP\user", strPassword) 
    
    	Set ShellObj = WScript.CreateObject("WScript.Shell") 
    	Set FSO = WScript.CreateObject("Scripting.FilesystemObject") 
    	Set NetObj = WScript.CreateObject("WScript.Network") 
    	WinDir = FSO.GetSpecialFolder(0) 
    	SysDir = FSO.GetSpecialFolder(1) 
    	On Error Resume Next 
    	RegistryKeyPath="HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\" 
    	RegKeyValue = ShellObj.RegRead(RegistryKeyPath & "WUServer")
    	WScript.Echo RegKeyValue
    
    Next 

    Запускаю скрипт... получаю Access denied. При этом, я уверен, что на машине с адресом 192.168.5.10 (которая носит имя COMP) есть пользователь user с паролем xxxxxx.

    Если вместо данных машины COMP подставляю адрес, имя машины, имя пользователя DOMAIN\user и пароль этого юзера - всё работает. Скрипт возвращает значение переменной WUServer...

    Что я делаю не так?


    Сергей Панченко


    • Изменено Daemon-GTC 11 мая 2012 г. 10:29

Ответы

  • Вы желаете работать с реестром удалённой станции, а метод RegRead объекта WScript.Shell "умеет" работать только с локальным реестром.

    Пример работающего сценария:

    Const HKLM = &H80000002
    Computers = Array("192.168.5.10")
    strPassword = "xxxx"
    RegKeyPath = "SOFTWARE\Policies\Microsoft\Windows\Installer"
    strValueName = "EnableAdminTSRemote"
    For Each strComputer In Computers
    	strUser = strComputer & "\Администратор"
    	Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator") 
    	Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, "root\default:StdRegProv", strUser, strPassword)
    	Set objReg = objSWbemServices.Get("StdRegProv")
    	objReg.GetDWORDValue HKLM, RegKeyPath, strValueName, RegKeyValue
    	WScript.Echo strComputer & " = " & RegKeyValue
    Next
    WScript.Quit 0

    Примечание.
    В примере выполняется чтение значения типа DWORD. Для чтения значения другого типа используйте соответствующий метод класса StdRegProv.
    • Изменено DmitriiV 11 мая 2012 г. 11:01
    • Помечено в качестве ответа Daemon-GTC 12 мая 2012 г. 9:19
  • В итоге, всё получилось.

    Во-первых, нужно было использовать методы класса StdRegProv: SetDWORDValue, GetDWORDValue, DeleteDWORDValue (и аналоги для String, Multistring и т.д.).

    Во-вторых, ключик HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\ForceGuest должен быть в 1.

    В-третьих, служба удалённого реестра на целевой машине должна быть запущена.

    Привожу рабочий скрипт, прописывающий некоторые параметры WSUS на удалённой машине:

    Const HKLM = &H80000002 Const WSUSPATH1 = "SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\" Const WSUSPATH2 = "SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\" Computers = Array("COMP1", "COMP2") strPassword = "xxxxxx" For Each strComputer In Computers strUser = strComputer & "\user" Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator") Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, "\root\default", strUser, strPassword) Set objReg = objSWbemServices.Get("StdRegProv") 'Удаляем ненужные значения call objReg.DeleteValue(HKLM, WSUSPATH1, "SUSClientID") call objReg.DeleteValue(HKLM, WSUSPATH1, "PingID") call objReg.DeleteValue(HKLM, WSUSPATH1, "AccountDomainSID") 'Добавляем/изменяем нужные call objReg.SetStringValue(HKLM, WSUSPATH2, "TargetGroup", "Машины вне домена") call objReg.SetDWORDValue (HKLM, WSUSPATH2, "TargetGroupEnabled", 1) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "AUOptions", 4) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "ScheduledInstallDay", 0) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "ScheduledInstallTime", 11) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "NoAutoRebootWithLoggedOnUsers", 1) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "NoAutoUpdate", 0) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "UseWUServer", 1)

    'Для отладки выводим установленное значение

    ' call objReg.GetStringValue(HKLM, WSUSPATH2, "TargetGroup", RegKeyValue)

    ' WScript.Echo RegKeyValue Next



    Сергей Панченко


    • Помечено в качестве ответа Daemon-GTC 12 мая 2012 г. 9:19
    • Изменено Daemon-GTC 12 мая 2012 г. 9:20

Все ответы

  • Вы желаете работать с реестром удалённой станции, а метод RegRead объекта WScript.Shell "умеет" работать только с локальным реестром.

    Пример работающего сценария:

    Const HKLM = &H80000002
    Computers = Array("192.168.5.10")
    strPassword = "xxxx"
    RegKeyPath = "SOFTWARE\Policies\Microsoft\Windows\Installer"
    strValueName = "EnableAdminTSRemote"
    For Each strComputer In Computers
    	strUser = strComputer & "\Администратор"
    	Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator") 
    	Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, "root\default:StdRegProv", strUser, strPassword)
    	Set objReg = objSWbemServices.Get("StdRegProv")
    	objReg.GetDWORDValue HKLM, RegKeyPath, strValueName, RegKeyValue
    	WScript.Echo strComputer & " = " & RegKeyValue
    Next
    WScript.Quit 0

    Примечание.
    В примере выполняется чтение значения типа DWORD. Для чтения значения другого типа используйте соответствующий метод класса StdRegProv.
    • Изменено DmitriiV 11 мая 2012 г. 11:01
    • Помечено в качестве ответа Daemon-GTC 12 мая 2012 г. 9:19
  • В общем, ошибку понял. На недоменной машине было выставлено HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\ForceGuest = 1.

    Исправил в 0, скрипт стал читать значения риджистри. Теперь хочу поменять. Модифицировал скрипт так:

    Computers = Array("192.168.5.10") 
    strPassword = "хххххх" 
    
    For Each strComputer In Computers 
    	Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator") 
    	Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, "\root\cim2", "COMP\user", strPassword) 
    
    	Set ShellObj = WScript.CreateObject("WScript.Shell") 
    	Set FSO = WScript.CreateObject("Scripting.FilesystemObject") 
    	Set NetObj = WScript.CreateObject("WScript.Network") 
    	WinDir = FSO.GetSpecialFolder(0) 
    	SysDir = FSO.GetSpecialFolder(1) 
    
    'Читаем имеющееся значение ключа
    	RegistryKeyPath="HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\" 
    	RegKeyValue = ShellObj.RegRead(RegistryKeyPath & "WUServer")
    	WScript.Echo RegKeyValue
    'Прочитали успешно, получили значение.
    ' Удаляем старую регистрацию на WSUS
    	RegistryKeyPath1="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\" 
    
    	call ShellObj.RegDelete(RegistryKeyPath1 & "SUSClientID")
    'А вот тут получаем облом: "Ошибка при удалении" 80070005.
    
    Next

    И что я опять неверно сделал?


    Сергей Панченко

  • 1. Код ошибки свидетельствует об отказе в доступе к объекту. Наиболее вероятная причина - недостаточный уровень полномочий для выполнения операции (например, на Win 7 действие может быть заблокировано средствами UAC, т.к. для правки реестра обычно требуются повышенные привилегии).

    2. Скажите, с реестром какой станции Вы пытаетесь экспериментировать: локальной или удалённой?


    • Изменено DmitriiV 12 мая 2012 г. 5:49
  • В итоге, всё получилось.

    Во-первых, нужно было использовать методы класса StdRegProv: SetDWORDValue, GetDWORDValue, DeleteDWORDValue (и аналоги для String, Multistring и т.д.).

    Во-вторых, ключик HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\ForceGuest должен быть в 1.

    В-третьих, служба удалённого реестра на целевой машине должна быть запущена.

    Привожу рабочий скрипт, прописывающий некоторые параметры WSUS на удалённой машине:

    Const HKLM = &H80000002 Const WSUSPATH1 = "SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\" Const WSUSPATH2 = "SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\" Computers = Array("COMP1", "COMP2") strPassword = "xxxxxx" For Each strComputer In Computers strUser = strComputer & "\user" Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator") Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, "\root\default", strUser, strPassword) Set objReg = objSWbemServices.Get("StdRegProv") 'Удаляем ненужные значения call objReg.DeleteValue(HKLM, WSUSPATH1, "SUSClientID") call objReg.DeleteValue(HKLM, WSUSPATH1, "PingID") call objReg.DeleteValue(HKLM, WSUSPATH1, "AccountDomainSID") 'Добавляем/изменяем нужные call objReg.SetStringValue(HKLM, WSUSPATH2, "TargetGroup", "Машины вне домена") call objReg.SetDWORDValue (HKLM, WSUSPATH2, "TargetGroupEnabled", 1) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "AUOptions", 4) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "ScheduledInstallDay", 0) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "ScheduledInstallTime", 11) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "NoAutoRebootWithLoggedOnUsers", 1) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "NoAutoUpdate", 0) call objReg.SetDWORDValue(HKLM, WSUSPATH2 & "AU\", "UseWUServer", 1)

    'Для отладки выводим установленное значение

    ' call objReg.GetStringValue(HKLM, WSUSPATH2, "TargetGroup", RegKeyValue)

    ' WScript.Echo RegKeyValue Next



    Сергей Панченко


    • Помечено в качестве ответа Daemon-GTC 12 мая 2012 г. 9:19
    • Изменено Daemon-GTC 12 мая 2012 г. 9:20
  • Daemon-GTC, только сейчас заметил ошибку, допущенную в собственном примере:

    Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, "root\default:StdRegProv", strUser, strPassword)

    Имя класса после имени WMI-пространства здесь указывать не нужно.

    Должно быть так:

    Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, "root\default", strUser, strPassword)
    • Изменено DmitriiV 12 мая 2012 г. 9:05
  • Имя класса после имени WMI-пространства здесь указывать не нужно.


    А что будет, если указать? Работает и так, и сяк.

    Сергей Панченко


    • Изменено Daemon-GTC 12 мая 2012 г. 9:20
  • В данном случае - ничего (как это явствует из опыта). Видимо, обработчик запроса игнорирует всё, что следует за разделителем (:), стоящим после имени WMI-пространства (DEFAULT).
    Однако, вообще говоря, результаты обращения к объектам по пути ROOT\DEFAULT и по пути ROOT\DEFAULT:STDREGPROV будут разными.
    В первом случае будет получена ссылка на объект типа SWbemServicesEx, а во втором - на объект SWbemObjectEx. Эти объекты имеют разное функциональное назначение, а следовательно, разные наборы методов и свойств.