Feeds:
Записи
Комментарии

Archive for Март 2012

Немного переименовал,может быть, не очень информативную название темы “Q&A”. В данной порции примеров приведу в основном о PowerShell V3,WMI,Active Directory и их применение.

  1. Как определить время старта и окончания Job в PowerShell V3?
  2. Как отправить почтовое сообщение на нестандартный порт в PowerShell V3?
  3. Какое новое свойство добавлено ко всем WMI объектам в PowerShell V3?
  4. Какие новые параметры появились у командлета Get-Command в PowerShell V3?
  5. Какую новую область видимости добавили в PowerShell V3?
  6. Как использовать удаленные Com объекты ?
  7. Почему Invoke-WmiMethod и [wmiclass] ведут себя по разному?
  8. Какой метод .Net используется в Set-WMIInstance для создания экземпляров?
  9. Как создать отсортированный hashtable?
  10. Как найти distinguishedname объекта по objectGuid?

1. Как определить время старта и окончания Job в PowerShell V3?

В версии PowerShell V3 добавились требуемые нам свойства,что облегчает определить продолжительность выполнения Job.

PS >$job = Start-Job {"Hello"}
PS >$job |Format-List *

PSBeginTime   :3/28/2012 10:12:29 AM
PSEndTime     :3/28/2012 10:12:31 AM

2. Как отправить почтовое сообщение на нестандартный порт в PowerShell V3?

В версии PowerShell V3 разработчики добавили параметр “Port“ для комадлета Send-MailMessage.

Пользователи,которые работают с Gmail указывают порт 587,т.к в PowerShell V2

не было параметра “Port“, требовалось использовать .Net функционал.

