PowerShell 技能连载 - 使用 PowerShell 的帮助

要查看完整的 PowerShell 帮助,您首先需要从 Internet 下载帮助信息。只需要以管理员权限打开一个 PowerShell 控制台执行以下代码:

PS> Start-Process -FilePath powershell.exe -Verb runas

下一步,下载 PowerShell 帮助:

PS> Update-Help -UICulture en-us -Force

请注意:PowerShell 帮助只有英语的版本。这是为什么要指定 -UICulture 确保请求下载英文帮助文件的原因。

当帮助文件安装完后,在 PowerShell 4.0 及以上版本就可以使用了。您可以显示一个命令的完整帮助,或只是显示示例代码:

PS> Get-Help -Name Get-Random -ShowWindow

PS> Get-Help -Name Get-Random -Examples

NAME
    Get-Random

SYNOPSIS
    Gets a random number, or selects objects randomly from a collection.

    -------------------------- EXAMPLE 1 --------------------------

    PS C:\>Get-Random
    3951433


    This command gets a random integer between 0 (zero) and Int32.MaxValue.




    -------------------------- EXAMPLE 2 --------------------------

    PS C:\>Get-Random -Maximum 100
    47


    This command gets a random integer between 0 (zero) and 99.



   ...

在 PowerShell 3.0 中,如果您并不是使用英语,您需要手动将帮助文件从 en-US 文件夹复制到您语言对应的文件夹中:

#requires -RunAsAdministrator
#requires -Version 3

$locale = $host.CurrentUICulture.Name
if ($locale -eq 'en-us')
{
    Write-Warning 'You are using the English locale, all is good.'
}
else
{
    Copy-Item -Path "$pshome\en-us\*" -Destination "$pshome\$locale\" -Recurse -ErrorAction SilentlyContinue -Verbose
    Write-Host "Help updated in $locale locale"
}

当帮助文件复制到您语言对应的文件夹中后,您就可以在非英语系统中使用英语的帮助文件了。

PowerShell 技能连载 - 设置 AD 账号的过期时间

要安全地使用临时的 AD 账号,例如给客户或是顾问使用,请记得设置一个失效日期。

以下示例代码演示了如何设置今天起 20 之后过期:

#requires -Version 1 -Modules ActiveDirectory
# SAMAccount name
$user = 'user12'

# days when to expire
$Days = 20

# expiration date is today plus the number of days
$expirationDate = (Get-Date).AddDays($Days)

Set-ADUser -Identity $user -AccountExpirationDate $expirationDate

请注意这段代码需要随 RSAT 免费工具发布的 Active Directory 模块。

如果您的计算机并没有连接到 AD,但是您拥有一个合法的 AD 账号,您可以用这种方法手动连接到 AD:

#requires -Version 1 -Modules ActiveDirectory

# Name or IP of DC
$ServerName = '10.10.12.110'
# Logon credentials
$Credential = Get-Credential


# SAMAccount name
$user = 'user12'

# days when to expire
$Days = 20

# expiration date is today plus the number of days
$expirationDate = (Get-Date).AddDays($Days)

Set-ADUser -Identity $user -AccountExpirationDate $expirationDate -Server $ServerName -Credential $Credential

PowerShell 技能连载 - 批量删除 AD 的防意外删除保护

缺省情况下,AD 对象是受保护防止意外删除的。要移除一个指定的范围内所有对象(例如某个机构之下)的这种保护,请试试这段代码:

#requires -Version 1 -Modules ActiveDirectory

Get-ADObject -Filter * -SearchBase 'OU=TestOU,DC=Vision,DC=local"' |
ForEach-Object -Process {
    Set-ADObject -ProtectedFromAccidentalDeletion $false -Identity $_
}

注意:这段代码需要免费的 RSAT 工具所带的 ActiveDirectory 模块。

PowerShell 技能连载 - AD 操作自动化入门

当 Microsoft 下载的免费的 RSAT 工具包含了 ActiveDirectory 模块。它带有一系列管理 Active Directory 账户的命令。

假设您已经连入了一个 Active Directory 环境,您可以使用以下示例代码来熟悉这些新命令:

# find your own user account by SAMAccountName
Get-ADUser -Identity $env:USERNAME

