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

Archive for the ‘Q&A’ Category

Нам требуется только добавлять текст в конец файла, поэтому вполне разумно будет ограничиться лишь разрешение Append Data (дозапись данных).

Для теста создадим файл и назначим требуемые права доступа:

 
#Создадим файл 
Set-Content -Path mydoc.txt -Value "Привет"

#Установим право доступа текущему пользователю Append Data & Read
$acl = Get-Acl mydoc.txt
$acl.SetAccessRuleProtection($true,$false)
$rule = New-Object Security.AccessControl.FileSystemAccessRule(
	$env:UserName,"Read,AppendData","Allow"
)
$acl.AddAccessRule($rule)
$acl | Set-Acl

#Посмотрим,что получилось
(Get-Acl mydoc.txt).Access

FileSystemRights  : AppendData, Read, Synchronize
AccessControlType : Allow
IdentityReference : PC\Kazun
IsInherited       : False
InheritanceFlags  : None
PropagationFlags  : None

Теперь попробуем добавить данные в конец файла:

  1. "Конец" >> mydoc.txt  — Out-File : Отказано в доступе по пути "C:\mydoc.txt".
  2. "Конец" | Out-File -Append mydoc.txt  — Out-File : Отказано в доступе по пути "C:\mydoc.txt".
  3. Add-Content mydoc.txt -Value "Конец" — Add-Content : Отказано в доступе по пути "C:\mydoc.txt".
  4. $file = [IO.File]::AppendText("mydoc.txt") — Исключение при вызове "AppendText" с "1" аргументами: "Отказано в доступе по пути "C:\mydoc.txt"."
  5. [IO.File]::AppendAllText("mydoc.txt","Конец") — Исключение при вызове "AppendAllText" с "2" аргументами: "Отказано в доступе по пути "C:\mydoc.txt"."
  6. $file = New-Object IO.FileStream("mydoc.txt", [IO.FileMode]::Append, [IO.FileAccess]::Write) — New-Object : Исключение при вызове ".ctor" с "3" аргументами: "Отказано в доступе по пути "C:\mydoc.txt"."

Все эти методы запрашивают более высокие разрешения (GENERIC_WRITE = 0x40000000) , нежели чем мы предоставили . Укажем более точные разрешения, для этого воспользуемся классом IO.FileStream.

 
#Текст, который мы добавим в конец файла
$text = "`r`nКонец"
#Преобразуем в массив байтов с кодировкой cp-1251
$TextBytes = [Text.Encoding]::GetEncoding("windows-1251").GetBytes($text)
#Укажем требуемые разрешения
$fs = New-Object IO.FileStream("mydoc.txt",[IO.FileMode]::Open,[Security.AccessControl.FileSystemRights]::AppendData,[IO.FileShare]::Read,8,[IO.FileOptions]::None)
#Добавим данные
$fs.Write($TextBytes,0,$TextBytes.Count)
#Закроем текущий поток
$fs.Close()

Код отработал без ошибок. Теперь посмотрим на наш результат:

 
PS С:\> Get-Content mydoc.txt
Привет
Конец

 

Более подробно с разрешениями NTFS,можете ознакомится:

Реклама

Read Full Post »

  1. Создание ускорителей(Accelerators) в PowerShell V3
  2. Поддержка V3 в Windows Server Core 2008 R2
  3. Тип bool в WMI
  4. Не очень ясное поведение Uninstall-WindowsFeature
  5. Почему Get-ChildItem в PowerShell V3 стал еще медленнее
  6. Актуальные версии помощи
  7. Печать диапазона страниц в Word
  8. Изменение поведения Register-EngineEvent при использвании источника события Exiting
  9. Получить UUID компьютера
  10. Автоматическое сохранение в  PowerShell Ise
  11. Удаление System Restore Point
  12. Проверка пароля пользователя
  13. Получить путь родительского объекта symlink
  14. Одна из проблем с GUI скриптами при переходе c PowerShell V2 на PowerShell V3

1. Создание ускорителей(Accelerators) в PowerShell V3

В своей заметке “Новинки PowerShell V3 часть 3”,я описывал ,как получить и создать ускорители в PowerShell V3.С выходом RTM версии ситуация изменилась и теперь потребуется другая техника. в связи с изменением внутренней структуры.

Для получения списков ускорителей по умолчанию:

[psobject].assembly.gettype("System.Management.Automation.TypeAccelerators")::Get

Для создания и удаления:

$acceleratorsType = [type]::gettype("System.Management.Automation.TypeAccelerators")
$acceleratorsType::Add("accelerators", $acceleratorsType)
$ArcSegment  = [type]::gettype("System.Windows.Media.ArcSegment")

# Создание
[accelerators]::Add(‘ArcSegment’,$ArcSegment)

# Убедимся,что ускоритель был добавлен
[accelerators]::get

# Удалить

[accelerators]::Remove(‘ArcSegment’)

Более подробно можно посмотреть модуль — Reflection Module 4.0 by Joel Bennett.

2. Поддержка V3 в Windows Server Core 2008 R2

Для этого требуется установить Service Pack 1 и .Net 4.0.

3. Тип bool в WMI