Send-MailMessage -SmtpServer smtp.test.com -From test@test.com -To user@user.com  `
    -Subject 'Test 587 Port' -Port 587 -Credential test@test.com -Body "Works" –UseSsl

Для версии PowerShell V2:

$EmailFrom = "test@test.com"
$EmailTo = "user@user.com"
$Subject = "Test 587 Port"
$SMTPServer = "smtp.test.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("username", "password");
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)

3. Какое новое свойство добавлено ко всем WMI объектам в PowerShell V3?

AliasProperty — свойство, определяющее новое имя существующего свойства

Здесь мы видим,что добавили новое свойство PSComputerName типа AliasProperty,

которое ссылается на значение __SERVER. Что удобно будет использовать в Advanced Functions.

PS > [wmi]"" | Get-Member

   TypeName: System.Management.ManagementObject#\

Name                MemberType    Definition
----                ----------    ----------
PSComputerName      AliasProperty PSComputerName = __SERVER

4. Какие новые параметры появились у командлета Get-Command в PowerShell V3?

В версии PowerShell V3 к командлету Get-Command добавились 4 новые параметра.

-CommandCapability<FlagsExpression<CommandCapability>>

Получает только команды с указанными возможностями. Допустимыми значениями являются Cmdlet, Script, Workflow, CIM, ScriptFile, Application, and Unknown.

Свойство  Capability команды указывает, что команда может сделать и как это можно использовать.Например, простые функции обладают возможностями Script, принимая во внимание, что расширенные функции имеют возможности Script и Cmdlet.

-ListImported

Получает только команды в текущей сессии.

Начиная с Windows PowerShell 3.0, по умолчанию, Get-Command получает все доступные команды, не ограничиваясь, только командами в текущей сессии.

-ParameterName<String[]>

Получает сведения только о командах  в сессии с указанным именем параметра.  Wildcard поддерживаются.

-ParameterType<PSTypeName[]>

Получает сведения только о командах в сессии с указанным типом параметра.Введите полное имя или часть имени типа  параметра. Wildcard поддерживаются.

С параметром CommandCapability мне не очень пока ясно. В основном,за исключением Cmdlet(но не Cmdlet,Script) и Application, можно посмотреть исходный код, свойство ScriptBlock.

Значением Unknown, тоже не очевидно.

PS > Get-Command -CommandCapability Unknown

Capability      Name                                               ModuleName
----------      ----                                               ----------
Unknown         Add-ProvisionedAppxPackage                         Dism
Unknown         Apply-WindowsUnattend                              Dism
Unknown         Begin-WebCommitDelay                               WebAdministration
Unknown         End-WebCommitDelay                                 WebAdministration
Unknown         gcai ->                                            CimCmdlets
Unknown         gcim ->                                            CimCmdlets

В основном это командлеты и альясы, но причем, как-то выборочно. Эти модули по умолчанию не импортированы  в текущую сессию. После импортирования они уже будут корректно определяться. Так же видим, gcai –> (в данном случае это альяс из модуля  CimCmdlets, но на что он ссылается, будет доступно только после импортирования модуля).

PS > Get-Command Add-ProvisionedAppxPackage

Capability      Name                                               ModuleName
----------      ----                                               ----------
Cmdlet          Add-ProvisionedAppxPackage                         Dism

PS > Get-Command gcai

Capability      Name                                               ModuleName
----------      ----                                               ----------
Cmdlet          gcai -> Get-CimAssociatedInstance

Примеры:

#Получить все команды у которых есть параметр Credential
Get-Command -ParameterName Credential

#Получить все команды у которых есть параметр Name типа String
Get-Command -ParameterName Name -ParameterType String

#Получить все команды в текущей сессии
Get-Command -ParameterName Credential

Для версии PowerShell V2 ,для поиска параметров с определенным именем, можно воспользоваться Get-Help или Get-Command.

Get-Help * -Parameter Name
Get-Command * -CommandType Cmdlet | Where {$_.Parameters["Name"]}

5. Какую новую область видимости добавили в PowerShell V3?

Using:

Указывает на локальную переменную. Используйте область видимости Using для удаленных команд, чтобы указать, что переменная находится в локальной сессии. По умолчанию, переменные в удаленных командах считаются определенными в удаленной сессии.

В версии PowerShell V2 для передачи параметра в scriptblock (можно  локально ), приходилось использовать ключевое слово param.

# Получить все процессы s* на удаленном компьютере
Invoke-Command -ComputerName localhost -ScriptBlock { param($name) Get-Process $name } -Arg "s*"

Особенно часто ошибка возникает,когда функцию определяют в локальной сессии, а хотят использовать в удаленной.

#Ошибка
Function Get-ProcName
{
    Get-Process | Foreach {$_.Name}
}

Invoke-Command -ComputerName localhost -ScriptBlock { Get-ProcName}

PS >  Invoke-Command -ComputerName localhost -ScriptBlock { Get-ProcName}
The term 'Get-ProcName' is not recognized as the name of a cmdlet, function, script file, or operable program. Check
the spelling of the name, or if a path was included, verify that the path is correct and try again.

Т.к Function это тот же scriptblock, для избежание ошибки, можно использовать множество вариантов, приведу один из:

$sb = {
    Function Get-ProcName
    {
        Get-Process | Foreach {$_.Name}
    }
    Get-ProcName
}

Invoke-Command -ComputerName localhost -ScriptBlock $sb

В версии PowerShell V3 для этого воспользуемся Using .

# Получить все процессы s* на удаленном компьютере
$name = “s*”
Invoke-Command -ComputerName localhost -ScriptBlock {Get-Process $using:name}

Using  предназначено для переменных и нет смысла использовать для функций, т.к  в конечном итоге будет исполняться scriptblock, а мы и так легко можем передать его командлету Invoke-Command.

Invoke-Command -ComputerName localhost -ScriptBlock {Invoke-Expression ${using:function:Get-ProcName}}

6. Как использовать удаленные Com объекты ?

Для создания удаленного экземпляра Com объекта воспользуемся .Net функционалом.

#ProgId например hnetcfg.fwpolicy2
[System.Activator]::CreateInstance([type]::GetTypeFromProgID("ProgId", "ComputerName"))

Зарегистрированные ProgId в системе,можно найти с помощью:

Get-WmiObject Win32_ClassicCOMClassSetting | Where {$_.ProgId} | Format-Table ProgId

7. Почему Invoke-WmiMethod и [wmiclass] ведут себя по разному?

Пример объяснения приведу на WMI классе MicrosoftDNS_ResourceRecord и методе CreateInstanceFromTextRepresentation.

Синтаксис метода CreateInstanceFromTextRepresentation:

void CreateInstanceFromTextRepresentation(

[in] string DnsServerName,

[in] string ContainerName,

[in] string TextRepresentation,

[out, ref] MicrosoftDNS_ResourceRecord &RR

);

Теперь создадим DNS запись типа TXT используя [wmiclass]:

#Имя Dns сервера
$DnsServerName = "dc1.contoso.com"

#Имя зоны , где создать запись
$ContainerName = "contoso.com"

#Текстовое представление записи, если значение содержит пробелы, заключить в двойные кавычки
$TextRepresentation = "testtxt.contoso.com IN TXT ""This is a text"""

#Создадим wmi объект
$wmi = [wmiclass]"root\MicrosoftDNS:MicrosoftDNS_ResourceRecord"

#Выполним метод CreateInstanceFromTextRepresentation
$wmi.CreateInstanceFromTextRepresentation(
    $DnsServerName,
    $ContainerName,
    $TextRepresentation
    )

Для определения,какие параметры принимает метод CreateInstanceFromTextRepresentation, можно воспользоваться:

PS > $wmi.CreateInstanceFromTextRepresentation.OverloadDefinitions
System.Management.ManagementBaseObject CreateInstanceFromTextRepresentation(
    System.String DnsServerName,
    System.String ContainerName, System.String TextRepresentation
)

С [wmiclass] проблем не возникает при создании записи. Попробуем использовать Invoke-WmiMethod и получаем ошибку.

PS > Invoke-WmiMethod -Namespace "root\MicrosoftDNS"  -Class MicrosoftDNS_ResourceRecord `
>> -Name  CreateInstanceFromTextRepresentation -argumentlist $DNSServer,$ContainerName,$TextRepresentation

Invoke-WmiMethod : Invalid parameter
At line:1 char:1
+ Invoke-WmiMethod -Namespace "root\MicrosoftDNS"  -Class MicrosoftDNS_ResourceRec ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Invoke-WmiMethod], ManagementException
    + FullyQualifiedErrorId : InvokeWMIManagementException,Microsoft.PowerShell.Commands.InvokeWmiMethod

Данная ошибка не очень информативная, синтаксис с виду правильный, но не работает. Проблема в том,что Invoke-WmiMethod  используем свой порядок входных параметров и внутри использует .Net метод GetMethodParameters.

