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

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.

    

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()

Q&A

1) Как программно отключить монитор?

$signature = @"
    [DllImport("User32.DLL")]
    public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
"@

$type = Add-Type -MemberDefinition $signature -Name Win32 -Namespace SendMessage -PassThru
$type::SendMessage(0xFFFF,0x0112,0xF170,2)

2) Какие ярлыки соответствуют данному exe?

Get-WmiObject Win32_ShortcutFile  -Filter "Target='C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'"

3) Какой класс использовать для работы с большими целыми числами?

В .Net 4.0 есть структура BigInteger Structure для работы с большими числами. По умолчанию в PowerShell V2 не включена поддержка .Net 4.0, для включение – http://tfl09.blogspot.com/2010/08/using-newer-versions-of-net-with.html

4) Как сделать побитовый сдвиг?

V2 : Используйте скрипт http://huddledmasses.org/powershell-needs-shift-operators/

V3 : Появились встроенные операторы для побитового сдвига, -shl и -shr

5) Как просто сгенерировать пароль?

Function Get-Password {
        param($number=1,$length=10)
        $rand = New-Object System.Random
        for($i=0;$i -lt $number;$i++)
        {
                -join (1..$length | ForEach { [char]$rand.next(33,127) })
        }
}

PS > Get-Password -number 5 -length 15
1'K[jc_K8fLV4V:
,Y;u*r)u!9-,lr$
v$m6@`-I:gpY0yG
4~YC1MNlMe)0KB]
XrX4oIh|7X~0".9

6) Как работать с путями больше 256 символов?

Модуль – http://huddledmasses.org/long-path-module-experimental-io/

Также можно использовать часть возможностей cmd.exe используя префикс \\?\ – подробнее можно узнать в статье Naming Files, Paths, and Namespaces.

7) Как преобразовать пароль в Base64 для использование в атрибуте unicodepwd?

VBS – http://www.rlmueller.net/Programs/PwdToBase64.txt
Вручную – http://www.oszone.net/13669/Active-Directory-UnicodePwd-AD-LDS

И в одну строчку на PowerShell, двойные кавычки обязательные.

[convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes(‘”xZy$132#q!”‘))

1)      Использование ComObject – WMPlayer.OCX.7

$cds = (New-Object -ComObject "WMPlayer.OCX.7").cdromcollection
#Количество cd-rom's в системе
$cds.count
#Какой букве,соответсвует номер в коллекции
0..($cds.count-1) | select @{n="ItemCount";e={$_}},@{n="driveSpecifier";e={$cds.item($_).driveSpecifier}}
#Извлечь первый в номере коллекции
$cds.item(0).eject()
#Для закрытия 
$cds.item(0).eject()
#Извлечь по букве
$cds.getByDriveSpecifier("X").Eject()
#Для закрытия
$cds.getByDriveSpecifier("X").Eject()


Пример вывода
PS >  0..($cds.count-1) | select @{n="ItemCount";e={$_}},@{n="driveSpecifier";e={$cds.item($_).driveSpecifier}}

                                                 ItemCount driveSpecifier
                                                 --------- --------------
                                                         0 D:
                                                         1 I:

PS >  $cds.item(1).eject()
PS >  $cds.getByDriveSpecifier("I").Eject()

2)      Использование ComObject – Shell.Application

Данная библиотека хорошо документирована , подробнее можно прочитать на сайте – http://msdn.microsoft.com/en-us/library/bb774094(v=vs.85).aspx

Константы можно также посмотреть на сайте – ShellSpecialFolderConstants enumeration, нам потребуется только одна константа:

ssfDRIVES

0×11 (17). My Computer—the virtual folder that contains everything on the local computer: storage devices, printers, and Control Panel. This folder can also contain mapped network drives.

PS. Глагола для закрытия CD-ROM’a я не нашел.

$shellapp = New-Object -comObject Shell.Application
#Количество cd-rom's в системе
$shellapp.Namespace(17).Items() | Where {$_.Type -eq "CD Drive"}
#Какие действия можно выполнять над объектом,используя Verb
#Основная проблема,что зависит от локализации системы
$shellapp.Namespace(17).ParseName("X:").Verbs()
#Для англоязычной Windows - глагол Eject
$shellapp.Namespace(17).ParseName("X:").InvokeVerb("Eject")

Пример вывода:

PS > $shellapp.Namespace(17).Items() | Where {$_.Type -eq "CD Drive"}
Application  : System.__ComObject
Parent       : System.__ComObject
Name         : BD-ROM Drive (D:)
Path         : D:\
GetLink      : 
GetFolder    : System.__ComObject
IsLink       : False
IsFolder     : True
IsFileSystem : True
IsBrowsable  : False
ModifyDate   : 30.12.1899 0:00:00
Size         : 0
Type         : CD Drive

Application  : System.__ComObject
Parent       : System.__ComObject
Name         : DVD RW Drive (I:)
Path         : I:\
GetLink      : 
GetFolder    : System.__ComObject
IsLink       : False
IsFolder     : True
IsFileSystem : True
IsBrowsable  : False
ModifyDate   : 30.12.1899 0:00:00
Size         : 0
Type         : CD Drive


PS >  $shellapp.Namespace(17).ParseName("I:")


Application  : System.__ComObject
Parent       : System.__ComObject
Name         : DVD RW Drive (I:)
Path         : I:\
GetLink      :
GetFolder    : System.__ComObject
IsLink       : False
IsFolder     : True
IsFileSystem : True
IsBrowsable  : False
ModifyDate   : 30.12.1899 0:00:00
Size         : 0
Type         : CD Drive

PS > $shellapp.Namespace(17).ParseName("I:").Verbs() | Select Name

Name
----
&Open

Burn &to disc
Scan selected files with Anti&Vir
Form&at...
E&ject
&Copy
Create &shortcut
P&roperties

PS > $shellapp.Namespace(17).ParseName("I:").InvokeVerb("Eject")

3)      Использование WinAPI – mciSendString

Документация по функции, можно посмотреть на msdn – mciSendString , определение данной функции для C#, можно посмотреть на pInvoke – mciSendString.

#Количество cd-rom's в системе
Get-WmiObject Win32_CDROMDrive

$code = @"
[DllImport("winmm.dll")]
public static extern Int32 mciSendString(String command, StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);
"@
$cdrom = Add-Type -MemberDefinition $code -Name System -Namespace CDROM -UsingNamespace System.Text -PassThru 
#OPEN
$cdrom::mciSendString("open X: type CDAudio alias driveX", $null, 0, [IntPtr]::Zero)
$cdrom::mciSendString("set driveX door open", $null, 0, [IntPtr]::Zero)
#CLOSE
$cdrom::mciSendString("open X: type CDAudio alias driveI", $null, 0, [IntPtr]::Zero)
$cdrom::mciSendString("set driveX door closed", $null, 0, [IntPtr]::Zero)


Пример вывода:

PS > Get-WmiObject Win32_CDROMDrive | Select Caption,Drive

Caption                                                     Drive
-------                                                     -----
Optiarc DVD RW AD-7203A ATA Device                          I:
WDKVYZW YJ85M3OT SCSI CdRom Device                          D:

PS > $drive = "I"
PS > $string = "open $drive`: type CDAudio alias drive$drive"
PS > $cdrom::mciSendString($string, $null, 0, [IntPtr]::Zero)
0
PS > $setstring = "set drive$drive door open"
PS > $cdrom::mciSendString($setstring, $null, 0, [IntPtr]::Zero)
0
PS > $clsstring = "set drive$drive door closed"
PS > $cdrom::mciSendString($clsstring, $null, 0, [IntPtr]::Zero)
0

