PowerShell 技能连载 - 对图片编码

如果您的脚本需要图标或图片等资源,您不需要另外发布这些资源。它们可以用 Base64 编码并且以纯文本的方式加到您的脚本中。

这个例子演示了如何将一个 JPG 图片转换为 Base64 编码的字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function Convert-JPG2Base64
{
param
(
[Parameter(Mandatory=$true)]
[String]
$Path
)

$format = [System.Drawing.Imaging.ImageFormat]::Jpeg

$image = [System.Drawing.Image]::FromFile($Path)
$stream = New-Object -TypeName System.IO.MemoryStream
$image.Save($stream, $format)
$bytes = [Byte[]]($stream.ToArray())
[System.Convert]::ToBase64String($bytes, 'InsertLineBreaks')
}

# find a random picture
$picture = Get-ChildItem $env:windir\Web\Wallpaper *.jpg -Recurse |
Select-Object -First 1

$pictureString = Convert-JPG2Base64 -Path $picture.FullName

$pictureString

Convert-JPG2Base64 函数接受一个 JPG 图片路径作为参数并且返回 Base64 编码后的图片。在这个例子中,我们使用 Windows 文件夹中的第一个 JPG 墙纸。请确保您的 Windows 文件夹中包含图片,或者把 JPG 图片的文件夹改为您想要的文件夹。

返回的文本可以嵌入一段脚本中。而且,返回的 Base64 文本可能会非常大,由图片的尺寸和质量决定。

明天,我们将演示如何将 Base64 编码后的图片加载到内存中,并在自己的 WPF 窗口中显示。

PowerShell 技能连载 - 用 Base64 编解码文本

以下是将文本用 Base64 编码的简单方法:

1
2
3
4
#requires -Version 1

$text = 'Hello World!'
[Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($text), 'InsertLineBreaks')

结果字符串看起来大概如下:

SABlAGwAbABvACAAVwBvAHIAbABkACEA

文本编码可以用于简易的混淆文本,或是保护文本防止不小心被错误地格式化。例如 PowerShell.exe 可运行 Base64 编码过的命令。以下是一个例子(请打开您机器的声音):

1
powershell.exe -EncodedCommand ZgBvAHIAKAAkAHgAIAA9ACAAMQAwADAAMAA7ACAAJAB4ACAALQBsAHQAIAAxADIAMAAwADAAOwAgACQAeAArAD0AMQAwADAAMAApACAAewAgAFsAUwB5AHMAdABlAG0ALgBDAG8AbgBzAG8AbABlAF0AOgA6AEIAZQBlAHAAKAAkAHgALAAgADMAMAAwACkAOwAgACIAJAB4ACAASAB6ACIAfQA=

要解码一个 Base64 字符串,您可以使用以下代码。

1
2
3
4
#requires -Version 1

$text = 'SABlAGwAbABvACAAVwBvAHIAbABkACEA'
[Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($text))

您也可以使用这段代码来解码上面那段编码后的命令,看看它做了什么。只需要用编码过的命令替换掉 $test

PowerShell 技能连载 - 管理 Windows 防火墙

从 Windows 8 和 Server 2012 开始,有一个 Cmdlet 可以在多个配置中启用客户端防火墙:

1
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True

在之前的操作系统中,您需要使用依靠 netsh.exe:

1
netsh advfirewall set allprofiles state on

PowerShell 技能连载 - 查找递归的 AD 成员

在 AD 中,有一个看起来很奇怪的过滤器:1.2.840.113556.1.4.1941。它被称为“链式匹配规则”,可以用来快速查找嵌套的成员。

您所需的是某个成员的 DN。然后,您可以像这样使用它:

1
2
3
4
#requires -Version 1 -Modules ActiveDirectory

$DN = 'place DN here!'
Get-ADGroup -LDAPFilter "(member:1.2.840.113556.1.4.1941:=$($DN))"