PS > $wmi.GetMethodParameters("CreateInstanceFromTextRepresentation")

__GENUS            : 2
__CLASS            : __PARAMETERS
__SUPERCLASS       :
__DYNASTY          : __PARAMETERS
__RELPATH          :
__PROPERTY_COUNT   : 3
__DERIVATION       : {}
__SERVER           :
__NAMESPACE        :
__PATH             :
ContainerName      :
DnsServerName      :
TextRepresentation :

Здесь хорошо видно,что порядок входных параметров должен быть – ContainerName,DnsServerName,TextRepresentation. Что отличается от синтаксиса,который в msdn или при CreateInstanceFromTextRepresentation.OverloadDefinitions .

Выполним Invoke-WmiMethod  с корректным порядком входных параметров:

PS > invoke-wmimethod -Namespace "root\MicrosoftDNS"  -Class MicrosoftDNS_ResourceRecord `
>>     -Name  CreateInstanceFromTextRepresentation -argumentlist $ContainerName,$DNSServer,$TextRepresentation

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 1
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
RR               : MicrosoftDNS_TXTType.RecordData="\"This is a text\"",RecordClass=1,DnsServerName="DC1.contoso.
                   com",ContainerName="contoso.com",DomainName="contoso.com",OwnerName="testtxt.contoso.com"

Командлет Invoke-WmiMethod,  отработал, как полагается.

8. Какой метод .Net используется в Set-WMIInstance для создания экземпляров?

Данный командлет использует .Net метод  CreateInstance — ((ManagementClass) instance.InputObject).CreateInstance();. Не все классы поддерживают создание экземпляра, хотя с виду и создают его.

Приведу пример с WMI классом MicrosoftDNS_ResourceRecord

# Получим ошибку,т.к данный класс не поддерживает создания записей таким способом, используйте метод CreateInstanceFromTextRepresentation
Set-WMIInstance -Namespace root\MicrosoftDNS -class MicrosoftDNS_ResourceRecord -argument @{
    DnsServerName = $DNSServer;
    ContainerName = $Domain;
    DomainName = $Domain;
    OwnerName = $CN;
    RecordClass=1;
    RecordData = $TXT;
    TTL = 3600;
    TextRepresentation = $TextRepresentation;
    Timestamp = 0
}

PS > $wmi.CreateInstance()

__GENUS            : 2
__CLASS            : MicrosoftDNS_ResourceRecord
__SUPERCLASS       : CIM_LogicalElement
__DYNASTY          : CIM_ManagedSystemElement
__RELPATH          :
__PROPERTY_COUNT   : 14
__DERIVATION       : {CIM_LogicalElement, CIM_ManagedSystemElement}
__SERVER           :
__NAMESPACE        :
__PATH             :
Caption            :
ContainerName      :
Description        :
DnsServerName      :
DomainName         :
InstallDate        :
Name               :
OwnerName          :
RecordClass        : 1
RecordData         :
Status             :
TextRepresentation :
Timestamp          :
TTL                :
PSComputerName     :

С классом MicrosoftDNS_TXTType , таких проблем не возникает :

Set-WMIInstance -Namespace root\MicrosoftDNS -class MicrosoftDNS_TXTType -argument @{
    DnsServerName = $DNSServer;
    ContainerName = $Domain;
    DomainName = $Domain;
    OwnerName = $CN;
    RecordClass=1;
    RecordData = $TXT;
    TTL = 3600;
}

9. Как создать отсортированный hashtable?

В версии PowerShell V3 мы можем воспользоваться атрибутом [ordered].

[ordered]@{a=1;b=2;c=3}

Для версии PowerShell V2, можно воспользоваться:

1) $hast.GetEnumerator() | Sort name
2) [collections.sortedlist]$hash
3)  $OrderedList = New-Object System.Collections.Specialized.OrderedDictionary
      $OrderedList.Add("a","1")
      $OrderedList.Add("b","2")
      $OrderedList.Add("c","3")

10. Как найти distinguishedname объекта по objectGuid?

Практический пример применения это использование для определения DN из событий журнала Security.Возьмем для примера событие под номером 566(4662).

PS > Get-EventLog -LogName security -InstanceId 4662 | select -First 1 -ExpandProperty message
An operation was performed on an object.

Object:
        Object Server:          DS
        Object Type:            %{19195a5b-6da0-11d0-afd3-00c04fd930c9}
        Object Name:            %{7ac689ea-20ed-48eb-93c7-c97d5ae20fd4}
        Handle ID:              0x0

Вместо DN здесь представлен objectGuid, в оснастке EventLog отображается DN объекта.Для поиска Dn по ObjectGuid:

$guid = "7ac689ea-20ed-48eb-93c7-c97d5ae20fd4"
$bguid = -join (([GUID]$guid).ToByteArray() |% {"\{0:x}" -f $_})
$dn = ([adsisearcher]"(objectguid=$bguid)").FindOne().Properties.distinguishedname

Более наглядный пример, найдем все события с EventId 4662 и добавим новое свойство DNName  к объекту:


Get-WinEvent -FilterHashtable @{LogName="Security";Id=4662} | Foreach {
    $xevent = [xml]$_.ToXml()
    [Guid]$guid = $xevent.Event.EventData.Data | Where {$_.name -eq "ObjectName"} | Foreach {$_."#text" -replace "\W"}
    $bguid = -join ($guid.ToByteArray() |% {"\{0:x}" -f $_})
    [string]$dn = ([adsisearcher]"(objectguid=$bguid)").FindOne().Properties.distinguishedname
    $_ | Add-Member -Name DNName -Value $dn -MemberType NoteProperty -PassThru
}

 

 

Реклама

Read Full Post »

Distinguished Name:

Поиск объектов доменов Active Directory выполняется но иерархическому пути,
включающему метки имен доменов и каждого из контейнерных объектов. Полный
путь к объекту задается различающимся именем (distinguished name, DN), а имя самого
объекта — относительным различающимся именем (relative distinguished name, RDN).
Охватывая полный путь к объекту, включающий имя объекта и всех его родителей,
начиная с корня домена, различающимся имя уникально (указывает только на данный
объект) и однозначно (в каталоге нет другого объекта с данным именем)
идентифицирует объект в иерархии доменов и позволяет LDАР-клиенту
получить в каталоге сведения об этом объекте.

Relative Distinguished Name:

Относительное различающееся имя (relative distinguished name, RDN) — это
часть имени объекта, являющаяся атрибутом его самого и отличающая его от
других объектов па одном уровне иерархии имен. По умолчанию максимальная длина
относительного составного имени — 255 символов, но в схеме каталога могут
быть заданы дополнительные ограничения на атрибуты.
Например, длина атрибута cn, который часто используется в качестве
относительного составного имени, не может превышать 64 символа.
Относительные различающееся имена в Active Directory уникальны
среди потомков одного родителя, то есть в одном родительском
контейнере не могут существовать два объекта с одним RDN. Однако, два
объекта одного каталога могут иметь одинаковые относительные составные
имена и оставаться уникальным, находясь в разных родительских контейнерах.

Почти все символы могут быть использованы в Distinguished Names.
Некоторые зарезервированные символы должны быть экранированы с помощью
символа «\». В Active Directory требуется, чтобы следующие
символы были экранированы.Более подробно:

1) http://msdn.microsoft.com/en-us/library/aa366101(VS.85).aspx
2) http://www.rlmueller.net/CharactersEscaped.htm

По умолчанию в .Net по работе с Active Directory нет методов,которые
делают корректную проверку DN,RND и т.д. Поэтому воспользуемся проектом DNParser.
Сам проект написан на C# и предоставлен в виде исходных кодов.Проект совместим
с RFC 2253.

1) Скачиваем проект DNParser
http://www.codeproject.com/Articles/9788/An-RFC-2253-Compliant-Distinguished-Name-Parser

2) Разархивируем проект

3) Скомпилируем проект в виде dll библиотеки

cd $env:windir\Microsoft.NET\Framework\v2.0.50727
.\csc.exe /t:library "/out:C:\cpi.dll" "ПУТЬ:\DNParser_src\CPI.DirectoryServices\*.cs"

4) Загрузим dll в текущую сессию

 $cpi = Add-Type -Path E:\cpi.dll -PassThru

5) Посмотрим какие классы содержит данная dll

PS >  $cpi | ft fullname

FullName
--------
CPI.DirectoryServices.DN
CPI.DirectoryServices.DN+ParserState
CPI.DirectoryServices.EscapeChars
CPI.DirectoryServices.RDN
CPI.DirectoryServices.RDN+ParserState
CPI.DirectoryServices.RDNList
CPI.DirectoryServices.RDNComponent
CPI.DirectoryServices.RDNComponent+RDNValueType
CPI.DirectoryServices.RDNComponentList

Пример работы:

#Создать объект
$dn = [CPI.DirectoryServices.DN]"CN=Kazun,OU=People,DC=example,DC=com"

#Отобразить DN
PS >  "$dn"
CN=Kazun,OU=People,DC=example,DC=com
PS >  $dn.ToString()
CN=Kazun,OU=People,DC=example,DC=com
PS >  [string]$dn
CN=Kazun,OU=People,DC=example,DC=com

#Получить родительский объект
PS >  $dn.Parent.ToString()
OU=People,DC=example,DC=com
PS >  $dn.Parent.Parent.ToString()
DC=example,DC=com

#Отобразить все индивидуальные RDN
PS >  $dn.Rdns

Components
----------
{CN=Kazun}
{OU=People}
{DC=example}
{DC=com}

PS >  $dn.Rdns | Foreach {$_.ToString()}
CN=Kazun
OU=People
DC=example
DC=com

#Отобразить конкретный RDN
PS >  $dn.Rdns[1].ToString()
OU=People

#Создать объект,который содержит escape символы
$dn = [CPI.DirectoryServices.DN]"CN=Pete Everett\2a\, esq.,OU=People,DC=example,DC=com"

PS >  $dn.ToString()
CN=Pete Everett*\, esq.,OU=People,DC=example,DC=com

#Отобразить DN без escape символов
PS >  $dn.ToString("None")
CN=Pete Everett*, esq.,OU=People,DC=example,DC=com

#Отобразим все перечисления

PS >  [enum]::GetNames([CPI.DirectoryServices.EscapeChars])
None
ControlChars
SpecialChars
MultibyteChars

#Создать объект с Multibyte Chars
$dn = [CPI.DirectoryServices.DN]"CN=Антон Петрович,OU=People,DC=example,DC=com"

#Отобразить как MultibyteChars
PS >  $dn.ToString("MultibyteChars")
CN=\D0\90\D0\BD\D1\82\D0\BE\D0\BD \D0\9F\D0\B5\D1\82\D1\80\D0\BE\D0\B2\D0\B8\D1\87,OU=People,DC=example,DC=com


#Ошибка при некорректном DN
PS >  [CPI.DirectoryServices.DN]"CN=Kazun<,OU=People,DC=example,DC=com"
Cannot convert value "CN=Kazun<,OU=People,DC=example,DC=com" to type "CPI.DirectoryServices.DN". Error: "Invalid RDN: U
nquoted special character '<'
Parameter name: CN=Kazun<"
At line:1 char:27
+ [CPI.DirectoryServices.DN] <<<< "CN=Kazun<,OU=People,DC=example,DC=com"
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException
	
PS >  [CPI.DirectoryServices.DN]"CN=Kazun\<,OU=People,DC=example,DC=com"

                          CharsToEscape RDNs                                    
                          ------------- ----                                    
             ControlChars, SpecialChars {CN=Kazun\<, OU=People, DC=example,

PS >  [CPI.DirectoryServices.DN]"CN=Kazun\3C,OU=People,DC=example,DC=com"

                          CharsToEscape RDNs
                          ------------- ----
             ControlChars, SpecialChars {CN=Kazun\<, OU=People, DC=example,

Read Full Post »

Q&A

1) Как найти группы безопасности в домене?

a) Используя Active Directory module

Get-ADGroup  -Filter {GroupCategory -eq "Security"} 

Так же можно указать область действия группы.
GroupScope:
Global
DomainLocal
Universal

#Отобразить Global и Universal группы безопасности
$filter = {GroupCategory -eq "Security" -and GroupScope -eq "Global" -or GroupScope -eq "Universal"}
Get-ADGroup  -Filter $filter

b) Используя Quest.ActiveRoles.ADManagement

Get-QADGroup -GroupType Security 

Так же можно указать область действия группы.
GroupScope:
Global
DomainLocal
Universal

		
#Отобразить Global
Get-QADGroup -GroupType Security -GroupScope Global

c) Используя ADSI и LDAP запрос

Какие значения может принимать атрибут GroupType —
http://msdn.microsoft.com/en-us/library/windows/desktop/ms675935

	
Все Security группы 
(&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=2147483648))

Все Security группы с типом Global
(&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=2147483650))

Все Security группы с типом Domain Local
(&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=2147483652))

Все Security группы с типом Universal
(&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=2147483656))

Флаг 2147483648 указывает,что это группа имеет тип Security.Для поиска групп
с типом Distribution,для командлетов Get-ADGroup и Get-QADGroup задать параметр
GroupCategory равным Distribution.

	
Все Distribution группы 
(&(objectCategory=group)(!(groupType:1.2.840.113556.1.4.803:=2147483648)))

Все Distribution группы с типом Global
(&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=2)(!(groupType:1.2.840.113556.1.4.803:=2147483648)))

Все Distribution группы с типом Domain Local
(&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=4)(!(groupType:1.2.840.113556.1.4.803:=2147483648)))

Все Distribution группы с типом Universal
(&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=8)(!(groupType:1.2.840.113556.1.4.803:=2147483648)))


#Отобразим все группы с типом Security
$query = "(&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=2147483648))"
$searcher = [adsisearcher]$query
$searcher.FindAll()

2) Как можно отобразить свойство пользователя используя оснастку
Active Directory Users and Computers?

	
#Задаем путь до объекта
$path = "contoso.com/Human Resources/Human Resources Users" -split "/"
#Имя объекта
$user = "Kazun"

#GUID оснастки Active Directory Users and Computers
$guid = "{E355E538-1C2E-11D0-8C37-00C04FD8FE93}"
#Создаем ComObject
$mmc = New-Object -ComObject MMC20.Application
#Добавляем оснастку в консоль
#mmc - Add/Remove Snap-in - Active Directory Users and Computers - ADD>
$mmc.Document.SnapIns.Add($guid)

#Переходим к контайнеру где располагается объект
$view = $mmc.Document.Views.Item(1)
$view.ActiveScopeNode = $view.ListItems.Item(1)

foreach ($i in $path)
{
	$view.ActiveScopeNode = $view.ListItems | Where {$_.Name -eq $i}
}

$usernode = $mmc.Document.ActiveView.ListItems | Where {$_.Name -eq $user}
#Выбираем объект
$mmc.Document.ActiveView.Select($usernode)
#Вызываем пункт меню Properties,не зависит от локализации
$mmc.Document.ActiveView.ExecuteSelectionMenuItem("_PROPERTIES")

3) Как узнать,какие динамические параметры поддерживает командлет?

Командлет Get-Help может не всегда предоставить полную информацию по командлету.
Допустим если вы хотите посмотреть справку по командлетку Get-Content,то вы
не увидите,что есть динамические параметры,такие как — Delimiter, Encoding, Wait.
Вам придеться обратиться к справке к провайдера,где есть пункт DYNAMIC PARAMETERS,
там можно посмотреть,какие параметры и командлеты поддерживаются.

Или скажем вы набираете и получаете ошибку,что такого параметра нет:

PS >  Get-Help Get-Content -Parameter Encoding
Get-Help : No parameter matches criteria Encoding.
At line:1 char:9
+ Get-Help <<<<  Get-Content -Parameter Encoding
    + CategoryInfo          : InvalidArgument: (System.Manageme...CommandHelpInfo:ProviderCommandHelpInfo) [Get-Help],
    PSArgumentException
    + FullyQualifiedErrorId : NoParmsFound,Microsoft.PowerShell.Commands.GetHelpCommand

Но если вы воспользуетесь командлетом Get-Command,то можем убедиться,что параметр
присутствует и создается динамически.

PS >  (Get-Command Get-Content).Parameters | Format-Table -AutoSize

Key             Value
---             -----
ReadCount       System.Management.Automation.ParameterMetadata
TotalCount      System.Management.Automation.ParameterMetadata
Path            System.Management.Automation.ParameterMetadata
LiteralPath     System.Management.Automation.ParameterMetadata
Filter          System.Management.Automation.ParameterMetadata
Include         System.Management.Automation.ParameterMetadata
Exclude         System.Management.Automation.ParameterMetadata
Force           System.Management.Automation.ParameterMetadata
Credential      System.Management.Automation.ParameterMetadata
Verbose         System.Management.Automation.ParameterMetadata
Debug           System.Management.Automation.ParameterMetadata
ErrorAction     System.Management.Automation.ParameterMetadata
WarningAction   System.Management.Automation.ParameterMetadata
ErrorVariable   System.Management.Automation.ParameterMetadata
WarningVariable System.Management.Automation.ParameterMetadata
OutVariable     System.Management.Automation.ParameterMetadata
OutBuffer       System.Management.Automation.ParameterMetadata
UseTransaction  System.Management.Automation.ParameterMetadata
Delimiter       System.Management.Automation.ParameterMetadata
Wait            System.Management.Automation.ParameterMetadata
Encoding        System.Management.Automation.ParameterMetadata

Теперь убедимся,что параметр динамический(свойство IsDynamic=$true):

PS > (Get-Command Get-Content).Parameters["Encoding"]

Name            : Encoding
ParameterType   : Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding
ParameterSets   : {[__AllParameterSets, System.Management.Automation.ParameterSetMetadata]}
IsDynamic       : True
Aliases         : {}
Attributes      : {__AllParameterSets}
SwitchParameter : False

Динамические параметры создаются на лету взависимости от пути к объекту.Возьмем
на пример командлет Get-Item. Если мы будем работать с провайдером Certificate,то
у нас создается динамический параметр CodeSigningCert,а если скажем с провайдером
ActiveDirectory,то в этом случае создается уже целый набор.

Для облегчения поиска динамических параметров,один из гуру Oisin Grehan,создал
простую функцию — http://www.nivot.org/post/2010/01/18/PowerShell20AboutDynamicParameters.aspx

Приведу код этой функции и пару примеров:

function Get-DynamicParameter {
    param(        
        [string]$command
    ) 
  
    $parameters = @{}
    get-psdrive | sort -unique provider | % {
        $parameters[$_.provider.name] = gcm $command -args "$($_.name):" | % {
            $c = $_; @($_.parameters.keys) | sort | ? {
                $c.parameters[$_].isdynamic
            }
        }
    }
    $parameters    
}

PS > Get-DynamicParameter Get-Content

Name                           Value
----                           -----
Alias
FileSystem                     {Delimiter, Encoding, Wait}
Certificate
Registry
Variable
Environment
WSMan
ActiveDirectory
Function

PS > Get-DynamicParameter Get-Item

Name                           Value
----                           -----
Alias
FileSystem
Certificate                    CodeSigningCert
Registry
Variable
Environment
WSMan
ActiveDirectory                {AuthType, FormatType, GlobalCatalog, PageSize...}
Function

PS > (Get-DynamicParameter Get-Item).ActiveDirectory
AuthType
FormatType
GlobalCatalog
PageSize
Properties
Server
SizeLimit

PS. В PowerShell V3 было сделано улучшение в этом плане,теперь Get-Help
позволяет отобразить динамические параметры.

PS > Get-Help Get-Content -Parameter Wait

-Wait [<SwitchParameter>]
    Waits for contents to be appended to the file. 
	If content is appended, it returns the appended content. If the
    content has changed, it returns the entire file.

PS > Get-Help Get-Content -Parameter Encoding

-Encoding <FileSystemCmdletProviderEncoding>
    Specifies the file encoding. The default is ASCII.

    Valid values are:

    -- ASCII:  Uses the encoding for the ASCII (7-bit) character set.
    -- BigEndianUnicode:  Encodes in UTF-16 format using the big-endian byte order.
    -- Byte:   Encodes a set of characters into a sequence of bytes.
    -- String:  Uses the encoding type for a string.
    -- Unicode:  Encodes in UTF-16 format using the little-endian byte order.
    -- UTF7:   Encodes in UTF-7 format.
    -- UTF8:  Encodes in UTF-8 format.
    -- Unknown:  The encoding type is unknown or invalid. 
	The data can be treated as binary.

    Required?                    false
    Position?                    named
    Default value                ASCII
    Accept pipeline input?       false
    Accept wildcard characters?  false

4) Как определить установлен ли PowerShell?

Для этого можно запросить значение ключа (для версии 1 — V1,V2 и 3 — V3) Install:

	
	HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1 
 		Install = 1
	
	HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3 
 		Install = 1

#Для версии PowerShell V1,V2
PS > (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\PowerShell\1").Install
1

#Для версии PowerShell V3
PS > (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\PowerShell\3").Install
1

Достаточно HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1, т.к 
	V3 содержит ветку 1.

5) Какая разница между параметром Unique Select-Object,Get-Unique и Sort-Object?

В русской справке по командлету Select-Object(для PowerShell V2):

	-Unique 
	Указывает, что если несколько объектов ввода имеют одинаковые свойства и их 
	значения, то будет выбран только один из объектов.

Кто использует английскую версию PowerShell V2:

PS >  get-help Select-Object -Parameter unique

	-Unique [<SwitchParameter>]
    Specifies that if a subset of the input objects has identical properties and values, 
	only a single member of the subset will be selected.

Если мы воспользуемся параметром -Online,то значение справки будет обновлено:

PS >  get-help Select-Object -Online

	-Unique
	Specifies that if a subset of the input objects has identical properties 
	and values, only a single member of the subset will be selected.

	This parameter is case-sensitive. As a result, strings that differ only 
	in character casing are considered to be unique.

Здесь мы видим,что параметр зависит от регистра(case-sensitive),как и командлет
Get-Unique.

Командлет Sort-Object не зависит от регистра.

#Select-Object
PS >  "http","Http","HTTP" | Select-Object -Unique
http
Http
HTTP

#Sort-Object
PS >  "http","Http","HTTP" | Sort-Object -Unique
HTTP

#Get-Unique
PS >   "http","Http","HTTP" | Get-Unique
http
Http
HTTP

7) Как найти параметры,которые поддерживают wildcard или что такое globbing?

Процесс использования wildcard знаков иногда называется — globbing.Более
подробно можно посмотреть — http://en.wikipedia.org/wiki/Glob_(programming).
У параметров,которые поддерживают wildcard свойство globbing установлено в true.

Function Get-GlobbingParameter
{
	param($name = "*")
	Get-Command $name -CommandType Cmdlet | ForEach-Object {
	  $cmdlt = $_.Name
	  $_.ParameterSets | ForEach-Object {
	    $paramSet = $_.Name
	    $_.Parameters | ForEach-Object {
	      if ((Get-Help $cmdlt -param $_.Name -ea 0).Globbing) {
	          New-Object PSObject -Property @{
	            Cmdlet = $cmdlt
	            ParameterSet = $paramSet
	            Parameter = $_.Name
	          }
	        }
	      }
	    }
	  } | Format-Table ParameterSet, Parameter -AutoSize -GroupBy Cmdlet
 }
 
#Какие параметры у командлета Get-Process поддерживают wildcard
PS >  Get-GlobbingParameter Get-Process

   Cmdlet: Get-Process

ParameterSet Parameter
------------ ---------
Name         Name
Name         ComputerName
Name         Module
Name         FileVersionInfo
Id           Id
Id           ComputerName
Id           Module
Id           FileVersionInfo
InputObject  ComputerName
InputObject  Module
InputObject  FileVersionInfo
InputObject  InputObject

8) Какие assemblies были загружены в текущей сессии?

http://blogs.msdn.com/b/powershell/archive/2006/04/25/583254.aspx

9) Как удалить из локальной группы группу Everyone?

#Группа Test
$group = [ADSI]"WinNT://$env:ComputerName/Test,group"
#Список членов группы
$group.members() | 
	Foreach {$_.GetType().InvokeMember("Name","GetProperty",$null,$_,$null)}
#Удалить группу Everyone
$group.Remove("WinNT://Everyone")

Но скажем с локализованными версиями Windows не очень удобно использовать имена,
но метод Remove поддерживает SID,что облегчает задачу.

Well-known security identifiers in Windows operating systems —
http://support.microsoft.com/kb/243330

#Удалить группу Everyone(S-1-1-0) используя SID
$group.Remove("WinNT://S-1-1-0")

10) Как получить список групп в которых состоит пользовать используя WSMAN?

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

Для этого используем WMI Class Win32_UserAccount,т.к класс очень требователен
к ресурсам стоит всегда ограничить поиск.

Путь к объекту — Win32_UserAccount.Domain=»Domain»,Name=»User»

Т.к WSMAN использует URI заменить «,» на «+».

$computer = $env:COMPUTERNAME
$domain = $env:COMPUTERNAME
$user = "Kazun"

$filter = "{Object=Win32_UserAccount?Domain=$domain+Name=$user;ResultClassName=Win32_group}"
Get-WSManInstance -Enumerate -Dialect association -filter $filter -res wmicimv2/*

#Добавим параметр для удаленного компьютер
Get-WSManInstance -Enumerate -Dialect association -filter $filter -res wmicimv2/*`
	-Computer $computer