4)      Использование других WinAPi функций

Пример класса для C# был взят с сайта – http://stackoverflow.com/questions/1449410/programatically-ejecting-and-retracting-the-cd-drive-in-vb-net-or-c-sharp за авторством C# гуру Jon Skeet. Здесь лишь небольшая косметическая правка и адаптировано для PowerShell.

$code = @"
using System; 
using System.IO; 
using System.Runtime.InteropServices; 

namespace  System
{
	public class CDROM
	{ 
	    const int OPEN_EXISTING = 3; 
	    const uint GENERIC_READ = 0x80000000; 
	    const uint GENERIC_WRITE = 0x40000000; 
	    const uint IOCTL_STORAGE_EJECT_MEDIA = 2967560; 
	 
	    [DllImport("kernel32")] 
	    private static extern IntPtr CreateFile 
	        (string filename, uint desiredAccess,  
	         uint shareMode, IntPtr securityAttributes, 
	         int creationDisposition, int flagsAndAttributes,  
	         IntPtr templateFile); 
	 
	    [DllImport("kernel32")] 
	    private static extern int DeviceIoControl 
	        (IntPtr deviceHandle, uint ioControlCode,  
	         IntPtr inBuffer, int inBufferSize, 
	         IntPtr outBuffer, int outBufferSize,  
	         ref int bytesReturned, IntPtr overlapped); 
	 
	    [DllImport("kernel32")] 
	    private static extern int CloseHandle(IntPtr handle); 
	 
	    public static void EjectMedia(char driveLetter) 
	    { 
	        string path = "\\\\.\\" + driveLetter + ":"; 
	        IntPtr handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0,  
	                                   IntPtr.Zero, OPEN_EXISTING, 0, 
	                                   IntPtr.Zero); 
	        if ((long) handle == -1) 
	        { 
	            throw new IOException("Unable to open drive " + driveLetter); 
	        } 
	        int dummy = 0; 
	        DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0,  
	                        IntPtr.Zero, 0, ref dummy, IntPtr.Zero); 
	        CloseHandle(handle); 
	    } 
	}
}
"@
Add-Type -TypeDefinition $code 

Пример вывода:

PS > Get-WmiObject Win32_CDROMDrive | Select Caption,Drive

Caption                                                     Drive
-------                                                     -----
Optiarc DVD RW AD-7203A ATA Device                          I:
WDKVYZW YJ85M3OT SCSI CdRom Device                          D:

PS >  [CDROM]::EjectMedia("I")

По умолчанию в Windows нет консольного приложения для управления ABE. Более подробно про ABE,можно узнать в блоге Алексея Горбунова и ABE Graphical User Interface , во второй ссылке подробно рассказывается, какие API используются для управления ABE.