При использовании типа bool с WMI/CIM,можно заменить отличие от .Net.

“Boolean” в CIM / WMI может содержать 3 значения: bool:null, bool:true, bool:false.

“Boolean” в .NET содержит 2 значения: bool:true и bool:false.

4. Не очень ясное поведение Uninstall-WindowsFeature

Попробуем удалить несуществующую службу.

PS > Uninstall-WindowsFeature IamNotExists –Verbose
VERBOSE: Uninstallation started…
Uninstall-WindowsFeature : ArgumentNotValid: The role, role service, or feature name is not valid: ‘IamNotExists’. The name was not found.
At line:1 char:1
+ Uninstall-WindowsFeature IamNotExists –Verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (IamNotExists:String) [Uninstall-WindowsFeature], Exception
    + FullyQualifiedErrorId : NameDoesNotExist,Microsoft.Windows.ServerManager.Commands.RemoveWindowsFeatureCommand

Success Restart Needed Exit Code      Feature Result
——- ————— ———      —————
False   No             InvalidArgs    {}
VERBOSE: Uninstallation succeeded.

Как видим получаем ошибку,но и "VERBOSE: Uninstallation succeeded",по словам разработчиков это  не очень красивы вывод,что будет исправлено в следующем релизе.

5. Почему Get-ChildItem в PowerShell V3 стал еще медленнее

Командлет Get-ChildItem всегда не радовал своей скоростью работы,но в PowerShell V3,скорость работы может упасть в разы. Поэтому во многих случаях используют .Net или команду из cmd:

  • cmd /c dir  /s /b
  • Скажем в случае получения только подпапок,часто встречаем конструкцию вида :

Get-ChildItem folder –Recurse | Foreach {!$_.PsIsContainer} ,для ускорения,можно воспользоваться .Net GetDirectories,с одним большим НО не должно быть ссылок и при возникновении исключения  Access Denied  возникает Terminate Error ,и исполнение останавливается  ,в случае ссылок  произойдет зацикливание,а в случае с хорошо знакомой нам конструкцией такого не возникает.

(gi C:\Windows).GetDirectories("*.*","AllDirectories")

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

# В PowerShell V2 рекурсивный поиск не производится,только в текущей папке
PS >  Get-ChildItem 1.csv -recurse
    Directory: C:\Test
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        17.11.2012     11:50         70 1.csv

# В PowerShell V3 используется рекурсивный поиск
PS >  Get-ChildItem 1.csv -recurse
    Directory: C:\Test\1\2

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        17.11.2012     11:50         70 1.csv

    Directory: C:\Test
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        17.11.2012     11:50         70 1.csv

Для получения аналогичного результата в PowerShell V2  — Get-ChildItem . 1.csv –recurse

В PowerShell V3 происходит проверка, является ли элемент каталогом. Если так, получаем список содержимого в этом каталоге. Если это файл, получаем  этот файл. Если файл не существует, тогда  рекурсивно перечислим его родительский каталог в поисках файлов или дочерний каталог. Это  алгоритм рекурсии  используется в cmd.exe команда dir.

В связи с этим,будет наблюдаться падение производительности,если корневая папка отсутствует,пока не будет произведен поиск до конца.

Зато подобный синтаксис позволяет(на примере dir c:\*.txt –rec и dir C:\file.txt –rec)

  • Производить поиск в текущей папке и всех ее подпапок на наличие текстовых файлов
  • Производить поиск в конкретной папке и всех ее дочерних подпапок на наличие текстовых файлов
  • Аналогично для file.txt

Более наглядный пример с потерей производительности,можно посмотреть на — Serious Get-ChildItem performance degradation in v3 by Kirk Munro. В примере потеря скорости наблюдается в 1300 раз,если корневая папка отсутствует,пока не будет произведен поиск до конца. Поэтому рекомендуется сначала протестировать существование объекта с помощью Test-Path и уже воспользоваться Get-ChildItem.

6. Актуальные версии помощи

В связи с новой системой обновления помощи с использованием командлета Update-Help в ведено понятие версий(подробнее о обновлении about_Updatable_Help). На сайте technet можно посмотреть актуальные версии помощи — Updatable Help Status.

Updated: November 12, 2012

ModuleName Locales Version
AppLocker en-US 3.1.0.0
ClusterAwareUpdating en-US 3.1.0.0
Microsoft.WSMan.Management en-US 3.2.0.0
NetSwitchTeam en-US 3.0.0.0

Для сравнения можно воспользоваться функцикй Get-HelpInfo — PS V3 by Oisin Grehan.

PS >  get-helpinfo | ft -AutoSize

ModuleName        UICulture Installed Available
----------        --------- --------- ---------
CimCmdlets        en-US     3.0.0.0   3.0.0.0
ISE               en-US     3.0.0.0   3.0.0.0
PSScheduledJob    en-US     3.1.0.0   3.1.0.0
PSWorkflow        en-US     3.2.0.0   3.2.0.0
PSWorkflowUtility en-US     3.0.0.0   3.0.0.0