Since this is a native LDAP filter, you can even use it without the ActiveDirectory module, resorting to native .NET methods:
由于它是一个原生的 LDAP 过滤器,您甚至可以在没有 ActiveDirectory 模块的情况下以 .NET 原生的方式使用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$DN = 'place DN here!'
$strFilter = "(member:1.2.840.113556.1.4.1941:=$DN)"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry('LDAP://rootDSE')
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = "LDAP://$($objDomain.rootDomainNamingContext)"
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = 'Subtree'
$colProplist = 'name'
foreach ($i in $colPropList){
$null = $objSearcher.PropertiesToLoad.Add($i)
}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{
$objItem = $objResult.Properties
$objItem.name
}

PowerShell 技能连载 - 清除回收站

在 PowerShell 5.0 之前,要清除回收站得手工删除每个驱动器根目录下隐藏的 $Recycle.Bin 文件夹里的内容。

有一些作者推荐使用名为 Shell.Application 的 COM 对象。它不一定可靠,因为回收站不一定可见,取决于资源管理器的设置。

幸运的事,PowerShell 5.0 终于提供了 Clear-RecycleBin Cmdlet。

PowerShell 技能连载 - 自动获取重要的支持响应信息

Here is a fun function to provide you with a good first level support response in case everyone is off for Christmas:
这是一个有趣的函数,当所有人都下班去过圣诞时将给您提供重要的支持响应信息。

#requires -Version 3

function Get-FirstLevelSupportResponse
{
  $url = 'http://pages.cs.wisc.edu/~ballard/bofh/bofhserver.pl'
  $ProgressPreference = 'SilentlyContinue'
  $page = Invoke-WebRequest -Uri $url -UseBasicParsing
  $pattern = '(?s)<br><font size\s?=\s?"\+2">(.+)</font'

  if ($page.Content -match $pattern)
  {
    $matches[1]
  }
}

您需要 Internet 连接来运行这段脚本。

PowerShell 技能连载 - 查询当前登录的用户名

有两种方式可以查询当前登录的用户:

# User logged on to a physical box
Get-WmiObject -Class Win32_ComputerSystem | Select-object -ExpandProperty UserName


# Owners of explorer.exe processes (desktop is an Explorer process)
Get-WmiObject -Class Win32_Process -Filter 'Name="explorer.exe"'  |
  ForEach-Object {
    $owner = $_.GetOwner()
    '{0}\{1}' -f  $owner.Domain, $owner.User
  } |
  Sort-Object -Unique

两种使用 Get-WmiObject 的方式都支持本地和远程方式调用。

PowerShell 技能连载 - 获取操作系统清单

如果您的老板需要一份您 AD 中所有计算机的操作系统清单,这也许是个好办法:

#requires -Version 1 -Modules ActiveDirectory

$max = 100

$os = Get-ADComputer -Filter * -Properties OperatingSystem -ResultPageSize $max |
Group-Object -Property OperatingSystem -NoElement |
Select-object -ExpandProperty Name |
ForEach-Object { '"{0}"' -f $_ }

$list = $os -join ','
$list
# copy list to clipboard
$list | clip

该脚本将从您的 AD 中获取计算机账户并将它们根据操作系统分组,然后将它整理成一个清单。请注意使用 PageSize 因为在一个大型的组织中获取所有计算机信息可能会花费很长时间。

PowerShell 技能连载 - 根据 OU 分析操作系统

以下是一个快捷的脚本,扫描 Active Directory 中的所有 OU,得到所有的计算机账户,然后将每个 OU 的信息按照操作系统分组:

#requires -Version 2 -Modules ActiveDirectory

Get-ADOrganizationalUnit -Filter * |
  ForEach-Object {
    $OU = $_

    Get-ADComputer -Filter * -SearchBase $OU.DistinguishedName -SearchScope SubTree -Properties Enabled, OperatingSystem |
      Where-Object { $_.Enabled -eq $true } |
      Group-Object -Property OperatingSystem -NoElement |
      Select-Object -Property Count, Name, OU, OUDN |
      ForEach-Object {
        $_.OU = $OU.Name
        $_.OUDN = $OU.DistinguishedName
        $_
      }
  } |
  Out-GridView