PowerShell 技能连载 - 搜索本地用户

您知道吗?您可以搜索计算机上的本地用户,就像搜索域账户一样。

以下的示例代码搜索所有以“A”开头并且是启用状态的本地用户:

Add-Type -AssemblyName System.DirectoryServices.AccountManagement

$type = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext('Machine', $env:COMPUTERNAME)

$UserPrincipal = New-Object System.DirectoryServices.AccountManagement.UserPrincipal($type)

# adjust your search criteria here:
$UserPrincipal.Name = 'A*'
# you can add even more:
$UserPrincipal.Enabled = $true

$searcher = New-Object System.DirectoryServices.AccountManagement.PrincipalSearcher
$searcher.QueryFilter = $UserPrincipal
$results = $searcher.FindAll();

$results | Select-Object -Property Name, LastLogon, Enabled

类似地,要查找所有设置了密码、密码永不过期,并且是启用状态的本地用户,试试以下代码:

Add-Type -AssemblyName System.DirectoryServices.AccountManagement

$type = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext('Machine', $env:COMPUTERNAME)

$UserPrincipal = New-Object System.DirectoryServices.AccountManagement.UserPrincipal($type)

# adjust your search criteria here:
$UserPrincipal.PasswordNeverExpires = $true
$UserPrincipal.Enabled = $true

$searcher = New-Object System.DirectoryServices.AccountManagement.PrincipalSearcher
$searcher.QueryFilter = $UserPrincipal
$results = $searcher.FindAll();

$results | Select-Object -Property Name, LastLogon, Enabled, PasswordNeverExpires

PowerShell 技能连载 - 获取本地组成员

在 PowerShell 中,通过 .NET Framework 3.51 或更高的版本,可以使用面向对象的方式管理本地用户和组。以下代码可以列出本机上的管理员用户:

Add-Type -AssemblyName System.DirectoryServices.AccountManagement

$type = New-Object DirectoryServices.AccountManagement.PrincipalContext('Machine', `$env:COMPUTERNAME)

$group = [DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($type, `'SAMAccountName', 'Administrators')

$group.Members | Select-Object -Property SAMAccountName, LastPasswordSet, LastLogon, Enabled

您还可以获取更多的信息,比如试着查询组本身的信息:

或者试着列出所有成员的所有属性:

PowerShell 技能连载 - 将 Windows 8.1 中的 CMD.EXE 替换为 POWERSHELL.EXE

Windows 8.1 仍然在它的一些上下文菜单中提供旧的 cmd.exe 命令行窗口。在 Windows 8.1 中,要将它由 cmd.exe 改为 powershell.exe,请右键单击任务栏,然后选择属性。

然后,单击“导航”标签页,然后选中第三个选项。

下一次,当您在 Windows 8.1 中按下 WIN+X 键时,迷你菜单上将显示“PowerShell”。

PowerShell 技能连载 - 使用 PowerShell 管理 Office365

您知道吗?您也可以用 PowerShell 管理您的 Office365 账户。如果您拥有一个 Office365 账户,请试试以下脚本:

$OfficeSession = New-PSSession -ConfigurationName Microsoft.Exchange `-ConnectionUri https://ps.outlook.com/powershell/ -Credential (Get-Credential) `-Authentication Basic -AllowRedirection

$import = Import-PSSession $OfficeSession -Prefix Off365

Get-Command -Noun Off365*

这段代码将使用您的凭据连接 Office 365,然后导入用于管理 Office 365 的 PowerShell cmdlet。您大约可以获得 400 个新的 cmdlet。如果您收到“Access Denied”提示,那么有可能您的账户没有足够的权限,或者您敲错了密码。

注意所有导入的 cmdlet 都是以 Off365 为前缀的,所以要查看所有的邮箱,请试试以下代码:

PS> Get-Off365Mailbox

您可以自己选择前缀(见前面的代码),这样您可以同时通过不同的前缀连接到多个 Office365 账户。当您执行 Import-PSSession 时,您还可以省略前缀。