Как происходит обновление с использованием Update-Help:

  1. Finds all of the modules that are installed on your computer (in the value of the PSModulePath environment variable) plus those in the current session.
  2. Finds the online location of Help files for each module.
  3. Checks to see if you have the latest Help files for the module on your computer. 
  4. Downloads the newest Help files if you don’t have them.
  5. Unpacks the Help files (they’re in CAB files).
  6. Verifies the XML and file types for security.
  7. Installs them in the language-specific subdirectory of the module directory.

Теперь у модулей,которые можно обновить с использованием Update-Help есть свойство – HelpInfoUri,указывающее на внешний источник,который содержит требуемые файлы.

PS >  dir $pshome\*HelpInfo.xml | ft name

Name
----
Microsoft.PowerShell.Core_00000000-0000-0000-0000-000000000000_HelpInfo.xml
Microsoft.PowerShell.Diagnostics_ca046f10-ca64-4740-8ff9-2565dba61a4f_HelpInfo.xml
Microsoft.PowerShell.Host_56d66100-99a0-4ffc-a12d-eee9a6718aef_HelpInfo.xml
Microsoft.PowerShell.Management_eefcb906-b326-4e99-9f54-8b4bb6ef3c6d_HelpInfo.xml
Microsoft.PowerShell.Security_a94c8c7e-9810-47c0-b8af-65089c13a35a_HelpInfo.xml
Microsoft.PowerShell.Utility_1da87e53-152b-403e-98dc-74d7b4d63d59_HelpInfo.xml
Microsoft.WSMan.Management_766204a6-330e-4263-a7ab-46c87afc366c_HelpInfo.xml

Update-Help ищет на локальном комьютере файлы *HelpInfo.xml в которых содержится версия.

PS > gc $PSHOME\modules\PSScheduledJob\*helpinfo.xml

<?xml version="1.0" encoding="utf-8"?>
<HelpInfo xmlns="http://schemas.microsoft.com/powershell/help/2010/05">
  <HelpContentURI>http://go.microsoft.com/fwlink/?LinkID=223911</HelpContentURI>
  <SupportedUICultures>
    <UICulture>
      <UICultureName>en-US</UICultureName>
      <UICultureVersion>3.1.0.0</UICultureVersion>
    </UICulture>
  </SupportedUICultures>
</HelpInfo>

PS C:\ > dir $PSHOME\modules\PSScheduledJob\*helpinfo.xml | 
    select-xml -Namespace $HelpInfoNamespace -XPath "//helpInfo:UICulture" | foreach {$_.Node}

UICultureName                                               UICultureVersion
-------------                                               ----------------
en-US                                                       3.1.0.0

Более подробно:

7. Печать диапазона страниц в Word

Требуется распечатать диапазон страниц с 5 по 10. Основную работу выполняет метод printout с описанием параметров.Главное учесть,что требуется указать все значения до требуемого параметра(т.е в данном примере нам требуется параметр Pages,поэтому и указываем Background,Append,Range,OutputFileName,From,To,Item,Copies)

$BackGround = 1
$Append     = 0
$Range      = 4
$Item       = 0
$Copies     = 1
#5-10
$Pages      = "5-9"

$Missing = [System.Reflection.Missing]::Value
$wd = New-Object -ComObject Word.Application
$doc = $wd.Documents.Open("C:\Files\Document.docx")
$doc.printout([ref]$BackGround, [ref]$Append, [ref]$Range, [ref]$Missing,[ref]$Missing,
    [ref]$Missing,[ref]$Item,[ref]$Copies,[ref]$Pages)
$doc.Quit()

8. Изменение поведения Register-EngineEvent при использвании источника события Exiting

В PowerShell V2 появился командлет Register-EngineEvent,который создает подписку на события, создаваемые обработчиком Windows PowerShell. При задании источника событий –SourceIdentifier  Exiting, что при завершении Windows PowerShell выполнялась команда. В PowerShell V2 событие Exiting возникало,только при использовании ключевого слова exit, при нажатии на кнопку Close(“X”) событие не возникало. Данное поведение было исправлено в PowerShell V3.

Register-EngineEvent -sourceIdentifier PowerShell.Exiting -action {Get-Process | add-content processLog.txt }

9. Получить UUID компьютера

(Get-WmiObject Win32_ComputerSystemProduct).UUID

10. Автоматическое сохранение в PowerShell Ise

AutoSaveMinuteInterval

Этот параметр является новым в PowerShell ISE v3 и  используется для задания интервала для автоматического сохранения скриптов. Эта функция не сохраняет автоматически файл, но он позволяет автоматического восстановливать несохраненные файлы в случае отказа ISE или непредвиденных ошибок. Это свойство принимает значение Int16, в диапазоне -32768 до 32767. Следующий параметр установить интервал авто сохранения в одну минуту.

$psISE.Options.AutoSaveMinuteInterval = 1

Установка отрицательное значения отключит функцию автосохранения ISE и способность восстановить несохраненные файлы в случае аварии.

Подобный функционал реализуется через Restart Manager API.

Про другие опции и улучшения — PowerShell v3 ISE and ISE scripting model changes & improvements

11. Удаление System Restore Point

В PowerShell V2 появился набор командлетов для управления System Restore Point, но нет возможности удалять точки. Для этого потребуется WinApi функция SRRemoveRestorePoint.