Утилита командной строки для управления ABE(более подробно смотри во второй ссылке):

ABECMD – http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=17510

В статье про “управление кэшированием общих папок”, весь функционал скрипта уже был реализован, поэтому достаточно было добавить только флаг FLAGS_ACCESS_BASED_DIRECTORY_ENUM, который равняется 0×0800.

$code = @"
public enum CacheType
{
	Manual    = 0x00,
	Documents = 0x10,
	Programs  = 0x20,
	None      = 0x30,
}

public const int FLAGS_ACCESS_BASED_DIRECTORY_ENUM = 0x0800;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHARE_INFO_1005
{
    public uint shi1005_flags;
}

[DllImport("Netapi32", CharSet=CharSet.Auto)]
    public static extern int NetApiBufferFree(IntPtr Buffer);

[DllImport("Netapi32.dll", SetLastError=true)]
public static extern int NetShareGetInfo(
    [MarshalAs(UnmanagedType.LPWStr)] string serverName,
    [MarshalAs(UnmanagedType.LPWStr)] string netName,
    Int32 level,
    out IntPtr bufPtr );

[DllImport("Netapi32.dll", CharSet = CharSet.Unicode)]
public static extern uint NetShareSetInfo(string servername, string netname,
    uint level, ref SHARE_INFO_1005 buf, out uint paramerror);
"@

Add-Type -MemberDefinition $code -name Share -namespace System