Теже действия,но используя Get-WmiObject.

$query = "Associators of {Win32_UserAccount.Domain='$domain',Name='$user'} where resultClass = Win32_Group"
Get-WmiObject -Query $query
	
#Добавим параметр для удаленного компьютер
Get-WmiObject -Query $query -ComputerName $computer

11) Почему разный результат при выполнении локального запуска и удаленного, используя
класс Win32_UserAccount в доменной среде?

При удаленном выполнении происходит «Double-Hop» запрос к Domain Controller,но
делегирование по умолчанию не настроенно.После включения делегирования,следует
задать уровень представления Delegate и передать учетные данные.Без предоставления
учетных данных будет возникать ошибка.

Get-WmiObject win32_useraccount -ComputerName RemotePC -Impersonation delegate `
	-Credential (get-credential)

12) Как скрыть кнопу Close(X) у WPF формы?

Т.к свойства для отключения кнопки «X» по умолчанию нет,требуется использовать
WinApi функции. Для запуска WPF формы,требуется использовать режим -STA.
В PowerShell ISE по умолчанию используется режим STA, в версии PowerShell V3,
можно изменить режим.

Add-Type –assemblyName PresentationFramework
Add-Type –assemblyName PresentationCore
Add-Type –assemblyName WindowsBase

$code = @"
[DllImport("user32.dll", SetLastError = true)] 
public static extern int GetWindowLong(IntPtr hWnd, int nIndex); 
[DllImport("user32.dll")] 
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
"@
Add-Type -MemberDefinition $code -Name Win32Util -Namespace System

$GWL_STYLE = -16
$WS_SYSMENU = 0x80000

[xml]$xaml = @'
     <Window
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:Name="Window"
         Title="MainWindow"
         Width="500" Height="150" Topmost="True">
     </Window>
'@
 
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$form=[Windows.Markup.XamlReader]::Load($reader)
$form_loaded =$Form.add_Loaded({
	$hwnd = (New-Object System.Windows.Interop.WindowInteropHelper($this)).Handle
 	[System.Win32Util]::SetWindowLong($hwnd, $GWL_STYLE, 
	([System.Win32Util]::GetWindowLong($hwnd, $GWL_STYLE)-band -bnot $WS_SYSMENU ))
	})
 
$form.ShowDialog() | out-null

хостинг изображений

13) Как скрыть консоль PowerShell при использовании PS2Exe?

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

Для этого нам потребуется Vbscript,который будет скрывать консоль,но в этом
случаи будет скрыта и GUI форма.Поэтому придеться использовать небольшие
изменения в PowerShell скрипте.

VbScript:
scriptName = "test.exe" 
set shell = wscript.createobject("wscript.shell")
set FSO = CreateObject("Scripting.FileSystemObject") 
scriptFolder = FSO.GetFile(Wscript.ScriptFullName).ParentFolder & "\" & scriptName
shell.run scriptFolder,0,false

Powershell:

Add-Type -AssemblyName System.Windows.Forms

$form = New-Object System.Windows.Forms.Form
$form.Add_Load({
$signature = @"
 [DllImport("user32.dll")]
 public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
"@

$showWindowAsync = Add-Type -memberDefinition $signature -name "Win32ShowWindowAsync"`
	-namespace Win32Functions -passThru