Пример скрипта удаления точек старше 14 дней:

$point = Add-Type  -memberDefinition @"
                [DllImport("Srclient.dll")]
                public static extern int SRRemoveRestorePoint(int index);
"@ -Name Win32 -NameSpace System -PassThru

$w = (Get-Date).AddDays(-14)
$mdtc = [Management.ManagementDateTimeConverter] -as [type]

Get-ComputerRestorePoint | Where {$mdtc::ToDateTime($_.CreationTime) -lt $w} | 
    Foreach {$point::SRRemoveRestorePoint($_.SequenceNumber)

12. Проверка пароля пользователя

Проверка стандартного пароля у пользователя в Active Directory. В .Net 2.0 можем использовать:

# Запрос учетных данных
$cred = Get-Credential 
$username = $cred.username
$password = $cred.GetNetworkCredential().password

# Пробуем произвести подключение
$Domain = "LDAP://DC=contoso,DC=com"
$ds = New-Object System.DirectoryServices.DirectoryEntry($Domain,$UserName,$Password)

if ($ds.name){
    "Success"
}
else {
    "Failed"
}

В  .Net 3.5 появился метод PrincipalContext.ValidateCredentials:

$cred = Get-Credential
Add-Type -assemblyname system.DirectoryServices.accountmanagement
$DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext("Domain") 
$DS.ValidateCredentials($cred.UserName, $cred.GetNetworkCredential().password)

13. Получить путь родительского объекта symlink

Самый простой использовать команду dir в cmd.exe.

PS >  cmd /c dir D:\ /AL

Volume in drive D is Новый том

Volume Serial Number is 1AAB-1B76

Directory of D:\

18.11.2012  19:08    <SYMLINKD>     2 [D:\1]

Метод является не очень удобным,для решения воспользуемся функцией GetFinalPathNameByHandle ,код на C# заимствован у

http://chrisbensen.blogspot.ru/2010/06/getfinalpathnamebyhandle.html :

param (
    $path
)

Add-Type -MemberDefinition @"
private const int FILE_SHARE_READ = 1;
private const int FILE_SHARE_WRITE = 2;

private const int CREATION_DISPOSITION_OPEN_EXISTING = 3;
private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;

[DllImport("kernel32.dll", EntryPoint = "GetFinalPathNameByHandleW", 
    CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetFinalPathNameByHandle(IntPtr handle, 
    [In, Out] StringBuilder path, int bufLen, int flags);

[DllImport("kernel32.dll", EntryPoint = "CreateFileW", 
    CharSet = CharSet.Unicode, SetLastError = true)]
public static extern SafeFileHandle CreateFile(string lpFileName, 
    int dwDesiredAccess, int dwShareMode,
IntPtr SecurityAttributes, int dwCreationDisposition, 
    int dwFlagsAndAttributes, IntPtr hTemplateFile);

public static string GetSymbolicLinkTarget(System.IO.DirectoryInfo symlink)
{
    SafeFileHandle directoryHandle = CreateFile(symlink.FullName, 
        0, 2, System.IntPtr.Zero, 
        CREATION_DISPOSITION_OPEN_EXISTING, 
        FILE_FLAG_BACKUP_SEMANTICS, System.IntPtr.Zero);
        
    if(directoryHandle.IsInvalid)
    throw new Win32Exception(Marshal.GetLastWin32Error());

    StringBuilder path = new StringBuilder(512);
    int size = GetFinalPathNameByHandle(directoryHandle.DangerousGetHandle(),
        path, path.Capacity, 0);
    if (size<0)
    throw new Win32Exception(Marshal.GetLastWin32Error());
    if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\')
    return path.ToString().Substring(4);
    else
    return path.ToString();
}
"@ -Name Win32 -NameSpace System -UsingNamespace System.Text,`
    Microsoft.Win32.SafeHandles,System.ComponentModel

$dir = Get-Item $path 
[System.Win32]::GetSymbolicLinkTarget($dir)

14. Одна из проблем с GUI скриптами при переходе c PowerShell V2 на PowerShell V3

Для примера возьмем скрипт  — http://technet.microsoft.com/en-us/library/ff730941.aspx . Данный скрипт  работает в V2,но V3 нет. Для этого явно надо задать область(script,global):

$OKButton.Add_Click({$global:x=$objTextBox.Text;$objForm.Close()})

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

PS >  $i=0;[Regex]::Replace(‘A+B+C+D’,’\+’,{($global:i++)})

A0B1C2D

PS  >  $i=0;[Regex]::Replace(‘A+B+C+D’,’\+’,{($i++)})

A0B0C0D

 

Read Full Post »

Немного переименовал,может быть, не очень информативную название темы “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 »

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 »

Q&A

1) Как установить/получить значение свойства EnableRemoteControl у пользователя?

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

Disable 0 — Remote control is disabled.

EnableInputNotify 1 — The user of remote control has full control of
the user’s session, with the user’s permission.

EnableInputNoNotify 2 — The user of remote control has full control of
the user’s session; the user’s permission is not required.

EnableNoInputNotify 3 — The user of remote control can view the session
remotely, with the user’s permission; the remote user
cannot actively control the session.

EnableNoInputNoNotify 4 — The user of remote control can view the session
remotely, but not actively control the session;
the user’s permission is not required.

Для получения свойства EnableRemoteControl:

	$user = [ADSI]"LDAP://CN=UserName,DC=Contoso,DC=Com"
	$user.EnableRemoteControl

Для установки свойства EnableRemoteControl(для примера Disable — 0):

	$user = [ADSI]"LDAP://CN=UserName,DC=Contoso,DC=Com"
	$user.InvokeSet("EnableRemoteControl",0)
	$user.SetInfo()

2) Как отправить запрос SoAP и получить результат?

function Execute-SOAPRequest
{
	[CmdletBinding()]
	param(
		[Xml]    $SOAPRequest,
        [String] $URL,
		[String] $SOAPAction
	)

		Write-Verbose "Sending SOAP Request To Server: $URL"
        $soapWebRequest = [System.Net.WebRequest]::Create($URL)
        $soapWebRequest.Headers.Add("SOAPAction","`"$SOAPAction`"")

        $soapWebRequest.ContentType = "text/xml;charset=`"utf-8`""
        $soapWebRequest.Accept      = "text/xml"
        $soapWebRequest.Method      = "POST"

        Write-Verbose "Initiating Send."
        $requestStream = $soapWebRequest.GetRequestStream()
        $SOAPRequest.Save($requestStream)
        $requestStream.Close()

        Write-Verbose "Send Complete, Waiting For Response."
        $resp = $soapWebRequest.GetResponse()
        $responseStream = $resp.GetResponseStream()
        $soapReader = [System.IO.StreamReader]($responseStream)
        $ReturnXml = [Xml]$soapReader.ReadToEnd()
        $responseStream.Close()

        Write-Verbose "Response Received."

        $ReturnXml
}

Пример работы используя сервис Whois:

$SOAPAction = "http://www.webservicex.net/GetWhoIS"

$url = 'http://www.webservicex.net/whois.asmx'
$soap = [xml]@'
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetWhoIS xmlns="http://www.webservicex.net">
      <HostName>yandex.ru</HostName>
    </GetWhoIS>
  </soap:Body>
</soap:Envelope>
'@

$xml = Execute-SOAPRequest $soap $url $SOAPAction -Verbose

PS >  $xml.Envelope.OuterXml
#Вывод обрезан
domain:        YANDEX.RU
nserver:       ns1.yandex.ru. 213.180.193.1
nserver:       ns2.yandex.ru. 213.180.199.34
nserver:       ns4.yandex.ru. 77.88.19.60
nserver:       ns5.yandex.ru. 213.180.204.1
state:         REGISTERED, DELEGATED, VERIFIED
org:           YANDEX, LLC.
registrar:     RU-CENTER-REG-RIPN
admin-contact: https://www.nic.ru/whois
created:       1997.09.23
paid-till:     2012.10.01
free-date:     2012.11.01
source:        TCI

Last updated on 2012.02.26 22:40:46 MSK

3) Как сменить значение Apply To для пользователя для OU?

$user = "NT AUTHORITY\Authenticated Users"
$ou   = [ADSI]"LDAP://OU=OUNAMe,DC=Contoso,DC=Com"
$user = $ou.objectsecurity.access | where {$_.IdentityReference -eq $user}

$rule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
		$user.IdentityReference,
		$user.ActiveDirectoryRights,
		$user.AccessControlType,
		$user.ObjectType,
		"All",
		$user.InheritedObjectType
		)