要查看 Office365 导出的所有命令,请使用以下代码:

$import.ExportedCommands

PowerShell 技能连载 - 显示 Path 环境变量

当您启动一个程序时,$env:Path 环境变量列出了 Windows 搜索路径中的所有目录。类似地,$env:PSModulePath 列出了 PowerShell 搜索 PowerShell 模块(包括它的自动加载模块)的所有目录。

这些变量包含了以分号分隔的信息。所以使用 -split 操作符分隔并显示它们:

顺便说一下,第三行(在 Program Files 中的)是在 PowerShell 4.0 中才加入的。

PowerShell 技能连载 - 查找磁盘分区详细信息

要查看磁盘分区信息,请使用 WMI:

Get-WmiObject -Class Win32_DiskPartition |
  Select-Object -Property *

然后,选择您感兴趣的属性,然后将 * 号替换成逗号分隔的属性列表。例如:

Get-WmiObject -Class Win32_DiskPartition |
  Select-Object -Property Name, BlockSize, Description, BootPartition

如果您选择四个或四个以下的属性,结果是一个干净的表格,否则将是一个列表:

如果您想知道更多的信息,请使用 -List 参数来搜索其它 WMI 类,或者和 “disk” 有关的,或者其它完全不相关的:

PowerShell 技能连载 - 为 AD 用户设置缺省的 Email 地址

编写 Active Directory 脚本不需要额外的 module。通过简单的 .NET 框架方法,您可以实现令人惊叹的功能。实际上,这个技术十分强大,您不应该在您的生产环境下运行以下的例子,除非您知道自己在做什么。

一下代码片段在您的 Active Directory 中查找存储于 CN=Users 并且没有邮箱地址的的所有用户。然后,脚本将为他们设置一个缺省的邮箱地址。该地址由姓名 + “mycompany.com” 组成。

# adjust LDAP path (i.e. remove CN=Users to search the entire domain):
$SearchRoot = 'LDAP://CN=Users,{0}' -f ([ADSI]'').distinguishedName.ToString()
# adjust LDAPFilter. Example: (!mail=*) = all users with no defined mail attribute
$LdapFilter = "(&(objectClass=user)(objectCategory=person)(!mail=*))"

$Searcher = New-Object DirectoryServices.DirectorySearcher($SearchRoot, $LdapFilter)
$Searcher.PageSize = 1000
$Searcher.FindAll() | ForEach-Object {
  $User = $_.GetDirectoryEntry()
  try
  {
        # Set mail attribute
        $User.Put("mail", ('{0}.{1}@mycompany.com' -f $user.givenName.ToString(), $user.sn.ToString()))

        # Commit the change
        $User.SetInfo()
  }
  catch { Write-Warning "Problems with $user. Reason: $_" }
}

这个示例代码可以读取并且修改、设置任意的属性。它特别适用于不能通过 cmdlet 设置的自定义属性。

PowerShell 技能连载 - 锁定屏幕

借助 WPF,PowerShell 用几行代码就可以创建窗口。以下是一个有趣的关于透明屏幕覆盖层的例子。

您可以调用 Lock-Screen 并且传入一个脚本块和一个标题。PowerShell 将会用它的覆盖层锁定屏幕,再次执行代码将解锁。

function Lock-Screen([ScriptBlock] $Payload={Start-Sleep -Seconds 5}, $Title='Busy, go away.')
{
    try
    {
      $window = New-Object Windows.Window
      $label = New-Object Windows.Controls.Label

      $label.Content = $Title
      $label.FontSize = 60
      $label.FontFamily = 'Consolas'
      $label.Background = 'Transparent'
      $label.Foreground = 'Red'
      $label.HorizontalAlignment = 'Center'
      $label.VerticalAlignment = 'Center'

      $Window.AllowsTransparency = $True
      $Window.Opacity = .7
      $window.WindowStyle = 'None'
      $window.Content = $label
      $window.Left = $window.Top = 0
      $window.WindowState = 'Maximized'
      $window.Topmost = $true

      $null = $window.Show()
      Invoke-Command -ScriptBlock $Payload
    }
    finally { $window.Close() }
}