$showWindowAsync::ShowWindowAsync($form.Handle, 5) | Out-Null
$showWindowAsync::ShowWindowAsync($form.Handle, 9) | Out-Null
})
	
$form.ShowDialog()

обмен картинками Xmages.net

обмен картинками Xmages.net

14) Как применить разрешение «Apply GroupPolicy»?

#Создадим список групповых политик Имя-GUID
$gpo = @{}
[ADSI]"LDAP://CN=Policies,CN=System,DC=Contoso,DC=Com" | Foreach {
		$_.Children | Foreach {
			 $name = [string]$_.displayname
			 $path = $_.Path
			 $gpo.Add($name,$path)
		}
	}

#Теперь запретим пользователю это разрешение
$user = "Domain\UserName"
$adgpo = [ADSI]$gpo["GPOName"]

$rule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
		[System.Security.Principal.NTAccount]$user,
		"ExtendedRight",
		"Deny",
		[Guid]"edacfd8f-ffb3-11d1-b41d-00a0c968f939"
	)

$acl = $adgpo.ObjectSecurity
$acl.AddAccessRule($rule)
$adgpo.CommitChanges()

Пример:

PS > $gpo | fl

Name  : TestDenied
Value : LDAP://CN={37DBF41B-FA52-4977-B172-2F475A1684BF},CN=Policies,CN=System,DC=Contoso,DC=Com

PS > $user = "Contoso\Kazun"
PS > $adgpo = [ADSI]$gpo["TestDenied"]
......

PS > $adgpo.CommitChanges()

#Данный командлет из модуля  Quest.ActiveRoles.ADManagement
PS  Get-QADPermission TestDenied -Deny
Permissions for: contoso.com/System/Policies/{37DBF41B-FA52-4977-B172-2F475A1684BF}

Ctrl   Account                                  Rights
----   -------                                  ------
Deny   CONTOSO\kazun                            Apply Group Policy

#Командлет из модуля GroupPolicy,не дает нам нужный результат,вместо этого
# мы получаем GpoCustom. С помощью командлета Set-GPPermissions,мы  можем
# только разрешить "Apply GroupPolicy",но не запретить
PS > Get-GPPermissions -Name TestDenied -All

Trustee     : kazun
TrusteeType : User
Permission  : GpoCustom
Inherited   : False

PS > Set-GPPermissions -Name TestDenied -PermissionLevel GPOApply -TargetType user`
	-TargetName Kazun

Read Full Post »