$return = $false
$ou.objectsecurity.ModifyAccessRule("Add",$rule,[ref]$return)
if ($return)
{
	$ou.CommitChanges()
}

4) Как найти значение ip адреса компьютера используя DNS?

$filter = "(&(objectClass=organizationalunit)(name=*servers*))"
$searcher = [adsisearcher]$filter
$ous = $searcher.FindAll() | Foreach {$_.GetDirectoryEntry()}
$result = @()

foreach($ou in $ous)
{
	$ou.Children | Where {$_.SchemaClassName -eq "computer"} | Foreach {
		$comp = $_
		$ip = $null
		if ($comp.dnshostname)
		{
			try {
				$ip = [System.Net.Dns]::GetHostEntry(
					[string]$comp.dnshostname).AddressList -join ","
			}
			catch
			{
				$ip = "Not found"
			}
		}

		$result += New-Object PsObject -Property @{
						Name = [string]$comp.name
						dNSHostName = [string]$comp.dnshostname
						Ip = $ip
			}
	}
}

5) Прочитать файл,как массив символов?

В версии PowerShell V3 у комадлета Get-Content добавился параметр Raw,который
позволяет читать читать файл,как одну строку. В версии PowerShell V2 комадандлет
Get-Content возвращает массив строк.

# V3
Get-Content file.txt -Raw

В версии V2,мы можем использовать .Net метод класса Io.File — ReadAllText.
Разница между методами ReadAllText и ReadAllLines,ReadAllText — возвращает
одну строку,а метод ReadAllLines — возвращает массив строк.

# V2
[IO.File]::ReadAllText(«FullPatName»)

6) Как определить разрядность приложения 32-bit or 64-bit?