function Get-ShareABE
{
	param(
			[parameter(Mandatory=$true,ValueFromPipeline=$true,
			ValueFromPipelineByPropertyName=$true)]
			[Alias("Name")]
			[string]$ShareName
		)

	process {
		$bufptr = [IntPtr]::Zero
		$return = [Share]::NetShareGetInfo($null,$ShareName,1005,[ref]$bufptr)
		if($return -eq 0)
		{
			$Enable = "Disabled"
			$str1005 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($bufptr,[Share+SHARE_INFO_1005])
			$value = $str1005.shi1005_flags
			if ($value -band [Share]::FLAGS_ACCESS_BASED_DIRECTORY_ENUM)
			{
				$Enable = "Enabled"
			}
			Get-WmiObject Win32_Share -Filter "Name='$ShareName'" | Select-Object Name,`
				Path,Description,@{n="ABE";e={$Enable}},@{n="Flag";e={$value}}
		}
		else
		{
			Write-Host (net helpmsg $return)
		}
		[Share]::NetApiBufferFree($bufptr) | Out-Null
	}
}

function Set-ShareABE
{
	param(
		[parameter(Mandatory=$true,Position=0)]
		[string]$ShareName,
		[parameter(Mandatory=$true,Position=1)]
		[ValidateSet("Enable", "Disable")]
		[string]$Type
	)

	$paramerror = 0

	if ($Type -eq "Disable")
	{
		$flag = (Get-ShareABE -ShareName $ShareName).Flag -bxor [Share]::FLAGS_ACCESS_BASED_DIRECTORY_ENUM
	}
	else
	{
		$flag = [Share]::FLAGS_ACCESS_BASED_DIRECTORY_ENUM
	}
	$buf = New-Object Share+SHARE_INFO_1005 -Property @{shi1005_flags = $flag}
	$return = [Share]::NetShareSetInfo($null,$ShareName,1005,[ref]$buf,[ref]$paramerror)
	if ($return)
	{
		Write-Host (net helpmsg $return)
	}
}

Применение функции Get-ShareABE:

PS > Get-ShareABE doesnotexists
 This shared resource does not exist.
PS > Get-ShareABE Test

Name        : TEST
Path        : C:\TEST
Description :
ABE         : Disabled
Flag        : 0

PS > Get-WmiObject Win32_Share | Get-ShareABE

Name        : ADMIN$
Path        : C:\Windows
Description : Remote Admin
ABE         : Disabled
Flag        : 0

Name        : C$
Path        : C:\
Description : Default share
ABE         : Disabled
Flag        : 0

Name        : IPC$
Path        :
Description : Remote IPC
ABE         : Disabled
Flag        : 0

Name        : TEST
Path        : C:\TEST
Description :
ABE         : Disabled
Flag        : 0

Применение функции Set-ShareABE:

PS > Get-ShareABE Test

Name        : TEST
Path        : C:\TEST
Description :
ABE         : Disabled
Flag        : 0

PS > Set-ShareABE Test -Type Enable
PS > Get-ShareABE Test

Name        : TEST
Path        : C:\TEST
Description :
ABE         : Enabled
Flag        : 2048

PS > Set-ShareABE Test -Type Disable
PS > Get-ShareABE Test

Name        : TEST
Path        : C:\TEST
Description :
ABE         : Disabled
Flag        : 0

Q&A

1) Как получить номер недели в месяце (1-5)?

Function Get-WeekOfMonth
{
    param ([datetime]$date = (Get-Date)) 

    $beginningOfMonth = New-Object DateTime($date.Year,$date.Month,1)  

    while ($date.Date.AddDays(1).DayOfWeek -ne (Get-Culture).DateTimeFormat.FirstDayOfWeek)
    {
        $date = $date.AddDays(1)
    } 

    [int]([Math]::Truncate($date.Subtract($beginningOfMonth).TotalDays  / 7) + 1)
}  

2) Как отключить “X” в консоли PowerShell?

$code = @"
[DllImport("user32.dll")]
public static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags);

[DllImport("User32")]
public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
"@

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

$hMenu = [HideClose]::GetSystemMenu((gps -id $pid).MainWindowHandle, $false)
[HideClose]::DeleteMenu($hMenu,0xF060, 0)

3) Как используя метод XMLDocument.Save() сохранить данные в переменную?

$mem = New-Object IO.MemoryStream
$writer = New-Object IO.StreamWriter($mem)
$xml.Save($writer)
$var = [System.Text.Encoding]::Default.GetString($mem.toarray())
$var

Или

$xml.Save(($mem=New-Object IO.MemoryStream))
$var=[System.Text.Encoding]::Default.GetString($mem.toarray())

4) Какой метод класса System.Net.DNS лучше использовать?

Для разрешение имен в прямом и обратном направлении,лучше всего использовать статический метод GetHostEntry(IPAddress) и GetHostEntry(String).

5) Как отключить positional parameters?

V2:
param ($badparam,$i1,$i2)
if ($badparam) {“Вы не ввели обязательные параметры”}

V3: [CmdletBinding(PositionalBinding=$false)]

Текущие командлеты, не очень хорошо справляются с данной задачей, поэтому эффективным решением – использовать .Net. На одном из форумов, был найден скрипт на C#, который полностью решал эту задачу. Переводить скрипт полностью на PowerShell, я не вижу смысла, хотя код транслируется очень легко. Оригинал скрипта, можно посмотреть  – http://bit.ly/uR1bUL . Я сделал лишь небольшую обвязку в виде функции.


Function Get-EndTokenFile
{
	<#
	    .SYNOPSIS 
	    Читает последние N строк из файла.

	    .DESCRIPTION
	    Читаем последние N строк из файла с заданной кодировкой(по умолчанию ASCII)
		по заданному пути,который является обязательным параметром.
		
		.PARAMETER Path
		Путь к файлу(полное имя файла).Подстановочные знаки не разрешены.
		
		.PARAMETER Encoding
		Задает тип кодировки, используемой в файле. Пример: "Unicode", "UTF7", "UTF8", 
		"UTF32", "ASCII", "BigEndianUnicode", "Default","OEM","Windows-1251". 
		По умолчанию используется кодировка "ASCII".
		
		.PARAMETER ReadCount
		Количество выводимых строк.По умолчанию используется 1.
		
		.PARAMETER Separator
		Указывает разделитель для строк. По умолчанию используется разделитель `r`n.
		
		.PARAMETER Verbose
		Отображает подробные сведения о действиях, выполняемых командой.
		
		.PARAMETER WhatIf
		Описывает, что произойдет при выполнении команды, без ее фактического выполнения.

	     .EXAMPLE
	     C:\PS> Get-EndTokenFile -Path C:\file.txt
		 
		 .EXAMPLE
	     C:\PS> Get-EndTokenFile -Path C:\file.txt -WhatIf
		 
		 .EXAMPLE
	     C:\PS> Get-EndTokenFile -Path C:\file.txt -ReadCount 2
		 
		 .EXAMPLE
	     C:\PS> Get-EndTokenFile -Path C:\file.txt -Encoding Unicode
		 
		 .EXAMPLE
	     C:\PS> Get-ChildItem C:\Files\*.txt | Get-EndTokenFile 
	#>


	[CmdletBinding(SupportsShouldProcess=$true)]
	param (
			[Parameter(
					Mandatory=$true,
            		ValueFromPipeline=$true,
					ValueFromPipelineByPropertyName=$true
					)]
			[Alias("FullName")]
			[string]
			$Path,
			[string]$Encoding = "ASCII",
			[Int64]$ReadCount = 1,
			[string]$Separator = "`r`n"
		)
			
begin {
$code = @"
public static string ReadEndTokens(string path, Int64 numberOfTokens, Encoding encoding, string tokenSeparator) { 
 
    int sizeOfChar = encoding.GetByteCount("\n"); 
    byte[] buffer = encoding.GetBytes(tokenSeparator); 
 
 
    using (FileStream fs = new FileStream(path, FileMode.Open)) { 
        Int64 tokenCount = 0; 
        Int64 endPosition = fs.Length / sizeOfChar; 
 
        for (Int64 position = sizeOfChar; position < endPosition; position += sizeOfChar) { 
            fs.Seek(-position, SeekOrigin.End); 
            fs.Read(buffer, 0, buffer.Length); 
 
            if (encoding.GetString(buffer) == tokenSeparator) { 
                tokenCount++; 
                if (tokenCount == numberOfTokens) { 
                    byte[] returnBuffer = new byte[fs.Length - fs.Position]; 
                    fs.Read(returnBuffer, 0, returnBuffer.Length); 
                    return encoding.GetString(returnBuffer); 
                } 
            } 
        } 
 
        // handle case where number of tokens in file is less than numberOfTokens 
        fs.Seek(0, SeekOrigin.Begin); 
        buffer = new byte[fs.Length]; 
        fs.Read(buffer, 0, buffer.Length); 
        return encoding.GetString(buffer); 
    } 
} 
"@

	Add-Type -MemberDefinition $code -Name ReadLong -Namespace System -UsingNamespace System.Text,System.IO
}
process {
	if ($pscmdlet.ShouldProcess("Производим операцию чтения файла '$Path'."))
	{
		if (Test-Path $path)
		{
			[ReadLong]::ReadEndTokens($Path,$ReadCount,[System.Text.Encoding]::GetEncoding($Encoding),$Separator)
		}
		else
		{
			Write-Error "Файл $Path не найден."
		}
	}
	}
}


Управление процессом кэширования для общих папок с помощью PowerShell

Был задан вопрос: ”Как управлять процессом кэширования с помощью PowerShell?”. Для управления кэшированием в Windows, существует встроенная утилита net,у которой есть ключ /cache. Данный ключ принимает следующие параметры:

PS >  net share /?
	[/CACHE:Manual | Documents | Programs | BranchCache | None]

Для просмотра состояния кэширования для общей папки, можно воспользоваться, следующим синтаксисом:

Syntax: net share sharename

PS >  net share C$
Share name        C$
Path              C:\
Remark            Стандартный общий ресурс
Maximum users     No limit
Users
Caching           Manual caching of documents
Permission        Все, FULL

The command completed successfully.

На мой взгляд, утилита net,предоставляет простой и удобный способ управления – параметром кэширования. И именно его предпочтительней использовать в своих скриптах.

Попробуем реализовать данный функционал, используя стандартные WinApi функции. Для этого нам потребуется две функции и одна структура:

1)      NetShareGetInfo  – для получения состояние кэширования;

2)      NetShareSetInfo  – для установки параметра кэширования;
3)      _SHARE_INFO_1005– содержит информацию о кэшировании;

Структура _SHARE_INFO_1005 , поддерживает большое количество битовых флагов, но нам потребуется только флаг CSC_MASK, более подробно смотрите по ссылке выше. Определение данных функций для C#,можно посмотреть на сайтеPinvoke.
 

$code = @"
public enum CacheType
{
	Manual    = 0x00,
	Documents = 0x10,
	Programs  = 0x20,
	None      = 0x30,
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHARE_INFO_1005
{
    public uint shi1005_flags;
}

[DllImport("Netapi32", CharSet=CharSet.Auto)]
    public static extern int NetApiBufferFree(IntPtr Buffer);

[DllImport("Netapi32.dll", SetLastError=true)]
public static extern int NetShareGetInfo(
    [MarshalAs(UnmanagedType.LPWStr)] string serverName,
    [MarshalAs(UnmanagedType.LPWStr)] string netName,
    Int32 level,
    out IntPtr bufPtr );

[DllImport("Netapi32.dll", CharSet = CharSet.Unicode)]
public static extern uint NetShareSetInfo(string servername, string netname,
    uint level, ref SHARE_INFO_1005 buf, out uint paramerror);
"@

Add-Type -MemberDefinition $code -name Share -namespace System

function Get-ShareCache
{
	param(
			[parameter(Mandatory=$true,ValueFromPipeline=$true,
			ValueFromPipelineByPropertyName=$true)]
			[Alias("Name")]
			[string]$ShareName
		)

	process {
		$bufptr = [IntPtr]::Zero
		$return = [Share]::NetShareGetInfo($null,$ShareName,1005,[ref]$bufptr)
		if($return -eq 0)
		{
			$str1005 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($bufptr,[Share+SHARE_INFO_1005])
			$value = $str1005.shi1005_flags
			Get-WmiObject Win32_Share -Filter "Name='$ShareName'" | Select-Object Name,`
				Path,Description,@{n="Caching";e={
				1,2,256,512,1024,2048,4096 | Foreach {
					if ($value -band $_)
					{
						$value -= $_
					}
				}
				$value -as [Share+CacheType]}}
		}
		else
		{
			Write-Host (net helpmsg $return)
		}
		[Share]::NetApiBufferFree($bufptr) | Out-Null
	}
}