# find user account by DN
Get-ADUser -Identity 'CN=TWeltner,OU=Users,OU=Hannover,OU=Trainees,DC=powershell,DC=local'

# find your own user account and return all available attributes
Get-ADUser -Identity $env:USERNAME -Properties *

# find your own user account and change attributes
Get-ADUser -Identity $env:USERNAME | Set-ADUser -Description 'My account'

# find all user accounts where the SAMAccount name starts with "T"
Get-ADUser -Filter 'SAMAccountName -like "T*"'

# find user account "ThomasP" and use different logon details for AD

# logon details for your AD
$cred = Get-Credential
$IPDC = '10.10.11.2'
Get-ADUser -Identity ThomasP -Credential $cred -Server $IPDC

# find all groups and output results to gridview
Get-ADGroup -Filter * | Out-GridView

# find all groups below a given search root
Get-ADGroup -Filter * -SearchBase 'OU=test,DC=powershell,DC=local'

# get all members of a group
Get-ADGroupMember -Identity 'Domain Admins'

# create new user account named "Tom"
# define password
$secret = 'Initial$$00' | ConvertTo-SecureString -AsPlainText -Force
$secret = Read-Host -Prompt 'Password' -AsSecureString
New-ADUser -Name Tom -SamAccountName Tom -ChangePasswordAtLogon $true -AccountPassword $secret -Enabled $true

# delete user account "Tom"
Remove-ADUser -Identity Tom -Confirm:$false

# create an organizational unit named "NewOU1" in powershell.local
New-ADOrganizationalUnit -Name 'NewOU1' -Path 'DC=powershell,DC=local'

# all user accounts not used within last 180 days
$FileTime = (Get-Date).AddDays(-180).ToFileTime()
$ageLimit = "(lastLogontimestamp<=$FileTime)"
Get-ADUser -LDAPFilter $ageLimit

PowerShell 技能连载 - 设置本地 Administrator 账号的密码

要操作本地用户账号并设置一个新密码,您可以使用底层的 WinNT: 命名空间。

请注意,您需要管理员权限来设置新密码。

这个脚本可以为本地 Administrator 账号设置密码:

#requires -Version 1
$Password = 'P@ssw0rd'

$admin = [adsi]("WinNT://$env:computername/administrator, user")
$admin.psbase.invoke('SetPassword', $Password)

PowerShell 技能连载 - 加密文本

有很多办法可以加密文本。以下是一个未使用“密钥”的方法,所谓的密钥实际上是您的用户标识符加上机器名。

当您使用 ConvertTo-TextEncrypted 命令加密文本时,结果只能由同一个人在同一台机器上使用 ConvertFrom-TextEncrypted 命令来解密:

#requires -Version 2


function ConvertTo-TextEncrypted
{
    param([Parameter(ValueFromPipeline = $true)]$Text)

    process
    {
        $Text |
        ConvertTo-SecureString -AsPlainText -Force |
        ConvertFrom-SecureString
    }
}