$job =
{
  Get-ChildItem c:\windows -Recurse -ErrorAction SilentlyContinue
}

Lock-Screen -Payload $job -Title 'I am busy, go away and grab a coffee...'

您很快就会发现,锁屏确实可以防止鼠标点击,但是并不会屏蔽按键。这是一个有趣的技术,不是绝对安全的锁定。

PowerShell 技能连载 - 创建临时密码

以下是一些为您创建不同长度随机密码的代码:

$length = 8
$characters = [Char[]]((31..50) + (65..90) + (97..122))
$characters = $characters -ne 'O' -ne 'o' -ne 'l' -ne '1' -ne '-'
$password = -join ($characters | Get-Random -Count $length)
"Your temporary $length-character-password is $password"

您的密码长度通过 $length 变量设置。用于构成密码的字符集存放在 $characters 变量中。缺省情况下使用 ASCII 编码为 31-50、65-90、97-122 的所有字符。如您所见,通过 -ne 操作符,您可以调整列表和排除字符。在我们的例子中,我们排除了容易拼写错的字母。

PowerShell 技能连载 - 混淆凭据

您有没有办法安全地将机密的密码包含在 PowerShell 脚本中?您肯定不敢。但您可以使得别人更难以获取到秘密的信息。

以下是一个设计成在 PowerShell ISE 编辑器中使用的代码生成器脚本:

# ask for credentials
$cred = Get-Credential
$pwd = $cred.Password
$user = $cred.UserName

# create random encryption key
$key = 1..32 | ForEach-Object { Get-Random -Maximum 256 }

# encrypt password with key
$pwdencrypted = $pwd | ConvertFrom-SecureString -Key $key

# turn key and password into text representations
$secret = -join ($key | ForEach-Object { '{0:x2}' -f $_ })
$secret += $pwdencrypted

# create code
$code  = '$i = ''{0}'';' -f $secret
$code += '$cred = New-Object PSCredential('''
$code += $user + ''', (ConvertTo-SecureString $i.SubString(64)'
$code += ' -k ($i.SubString(0,64) -split "(?<=\G[0-9a-f]{2})(?=.)" |'
$code += ' % { [Convert]::ToByte($_,16) })))'

# write new script
$editor = $psise.CurrentPowerShellTab.files.Add().Editor
$editor.InsertText($code)
$editor.SetCaretPosition(1,1)

当您运行它的时候,它将询问用户输入一个用户名和密码。然后,它将会生成一段加密的 PowerShell 脚本片段。您可以在您的脚本中使用它。

以下是由以上脚本生成的一段加密的脚本片段:

$i = '73cc7284f9e79f68e9d245b5b2d96c4026397d96cfac6023325d1375414e5f7476492d1116743f0423413b16050a5345MgB8AGgAdABLAEkARABiAFIARgBiAGwAZwBHAHMAaQBLAFoAeQB2AGQAOQAyAGcAPQA9AHwAMgBiADIAMABmADYANwA1ADYANwBiAGYAYwA3AGMAOQA0ADIAMQA3ADcAYwAwADUANAA4ADkAZgBhADYAZgBkADkANgA4ADMAZAA5ADUANABjADgAMgAwADQANQA1ADkAZAA3AGUAMwBmADMAMQAzADQAZgBmADIAZABlADgAZQA=';$cred = New-Object PSCredential('contoso\fabrikam', (ConvertTo-SecureString $i.SubString(64) -k ($i.SubString(0,64) -split "(?<=\G[0-9a-f]{2})(?=.)" | % { [Convert]::ToByte($_,16) })))

这段自动生成的加密脚本片段将会定义一个 $cred 变量,用于保存包括密码在内的合法凭据。接下来您可以将 $cred 变量传递给您脚本中任何需要用户和密码的 -Credential 参数。