function Set-ShareCache
{
	param(
		[parameter(Mandatory=$true,Position=0)]
		[string]$ShareName,
		[parameter(Mandatory=$true,Position=1)]
		[ValidateSet("Manual", "Documents", "Programs","None")]
		[string]$CacheType
	)

	$paramerror = 0
	$buf = New-Object Share+SHARE_INFO_1005 -Property @{shi1005_flags = [Share+CacheType]::$CacheType}
	$return = [Share]::NetShareSetInfo($null,$ShareName,1005,[ref]$buf,[ref]$paramerror)
	if ($return)
	{
		Write-Host (net helpmsg $return)
	}
}

Использование.

Применение функции Get-ShareCache:

PS >  Get-ShareCache doesnotexists
 This shared resource does not exist.

PS >  Get-ShareCache C$ | Format-Table -Auto

Name Path Description              Caching
---- ---- -----------              -------
C$   C:\  Стандартный общий ресурс  Manual

PS >  Get-WmiObject Win32_Share | Get-ShareCache | Format-Table -Auto

Name   Path                              Description               Caching
----   ----                              -----------               -------
ADMIN$ C:\Windows                        Удаленный Admin            Manual
C$     C:\                               Стандартный общий ресурс   Manual
IPC$                                     Удаленный IPC              Manual
print$ C:\Windows\system32\spool\drivers Драйверы принтеров         Manual