function ConvertFrom-TextEncrypted
{
    param([Parameter(ValueFromPipeline = $true)]$Text)

    process
    {
        $SecureString = $Text |
        ConvertTo-SecureString

        $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
        [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
    }
}

要测试效果,请先使用这行代码:

PS> "Hello World" | ConvertTo-TextEncrypted | ConvertFrom-TextEncrypted
Hello World

下一步,得到相同的密文,然后将它保存到一个文件中:

$Path = "$env:temp\secret.txt"
'Hello World' | ConvertTo-TextEncrypted | Set-Content -Path $Path

现在,使用这行代码来读取加密的文件,然后对它进行解密:

$Path = "$env:temp\secret.txt"
Get-Content -Path $Path | ConvertFrom-TextEncrypted

请注意两个脚本都不包含密码。而实际的密码正是你的用户标识符。当另一个人,或是您在另一台机器上试图解开文件中的密文,将会失败。

这个方法可以用来安全地保存个人密码,这样您就不用每天都输入了。

PowerShell 技能连载 - 将过期的日志存档

有时,你会需要在文件超过一定的日期之后将它们移动到一个存档文件夹。

这个例子演示了如何检测过期文件的基本策略,以及如何将它们移动到存档文件夹:

#requires -Version 1
# how old (in days) would obsolete files be
$Days = 14

# where to look for obsolete files
$Path = $env:windir
$Filter = '*.log'

# where to move obsolete files
$DestinationPath = 'c:\archive'

# make sure destination folder exists
$destinationExists = Test-Path -Path $DestinationPath
if (!$destinationExists)
{
    $null = New-Item -Path $DestinationPath -ItemType Directory
}

$cutoffDate = (Get-Date).AddDays(-$Days)

Get-ChildItem -Path $Path -Filter $Filter -Recurse -ErrorAction SilentlyContinue |
Where-Object -FilterScript {
    $_.LastWriteTime -lt $cutoffDate
} |
Move-Item -Destination c:\archive -WhatIf

这个示例脚本在 Windows 文件夹和它的子文件夹中查找所有扩展名为 *.log 的日志文件。所有超过 14 天(在过去 14 天内没有修改过)的日志文件将被移动到 c:\archive 目录中。如果该文件夹不存在,则会自动创建。

请注意这只是一个示例脚本。您可能需要管理员权限才能确实将文件移出 Windows 文件夹。

PowerShell 技能连载 - 创建友好的“结束进程”应用程序

在前一个技能中,我们展示了如何选择应用程序并且立即结束它们。所有未保存的数据将会丢失。

这是一个更复杂的实现。它可以列出所有的应用程序,您可以选择希望结束的应用程序(按住 CTRL 键选择多个应用程序)。

该脚本接下来尝试向选中的应用程序发送“关闭窗口”消息。用户将有机会保存未保存的数据。用户也可以取消“关闭窗口”消息。

This is why the script waits for 15 seconds, and then checks whether the requested applications actually ended. If not, these applications are killed immediately (remove –WhatIf to actually kill them):
这是为什么该脚本等待 15 秒,然后确认请求的应用程序是否确实已结束的原因。如果指定的尚未结束,则此时立即结束(移除 -WhatIf 可以真正结束它们):

#requires -Version 3

$list = Get-Process |
    Where-Object -FilterScript {
        $_.MainWindowHandle -ne 0
    } |
    Select-Object -Property Name, Description, MainWindowTitle, Company, ID |
    Out-GridView -Title 'Choose Application to Kill' -PassThru

# try and close peacefully
$list.ID | ForEach-Object -Process {
    $process = Get-Process -Id $_
    $null = $process.CloseMainWindow()
}

# give user 15 seconds to respond
Start-Sleep -Seconds 15

# check to see if selected programs closed, and if not, kill
# them anyway (remove -WhatIf to actually kill them)
$list.ID |
ForEach-Object -Process {
    Get-Process -Id $_ -ErrorAction SilentlyContinue
    } |
    Where-Object -FilterScript {
        $_.hasExited -eq $false
    } |
    Stop-Process -WhatIf

PowerShell 技能连载 - 创建“结束进程”应用

只需要通过一个管道命令,PowerShell 就能够打开一个包含正在运行的程序列表。您可以选择列表中的一个或多个进程(按住 CTRL 键选择多余一个条目),然后 PowerShell 可以结束选中的程序。

Get-Process |
  Where-Object { $_.MainWindowHandle -ne 0 } |
  Select-Object -Property Name, Description, MainWindowTitle, Company, ID |
  Out-GridView -Title 'Choose Application to Kill' -PassThru |
  Stop-Process -WhatIf

请注意代码中使用了 -WhatIf 来模拟结束进程。如果您希望真的结束进程,那么移除 -WhatIf 代码。

结束程序会导致选中的应用程序立即停止。所有未保存的数据都会丢失。

PowerShell 技能连载 - 打开网页

要快速地在 Internet Explorer 中打开新的网页,您可以像这样定义一个名为 Show-WebPage 的新函数:

#requires -Version 2

function Show-WebPage
{
    param
    (
        [Parameter(Mandatory = $true, HelpMessage = 'URL to open')]
        $URL
    )

    Start-Process -FilePath iexplore.exe -ArgumentList $URL
}

当您运行这段脚本并执行 Show-WebPage 时,该命令将询问您要打开的 URL。您也可以通过 Show-WebPage 的参数提交 URL。

请注意该函数使用了 Start-Process 命令来启动您指定的浏览器。如果您将这行代码改为:

Start-Process -FilePath $URL

那么将会使用您的缺省浏览器来打开该 URL。