Готовую функцию можно взять на сайте:
http://www.pinvoke.net/default.aspx/kernel32.getbinarytype

7) Как узнать размер файла перед скачиванием?

$wc = new-object System.Net.WebClient
$url = "http://www.bartdesmet.net/download/ps.txt"
$wc.OpenRead($url) | Out-Null
$wc.ResponseHeaders["Content-Length"]
$url = "http://www.bartdesmet.net/download/ps.txt"
$wc = [System.Net.WebRequest]::Create($url)
$resp = $wc.GetResponse()
$resp.ContentLength

8) Есть ли Portable версия PowerShell?

Portable версию PowerShell можно бесплатно скачать на сайте:
http://site.shelltools.net/Applications/Portable_PowerShell

9) Как сконвертировать скрипт PowerShell в Exe?

Одна из целей это немного затруднить чтение вашего кода. Существует достаточно
много wrapper’s,но приведу два бесплатных решения. У всех решений большой
недостаток,требуется наличие PowerShell.

http://ps2exe.codeplex.com/
http://rkeithhill.wordpress.com/2010/09/21/make-ps1exewrapper/

10) Как управлять привязкой сетевых компонентов?

Для этого можно воспользоваться утилитой nvspbind,которую можно скачать на
сайте — http://archive.msdn.microsoft.com/nvspbind

11) Как получить массив строк после возврата от выполнения метода
DownloadString?

$str.split(«`n») или $str -split «`n»

12) Как найти события в интервале дат используя Xpath?

Значение времени используется в миллисекундах.

#Получить значение в миллисекуднах между датами
[int](new-timespan ([datetime]::Today) (get-date)).TotalMilliseconds

$filter = "*[System[TimeCreated[timediff(@SystemTime) >= 10000000] and TimeCreated[timediff(@SystemTime) <= 86400000]]]"
Get-WinEvent -FilterXPath $filter -LogName application

13) Как найти все слова в тексте начинающиеся с гласной?

[regex]::Matches($text,"(?i)\b[аеиоуыэюя]\S*") | ft value

Read Full Post »

Q&A

1) Как установить пользователю 'Deny this use permissions to logon 
    to a Remote Desktop Session Host Server'?

0 - для установки флажка
1 - для снятия флажка

$user = [ADSI]"LDAP://CN=UserName,OU=Clients,DC=contoso,DC=com"
$user.InvokeSet("AllowLogon",1)
$user.CommitChanges()

2) Как найти все пустые группы в Active Directory?

    ([adsisearcher]"(&(objectCategory=group)(!member=*))").FindAll()
    
3) Как найти все события с определенный LogonType в журнале Security?

Значения Logon Type можно посмотреть на сайте - 
    http://technet.microsoft.com/en-us/library/cc787567(v=ws.10).aspx
    
    $filter = "*[EventData[Data[@Name='LogonType']=5]]"
    Get-WinEvent -FilterXPath $filter -LogName Security
    
    #Найдем все события с опеределенным значением Logon Type и EventID
    $filter = "*[System[EventID=4624] 
        and EventData[Data[@Name='LogonType']=5]]"
    Get-WinEvent -FilterXPath $filter -LogName Security
    
    #Найдем все события с опеределенным значением Logon Type и EventID за
    #последние сутки
$time = [int](New-TimeSpan ([datetime]::Today) (get-date)).TotalMilliseconds
    $filter = "*[System[TimeCreated[timediff(@SystemTime) < $time] and 
        EventID=4624] and EventData[Data[@Name='LogonType']=5]]"
    Get-WinEvent -FilterXPath $filter -LogName Security 

Командлет Get-WinEvent работает только в системах Vista и выше,но дает 
преимущество,т.к не зависит от языка операционной системы.

4) Как создать диалог InputBox?

