Удалённый реестр.

Имеется ввиду не тот реестр который кто-то, зачем-то удалил (гад этакий :)), а просто реестр другого компьютера в том же домене. Или не в домене, главное чтоб у вас были административные права на том компьютере 🙂
С локальным реестром всё просто, cd hklm:\software\… get-itemProperty и т. д. А возможность работы с реестром другой машины в PoverShell V1 разработчики не предусмотрели. Зато они предусмотрели прекрасную возможность работы с .Net 😉

Я для себя написал пару функций упрощающих получение данных из удаленного реестра.

function Get-RegistrySubKeys([string]$Key, [string]$filter="*", [string]$computer="")
{
	if ($key -match "^(\w+)\:?[\\\/](.*)$")
	{
		$Path = $Matches[2]
		switch -regex ($matches[1]){
			'^HKLM|HKEY_LOCAL_MACHINE$' {$type = [Microsoft.Win32.RegistryHive]::LocalMachine}
			'^HKCR|HKEY_CLASSES_ROOT$' {$type = [Microsoft.Win32.RegistryHive]::ClassesRoot}
			'^HKCU|HKEY_CURRENT_USER$' {$type = [Microsoft.Win32.RegistryHive]::CurrentUser}
			'^HKCC|HKEY_CURRENT_CONFIG$' {$type = [Microsoft.Win32.RegistryHive]::CurrentConfig}
			'^HKU|HKEY_USERS$' {$type = [Microsoft.Win32.RegistryHive]::Users}
		}
		$regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($type, $computer)
		$regKey = $regKey.OpenSubKey($Path)
		$regKey.GetSubKeyNames() | ?{$_ -like $filter}
	}
}

function Get-RegistryValues([string]$Key, [string]$filter="*", [string]$computer="")
{
	if ($key -match "^(\w+)\:?[\\\/](.*)$")
	{
		$Path = $Matches[2]
		switch -regex ($matches[1]){
			'^HKLM|HKEY_LOCAL_MACHINE$' {$type = [Microsoft.Win32.RegistryHive]::LocalMachine}
			'^HKCR|HKEY_CLASSES_ROOT$' {$type = [Microsoft.Win32.RegistryHive]::ClassesRoot}
			'^HKCU|HKEY_CURRENT_USER$' {$type = [Microsoft.Win32.RegistryHive]::CurrentUser}
			'^HKCC|HKEY_CURRENT_CONFIG$' {$type = [Microsoft.Win32.RegistryHive]::CurrentConfig}
			'^HKU|HKEY_USERS$' {$type = [Microsoft.Win32.RegistryHive]::Users}
		}
		$regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($type, $computer)
		$regKey = $regKey.OpenSubKey($Path)
		$regkey.GetValueNames() | ?{$_ -like $filter} | 
select @{Name="Name"; Expression={$_}}, @{Name="Value"; Expression={$regKey.getValue($_)}}, @{Name="Type"; Expression={$regkey.GetValueKind($_)}}
	}
}

Вызываем вот так:

PS D:\PowerShell> Get-RegistryValues 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -comp $computer |ft -a

Name                       Value   Type
----                       -----   ----
AutoRestartShell               1  DWord
DefaultDomainName          Домен String
DefaultUserName             Юзер String
LegalNoticeCaption               String
LegalNoticeText                  String
PowerdownAfterShutdown         0 String

Или так:

PS D:\PowerShell> (Get-RegistryValues 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' "DefaultUserName" $computer).value
Юзер

Если вдруг понадобится поменять какое то значение, либо сделать что то еще — то либо ждите пока мне приспичит написать соответствующие функции, либо посмотрите на $regKey (класс [Microsoft.Win32.RegistryKey]) с помощью |Get-Member. Всё не так сложно как кажется 🙂

PS D:\PowerShell> $type = [m[tab].w[tab].r[tab][tab]::l[tab]
PS D:\PowerShell> $regKey = [m[tab].w[tab].r[tab][tab][tab]::o[tab]$type, "SomeComputer")
PS D:\PowerShell> $r[tab] = $r[tab].o[tab]"software\microsoft\windows\currentversion\run")
PS D:\PowerShell> $r[tab]| gm[tab]

Нет, всё таки автодополнение — квинтэссенция лени 🙂 Как же я мало набираю 🙂
Как это всё выглядит:

PS D:\PowerShell> $type = [Microsoft.Win32.RegistryHive]::LocalMachine
PS D:\PowerShell> $regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($type, "SomeComputer")
PS D:\PowerShell> $regKey = $regKey.OpenSubKey("software\microsoft\windows\currentversion\run")
PS D:\PowerShell> $regKey| Get-Member


   TypeName: Microsoft.Win32.RegistryKey

Name                      MemberType Definition
----                      ---------- ----------
Close                     Method     System.Void Close()
CreateObjRef              Method     System.Runtime.Remoting.ObjRef CreateObjRef(Type requestedType)
CreateSubKey              Method     Microsoft.Win32.RegistryKey CreateSubKey(String subkey), Microsoft.Win32.RegistryKey CreateSubKey(S... 
DeleteSubKey              Method     System.Void DeleteSubKey(String subkey), System.Void DeleteSubKey(String subkey, Boolean throwOnMis... 
DeleteSubKeyTree          Method     System.Void DeleteSubKeyTree(String subkey)
DeleteValue               Method     System.Void DeleteValue(String name), System.Void DeleteValue(String name, Boolean throwOnMissingVa... 

Кстати свойства и методы объектов тоже дополняются по табу 🙂 $regKey.c[tab]

Опубликовано в PowerShell. Комментарии к записи Удалённый реестр. отключены

Декодер

Простенькая функция для перекодировки текста из одной кодировки в другую.

function ConvertTo-Encoding ([string]$From, [string]$To){
	Begin{
		$encFrom = [System.Text.Encoding]::GetEncoding($from)
		$encTo = [System.Text.Encoding]::GetEncoding($to)
	}
	Process{
		$bytes = $encTo.GetBytes($_)
		$bytes = [System.Text.Encoding]::Convert($encFrom, $encTo, $bytes)
		$encTo.GetString($bytes)
	}
}

И на пару — для получения списка доступных кодировок:

function Get-Encodings {[System.Text.Encoding]::GetEncodings()}

Можно конечно и [s[tab].t[tab].encodi[tab]::[tab][tab] набрать, но мне показалось что в виде классической Get- функции это будет красивее 🙂 (Если у вас вдруг еще не дополнется .Net по табу — см. сюда)

Функция берет строку или массив строк на вход, и в качестве параметров указываются названия исходной и нужной кодировок (см. Get-Encodings).

Например:

PS D:\PowerShell> "Проверка" | ConvertTo-Encoding windows-1251 koi8-r
рТПЧЕТЛБ
PS D:\PowerShell> "рТПЧЕТЛБ" | ConvertTo-Encoding koi8-r windows-1251
Проверка

Ну или берём строки из файла и переправляем в другой файл:

PS D:\PowerShell> Get-Content notes.txt | ConvertTo-Encoding "windows-1251" "koi8-r" | Set-Content decoded.txt

То же самое но другими буквами 😉

PS D:\PowerShell> cat notes.txt | ConvertTo-Encoding "windows-1251" "koi8-r" > decoded.txt

Хотел приделать возможность указывать строку для перекодировки в качестве параметра (без «|»), но к сожалению такой финт ушами (несколько Parameter Set) можно сделать только в коммандлетах… В функциях — либо одно, либо другое 😦
Впрочем потом может напишу командлет где можно будет делать и так и эдак.

Опубликовано в PowerShell. 4 комментария »