Применение функции Set-ShareCache:

PS >  Get-ShareCache test | Format-Table -Auto

Name Path    Description Caching
---- ----    ----------- -------
Test C:\Test              Manual

PS >  Set-ShareCache -ShareName Test -CacheType Documents
PS >  Get-ShareCache test | Format-Table -Auto

Name Path    Description   Caching
---- ----    -----------   -------
Test C:\Test             Documents

PS >  Set-ShareCache -ShareName Test -CacheType Programs
PS >  "Test" | Get-ShareCache | Format-Table -Auto

Name Path    Description  Caching
---- ----    -----------  -------
Test C:\Test             Programs

Новинки PowerShell V3 часть 6

Поговорим еще немного о новых возможностях:

1)      Возможность установки и обновления файлов помощи, используя  командлет Update-Help

До выпуска PowerShell V3 CTP1,для получения помощи, вы использовали командлет Get-Help. Когда в документации находили ошибки или прочие неточности, нельзя было обновить справку для получения последних изменений. Для этого, приходилось использовать Get-Help command -Online и возможно данный недочет будет исправлен. В версии V3,данную проблему решает командлет Update-Help.

В PowerShell V3 CTP1,по умолчанию отсутствует стандартная справка, но она есть в cab файле.

Требуемые операции для обновления:

  1. Скачать cab файл –  PowerShell V3 CTP1
  2. Распаковываем(expand,7-Zip,Winrar,etc)
  3. Update-Help –SourcePath C:\folderexpand\HelpContent -UICulture en-Us,ru-RU –Force

Более подробно, можно прочитать в блоге – http://tfl09.blogspot.com/2011/09/powershell-v3-and-updateable-help.html

2)      Появилась новая встроенная переменная – $PSDefaultParameterValues

Определяет значения по умолчанию для параметров и  расширенных функций. $PSDefaultParameterValues  -  это hash table, где ключ содержит  cmdlet:param и в поле value находится стандартное значение.

PS > $PSDefaultParameterValues | gm
   TypeName: System.Management.Automation.DefaultParameterDictionary