Пример был взят с сайта(C#) - http://www.csharp-examples.net/inputbox/ 

Function Show-InputBox($title, $promptText)
{
  $form = New-Object Windows.Forms.Form
  $label = New-Object Windows.Forms.Label
  $textBox = New-Object Windows.Forms.TextBox
  $buttonOk = New-Object Windows.Forms.Button
  $buttonCancel = New-Object Windows.Forms.Button

  $form.Text = $title
  $label.Text = $promptText

  $buttonOk.Enabled = $false
  $buttonOk.Text = "OK"
  $buttonCancel.Text = "Cancel"
  $buttonOk.DialogResult = [Windows.Forms.DialogResult]::OK
  $buttonCancel.DialogResult = [Windows.Forms.DialogResult]::Cancel

  $label.SetBounds(9, 20, 372, 13)
  $textBox.SetBounds(12, 36, 372, 20)
  $buttonOk.SetBounds(228, 72, 75, 23)
  $buttonCancel.SetBounds(309, 72, 75, 23)

  $label.AutoSize = $true
  $textBox.Anchor = $textBox.Anchor -bor [Windows.Forms.AnchorStyles]::Right
  $buttonOk.Anchor = [Windows.Forms.AnchorStyles]::Bottom -bor [Windows.Forms.AnchorStyles]::Right
  $buttonCancel.Anchor = [Windows.Forms.AnchorStyles]::Bottom -bor [Windows.Forms.AnchorStyles]::Right
  
  $textBox.Add_TextChanged({
    if($this.Text){
        $buttonOk.Enabled = $true
    }
    else {
        $buttonOk.Enabled = $false
        }
    })
  $form.ClientSize = New-Object Drawing.Size(396, 107)
  $form.Controls.Add($label)
  $form.Controls.Add($textBox)
  $form.Controls.Add($buttonOk)
  $form.Controls.Add($buttonCancel)
  $form.ClientSize = New-Object Drawing.Size([Math]::Max(300, $label.Right + 10), $form.ClientSize.Height)
  $form.FormBorderStyle = [Windows.Forms.FormBorderStyle]::FixedDialog
  $form.StartPosition = [Windows.Forms.FormStartPosition]::CenterScreen
  $form.MinimizeBox = $false
  $form.MaximizeBox = $false
  $form.AcceptButton = $buttonOk
  $form.CancelButton = $buttonCancel

  $dialogResult = $form.ShowDialog()
  New-Object PsObject -Property @{
          Value = $textBox.Text
         DialogResult =  $dialogResult
    }
}

Еще пару вариантов:
Creating a Custom Input Box - 
    http://technet.microsoft.com/en-us/library/ff730941.aspx

An Easy InputBox - http://bit.ly/xyfKSe

5) Как проверить учетные данные пользователя при подключении 
    к Active Directory?

    #Требуется минимальная версия .Net 3.5
    $domain = "contoso.com"
    $cred = Get-Credential
$pc = New-Object DirectoryServices.AccountManagement.PrincipalContext(
            "Domain", $domain) 
$isValid = $pc.ValidateCredentials(
    ($cred.UserName -replace "^\\"), $cred.GetNetworkCredential().Password)
    
    #Вариант для младших версий
    $domain = "DC=Contoso,DC=Com"
    $cred = Get-Credential

    try
    {
        New-Object System.DirectoryServices.DirectoryEntry(
            "LDAP://$domain",
            ($cred.UserName -replace "^\\"), 
            $cred.GetNetworkCredential().Password) | Out-String
    }
    catch {
        Write-Host -ForegroundColor Yellow $_
    }
    
6) Как найти индекс указанного элемента в массиве?
    
Для этого нам понадобится статическое свойство IndexOf класса Array.
    
    #V2
    $array = 1..10
    [array]::IndexOf($array,5)
    
    #V3
    #В версии V3 появилось нововведение и теперь мы можем использовать 
    #статические методы класса из экземпляра объекта
    $array = 1..10
    $array.IndexOf(5)
    