Name                 MemberType            Definition
----                 ----------            ----------
Add                  Method                System.Void Add(System.Object key, System.Object value)
ChangeSinceLastCheck Method                bool ChangeSinceLastCheck()
Clear                Method                System.Void Clear()
Clone                Method                System.Object Clone()
Contains             Method                bool Contains(System.Object key)
ContainsKey          Method                bool ContainsKey(System.Object key)
ContainsValue        Method                bool ContainsValue(System.Object value)
CopyTo               Method                System.Void CopyTo(array array, int arrayIndex), System.Void CopyTo(array...
Equals               Method                bool Equals(System.Object obj)
GetEnumerator        Method                System.Collections.IDictionaryEnumerator GetEnumerator(), System.Collecti...
GetHashCode          Method                int GetHashCode()
GetObjectData        Method                System.Void GetObjectData(System.Runtime.Serialization.SerializationInfo ...
GetType              Method                type GetType()
OnDeserialization    Method                System.Void OnDeserialization(System.Object sender)
Remove               Method                System.Void Remove(System.Object key)
ToString             Method                string ToString()
Item                 ParameterizedProperty System.Object Item(System.Object key) {get;set;}
Count                Property              System.Int32 Count {get;}
IsFixedSize          Property              System.Boolean IsFixedSize {get;}
IsReadOnly           Property              System.Boolean IsReadOnly {get;}
IsSynchronized       Property              System.Boolean IsSynchronized {get;}
Keys                 Property              System.Collections.ICollection Keys {get;}
SyncRoot             Property              System.Object SyncRoot {get;}
Values               Property              System.Collections.ICollection Values {get;}

Синтаксис:

$PSDefaultParameterValues["Disabled"]=$true | $false
$PSDefaultParameterValues=@{"<CmdletName>:<ParameterName>"="<Value>"}
$PSDefaultParameterValues=@{"<CmdletName>:<ParameterName>"={<ScriptBlock>}}

$PSDefaultParameterValues включена по умолчанию (Disabled=$false).

Подстановочные знаки разрешены в <CmdletName> и <ParameterName>.

Значение по умолчанию может быть объект или script block. В случае если передается script block:

  1. (script block) – сначала PowerShell вычисляет значение выражения и используется, как параметр.
  2. {script block} – если требуется передать script block,напрямую, заключается в {}.

Примеры использования:

#Отключить использование $PSDefaultParameterValues
PS > $PSDefaultParameterValues["Disabled"]=$true

#Перезапишем стандартное значение -Path="." командлета Get-ChildItem

PS > $PSDefaultParameterValues=@{"Get-ChildItem:Path"="C:\"}
PS > Get-ChildItem


    Directory: C:\


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----         9/19/2011   8:16 PM            PerfLogs
d----         10/5/2011   2:19 AM            poshv3
d-r--         9/20/2011   9:48 PM            Program Files
d----         8/25/2011   1:00 PM            Program Files (x86)
d-r--         9/19/2011   8:14 PM            Users
d----         9/19/2011   8:16 PM            Windows

#Передадим script block,без вычисления выражения,используя двойные {}
PS >  $PSDefaultParameterValues=@{ "Invoke-Command:ScriptBlock"={{Get-Service | Where Status -EQ Running}} }
PS > Invoke-Command

Status   Name               DisplayName
------   ----               -----------
Running  BFE                Base Filtering Engine
Running  CryptSvc           Cryptographic Services
Running  DcomLaunch         DCOM Server Process Launcher
Running  DeviceAssociati... Device Association Service
Running  Dhcp               DHCP Client
Running  DPS                Diagnostic Policy Service
Running  EventLog           Windows Event Log
Running  EventSystem        COM+ Event System
Running  FontCache          Windows Font Cache Service
Running  gpsvc              Group Policy Client
Running  iphlpsvc           IP Helper
Running  LanmanServer       Server
Running  LanmanWorkstation  Workstation
Running  lmhosts            TCP/IP NetBIOS Helper
Running  LSM                Local Session Manager
Running  MpsSvc             Windows Firewall
Running  MSDTC              Distributed Transaction Coordinator

При обновлении справки, более подробно, можно узнать:

Get-Help about_preference_variables

http://powertoe.wordpress.com/2011/09/15/powershell-default-parameters-in-v-3-0/

Так же для работы, можно воспользоваться парой функций – http://poshcode.org/2990

Введение подобного функционала, может создать проблемы в безопасности и осложнение в отладке скриптов. Так что, аккуратнее, используйте данный функционал.

3)      Использование атрибутов.

Я не буду переписывать материал книги, а приведу ссылку на книгу Mastering PowerShell под авторством Tobias Weltner  и конкретно раздел, где рассказывается про данный функционал – Variable Management: Behind the Scenes. После прочтение, вам станет понятным, как использовать свойство Attributes – и как его применять для V1 и V2. Так же в разделе даны, какие  классы атрибутов бывают и , какие параметры они принимают.

Один из MVP по PowerShell Joel Bennett,написал функцию, где облегчается добавления данных атрибутов, к переменным. Приведу исходный код функции (http://poshcode.org/2991) :

function Protect-Variable {
param(
[Parameter(Mandatory=$true,Position=0)][String]$Name, [Int]$Scope = 1,
[Parameter(ParameterSetName="ValidateScriptBlock")][ScriptBlock]$ScriptBlock,
[Parameter(ParameterSetName="ValidateCount")][Int]$MinCount,
[Parameter(ParameterSetName="ValidateCount")][Int]$MaxCount,
[Parameter(ParameterSetName="ValidateLength")][Int]$MinLength,
[Parameter(ParameterSetName="ValidateLength")][Int]$MaxLength,
[Parameter(ParameterSetName="ValidatePattern")][Regex]$Pattern,
[Parameter(ParameterSetName="ValidateRange")][Int]$MinValue,
[Parameter(ParameterSetName="ValidateRange")][Int]$MaxValue,
[Parameter(ParameterSetName="ValidateSet")][String[]]$Set,
[Parameter(ParameterSetName="ValidateNotNull")][Switch]$NotNull,
[Parameter(ParameterSetName="ValidateNotNullOrEmpty")][Switch]$NotEmpty
)
   $Variable = Get-Variable $Name -Scope 1

   if($ScriptBlock) {
      $Attribute = new-object System.Management.Automation.ValidateScriptAttribute $ScriptBlock
      $Variable.Attributes.Add($Attribute)
   }
   if($MinCount -or $MaxCount) {
      if(!$MinCount) { $MinCount = [Int]::MinValue }
      if(!$MaxCount) { $MaxCount = [Int]::MaxValue }
      $Attribute = new-object System.Management.Automation.ValidateCountAttribute $MinCount, $MaxCount
      $Variable.Attributes.Add($Attribute)
   }
   if($MinLength -or $MaxLength) {
      $Attribute = new-object System.Management.Automation.ValidateLengthAttribute $MinLength, $MaxLength
      $Variable.Attributes.Add($Attribute)
   }
   if($Pattern) {
      $Attribute = new-object System.Management.Automation.ValidatePatternAttribute $Pattern
      $Variable.Attributes.Add($Attribute)
   }
   if($MinValue -or $MaxValue) {
      $Attribute = new-object System.Management.Automation.ValidateRangeAttribute $MinValue, $MaxValue
      $Variable.Attributes.Add($Attribute)
   }
   if($Set) {
      $Attribute = new-object System.Management.Automation.ValidateSetAttribute $Set
      $Variable.Attributes.Add($Attribute)
   }
   if($NotNull) {
      $Attribute = new-object System.Management.Automation.ValidateNotNullAttribute
      $Variable.Attributes.Add($Attribute)
   }
   if($NotEmpty) {
      $Attribute = new-object System.Management.Automation.ValidateNotNullOrEmptyAttribute
      $Variable.Attributes.Add($Attribute)
   }
}

Как использовать:

#Добавим атрибут ValidateRange для переменной test,которая принимает значение в интервале 10-100.
PS >  $test = 10
PS >  Protect-Variable test -MinValue 10 -MaxValue 100

Остальные примеры, можно посмотреть в книге, а также описание и использование – этих атрибутов, можно посмотреть в справке по расширенным функциям.

Get-Help about_functions_advanced_parameters

Что изменилось в V3,теперь данные атрибуты можно добавить, указав впереди переменной (возможно при объявлении).

#Добавим атрибут ValidateRange для переменной test,которая принимает значение в интервале 10-100.
PS > [ValidateRange(10,100)]$test = 42
PS > $test = 101
The variable cannot be validated because the value 101 is not a valid value for the test variable.
At line:1 char:1
+ $test = 101
+ ~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ValidationMetadataException
    + FullyQualifiedErrorId : ValidateSetFailure

#Добавим атрибут ValidateSet для переменной test,которая может принимать значение X,Y,Z.
PS > [ValidateSet("X","Y","Z")]$test = "X"
PS > $test = "hello"
The variable cannot be validated because the value hello is not a valid value for the test variable.
At line:1 char:1
+ $test = "hello"
+ ~~~~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ValidationMetadataException
    + FullyQualifiedErrorId : ValidateSetFailure

Как мы видим, теперь работа с атрибутами упростилась.

Новинки PowerShell V3 часть 5

Радостные новости, теперь  PowerShell V3 CTP1,  доступен для Windows 7 Service Pack 1 и Windows Server 2008 R2 SP1. Так что у кого нет возможности скачать Windows 8 Developer Preview, можете скачать по ссылке – http://www.microsoft.com/download/en/details.aspx?id=27548 . Перечислять возможности не буду, их можно будет посмотреть по ссылке выше.

Поговорим немного теперь про нововведения:

1)      Доступен параметр  -Stream у следующих командлетов:

  • Add-Content
  • Clear-Content
  • Get-Content
  • Get-Item
  • Out-String
  • Remove-Item
  • Set-Content

Когда скрипты скачиваются через Internet Explorer, Outlook и т.д, создается альтернативный поток данных NTFS,которые добавляют Zone Identifier. Поток Zone.Identifier это поток, содержащий текстовые данные. Он содержит внутри себя следующие строчки:

[ZoneTransfer]

ZoneId=3

Параметр ZoneId с числом означает зону, откуда прибыл файл на компьютер. Допустимы следующие значения:

  • 0 — локальный компьютер
  • 1 — интранет
  • 2 — доверенный источник
  • 3 — интернет
  • 4 — недоверенный источник

Более подробно можно узнать на сайте – http://hex.pp.ua/Zone.Identifier.php.

Посмотреть stream Zone Identifier ,можно с помощью notepad:


Notepad script.ps1:Zone.Identifier

Так же можно воспользоваться утилитой Stream от SysInternals – http://technet.microsoft.com/ru-RU/sysinternals/bb897440.aspx


C:\>streams script.ps1

Streams v1.56 - Enumerate alternate NTFS data streams

Copyright (C) 1999-2007 Mark Russinovich

Sysinternals - www.sysinternals.com

C:\script.ps1::Zone.Identifier:$DATA 26

Как удалить этот stream,можно прочитать в блоге – http://www.hanselman.com/blog/RemovingSecurityFromDownloadedPowerShellScriptsWithAlternativeDataStreams.aspx

Для PowerShell V3 :


#Получить все потоки

Get-Item script.ps1 -Stream *

Stream         Length

------         ------

:$DATA           4

Zone.Identifier  3

#Удалим поток Zone.Identifier

Remove-Item script.ps1 -Stream Zone.Identifier

Для работы с потоками в версии V2,можно посмотреть статью – http://thepowershellguy.com/blogs/posh/archive/2007/01/27/powershell-accessing-alternative-data-streams-of-files-on-an-ntfs-volume.aspx

2)      У командлета Get-Content ,два новых параметра Raw и Tail.

3)      Посмотреть изменения, которые произошли с параметрами комадлетов версии V2 и V3, для основных модулей.Shay Levy написал скрипт и выложил в подробном ввиде – http://www.powershellmagazine.com/2011/09/15/how-to-find-out-whats-new-in-powershell-vnext/

4)      Так же хорошей новостью, что у командлета  Out-GriedView, появился параметр Passthru.


Get-ChildItem | Out-GridView -PassThru | Select Name

Теперь вы можете выбрать, кликнув по заданному полю и нажать OK.Вы отфильтруете требуевые вам поля от остальных полей и передать дальше по конвейеру, получив более наглядный вывод.

Подробнее можно посмотреть – http://powertoe.wordpress.com/2011/09/19/out-gridview-now-has-a-passthru-parameter/

5)      У комадлета Tee-Object, добавился параметр –Append.


Get-ChildItem  | Tee-Object -FilePath result.txt | Select Name

Get-Process | Tee-Object -FilePath result.txt -Append | Select Name

6)      PowerShell Ise – доступен Add-On Команды и Help,которые реализуются с помощью командлета Show-Command. Подробнее – http://www.jonathanmedd.net/2011/09/powershell-v3-ise-commands-add-on.html

« Предыдущие записи

Follow

Get every new post delivered to your Inbox.