7) Как отправить пользователю сообщения на удаленный компьютер?
    
    Invoke-WmiMethod -Path Win32_Process -Name Create `
    -ArgumentList "msg * Hello" -ComputerName UserPc

8) Почему при запуске powershell параметры -file и -command 
            должны быть последними?

Данный баг был зарегистрирован на сайте http://bit.ly/xONJpz,
    особо неприятный момент,что - "Closed as Won't Fix".

9) Получаю ошибку "Unable to index into an object of type 
    System.Management.ManagementObjectCollection" ?

Ошибка возникает,что данный класс не содержит индексатора и мы не можем,
обращаться к элементам по индексу.
    
    #Пример ошибки
    $disks = gwmi win32_diskdrive
    $d = $disks[0]
    $p = $d.getrelated("win32_diskpartition")
    $p[0]
    Unable to index into an object of type 
        System.Management.ManagementObjectCollection.
    
    #Решение: привести явно к типу массив объектов
    1) @($p)[0]
    2) @($P).get(0)
    3) $p | select -f 1
    4) [array]$p = $d.getrelated("win32_diskpartition")
       $p[0]

Решения и вопрос из темы на форуме Technet(автор темы JRich, 
    I wish to thank the author of the question Justin).:

indexing problem -  http://bit.ly/yT4o2f

Также советую почитать его полезный блог,где можно подчерпнуть для себя 
много нового, jrich - http://jrich523.wordpress.com .


10) Какие потоки существуют в PowerShell?
    
    #V2
    0 - stdin
    1 - stdout
    2 - stderr
    
    #V3
    0 - stdin
    1 - stdout
    2 - stderr
    3 - warning 
    4 - verbose     
    5 - debug     
    
11) Как удалить запрещающее правило из ключа реестра?

Представим,что мы хотим удалить ключ реестра,но у него есть 
запрещающее правило, которое не позволяет нам удалить этот ключ,
но права у нас есть на изменение правил доступа.
    
    PS >  Get-Acl HKCU:\Test
    Get-Acl : Requested registry access is not allowed.
    
В этом случае нам поможет WMI  и метод SetSecurityDescriptor,который 
доступен только начиная с Vista и выше.
    
    $hkey = 2147483649 #HKCU
    $hsubkey = "Test"
    $reg = [wmiclass]"root\default:StdRegProv"
    $ace = $reg.GetSecurityDescriptor($hkey,$hsubkey).Descriptor.DACL

    $reg.psbase.Scope.Options.EnablePrivileges = $true
    $sd = ([WMIClass] "Win32_SecurityDescriptor").CreateInstance()
    $sd.ControlFlags = 0x0004
    
    #AceType=1 - Deny
    for($i=0;$i -lt $ace.length;$i++)
    {
        if($ace[$i].AceType -ne 1)
        {
            $SD.dacl += $ace[$i] 
        }
    }
    $reg.SetSecurityDescriptor($hkey,$hsubkey,$sd)
    

    #Когда мы удалили запрещаюищее правило,мы снова можем посмотреть ACL
    PS  >  Get-Acl HKCU:\Test | Out-String -Width 80

Path                       Owner                      Access
----                       -----                      ------
Microsoft.PowerShell.Co... WINPC\Александр            WINPC\Александр Allow

PS. Но лучше использовать для этого утилиты SubInAcl,SetAcl.











    
    

Read Full Post »

Q&A

1) Как найти строку в которой присутствует два слова?

"Вы заглянули в Интернет-магазин кормов для собак и кошек" -match "(?=.+кошек)(?=.+собак)"

Более подробно про регулярные выражения,Вы можете прочитать в блоге Василия Гусева — http://xaegr.wordpress.com/category/regular-expressions/

2) Как получить удаленный доступ к 64-x реестру из 32-x битного процесса?
Для этого требуется,чтобы на компьюетер был установлен .Net 4.0.

Скрипт «Access 64bit registry values from 32bit powershell» — использует Com объекты(не требует .Net 4.0, но и сложен).

Shay Levy написал два модуля для V3 и V2:
V2 — http://archive.msdn.microsoft.com/PSRemoteRegistry
V3 — http://psrr.codeplex.com/

3) Как установить изображение учетной записи?

$code = @"
[DllImport("shell32.dll", EntryPoint = "#262", CharSet = CharSet.Unicode, PreserveSig = false)]  
public static extern void SetUserTile(string username, int notneeded, string picturefilename);
"@

Add-Type -MemberDefinition $code -Name UserTile -Namespace System

#Применение
[UserTile]::SetUserTile("domain\username","picturefilename.jpg")

4) Как установить максимальный строк действия пароля неограничен?

Set-ADDefaultDomainPasswordPolicy contoso.com -MaxPasswordAge ([timespan]::MinValue)

5) Как экранировать символ \ в фильтре командлетов Active Directory ?

Для экранирования символа \ — используйте escape-последовательность \5c. Про остальные символы — можно прочитать в стандартной справке — about_ActiveDirectory_Filter

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

Get-ADUser -Filter "ProfilePath -like '\5c\5ceserver1\5cProfiles$\5c*'" -Properties profilepath

6) Как очистить корзину для конкретного пользователя или для всех?

#xp/2003
$shell = New-Object –ComObject Shell.Application
$rb = $shell.NameSpace(0xA).Self
$rb.InvokeVerb("Empty Recycle &Bin")

#Vista и выше
$shell = New-Object –ComObject Shell.Application
$shell.NameSpace(0xA).Items() | Remove-Item -Recurse

#Для всех пользователей
#Recycle - Xp/2003/Vista
#$Recycle.Bin - 7
$disks = Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3"

foreach ($disk in $disks)
{
	$rbpathold = "$($disk.DeviceID)\Recycle"
	$rbpathnew = "$($disk.DeviceID)\`$Recycle.Bin"
	
	if (Test-Path $rbpathold)
	{
		Remove-Item $rbpathold -Force -Recurse
	}
	
	if (Test-Path $rbpathnew)
	{
		Remove-Item $rbpathnew -Force -Recurse 
	}
}

7) Как установить значение параметров во вкладе «Совместимость» для приложения?

Для управления параметрами воспользуемся реестром.

#Для конкретного пользователя,путь в реестре 
"HKCU:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"

#Для всех пользователей,путь в реестре
"HKLM:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"

Name - путь к приложению
Type - REG_SZ
Value - параметры(через пробел)

Run in 256 colors - 256COLOR
Run in 640 x 480 screen resolution - 640X480
Disable visual themes - DISABLETHEMES
Disable Desktop composition - DISABLEDWM 
Disable display scaling on hight DPI settings - HIGHDPIAWARE
Run this  program run as an administrator - RUNASADMIN

Установить для приложения все эти параметры - "256COLOR 640X480 DISABLETHEMES DISABLEDWM HIGHDPIAWARE RUNASADMIN" 
Set-ItemProperty -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" -Name "C:\Program\calcX.exe" -Value "256COLOR 640X480 DISABLETHEMES DISABLEDWM HIGHDPIAWARE RUNASADMIN" 

Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" -Name "C:\Program\calcX.exe" -Value "256COLOR 640X480 DISABLETHEMES DISABLEDWM HIGHDPIAWARE RUNASADMIN" 

Чтобы параметры вступили в силу требуется перезагрузка или рестарт explorer.

8) Как установить свойство AutomaticManagedPage у класса Win32_ComputerSystem?

Для установки AutomaticManagedPage, требуется ,чтобы PowerShell был запущен в режиме STA и с правами администратора.

Start-Process powershell -Arg "-STA" -Verb RunAs

$System = Get-WmiObject Win32_ComputerSystem 
$System.AutomaticManagedPagefile = $False
$System.Put()

Read Full Post »

Older Posts »