PowerShell 技能连载 - 进度条技巧(第 4 部分)

由于广大用户的要求,这里提供了一段代码,演示如何使用嵌套进度条并显示每个任务的“真实”进度指示器:

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
26
$servers = 'dc-01', 'dc-02', 'msv3', 'msv4'
$ports = 80, 445, 5985

$counterServers = 0
$servers | ForEach-Object {
# increment server counter and calculate progress
$counterServers++
$percentServers = $counterServers * 100 / $servers.Count

$server = $_
Write-Progress -Activity 'Checking Servers' -Status $server -Id 1 -PercentComplete $percentServers

$counterPorts = 0
$ports | ForEach-Object {
# increment port counter and calculate progress
$counterPorts++
$percentPorts = $counterPorts * 100 / $ports.Count


$port = $_
Write-Progress -Activity 'Checking Port' -Status $port -Id 2 -PercentComplete $percentPorts

# here would be your code that performs some task, i.e. a port test:
Start-Sleep -Seconds 1
}
}

PowerShell 技能连载 - 进度条技巧(第 3 部分)

PowerShell 内置的进度条可以嵌套,每个任务显示一个进度条。为了使其正常工作,请为您的进度条分配不同的 ID 号码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$servers = 'dc-01', 'dc-02', 'msv3', 'msv4'
$ports = 80, 445, 5985

$servers | ForEach-Object {
$server = $_
Write-Progress -Activity 'Checking Servers' -Status $server -Id 1

$ports | ForEach-Object {
$port = $_
Write-Progress -Activity 'Checking Port' -Status $port -Id 2

# here would be your code that performs some task, i.e. a port test:
Start-Sleep -Seconds 1
}
}

PowerShell 技能连载 - 进度条技巧(第 2 部分)

内置的 PowerShell 进度条支持“真实”的进度指示器,只要您提交一个在 0 到 100 范围内的“percentCompleted”值:

1
2
3
4
5
6
0..100 | ForEach-Object {
$message = '{0:p0} done' -f ($_/100)
Write-Progress -Activity 'I am busy' -Status $message -PercentComplete $_

Start-Sleep -Milliseconds 100
}

为了显示一个“真实”的进度指示器,因此您的脚本需要“知道”已经处理了多少给定任务。

以下是一个修改后的示例,它定义了需要处理多少个任务,然后从中计算出完成百分比:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$data = Get-Service  # for illustration, let's assume you want to process all services

$counter = 0
$maximum = $data.Count # number of items to be processed

$data | ForEach-Object {
# increment counter
$counter++
$percentCompleted = $counter * 100 / $maximum
$message = '{0:p1} done, processing {1}' -f ($percentCompleted/100), $_.DisplayName
Write-Progress -Activity 'I am busy' -Status $message -PercentComplete $percentCompleted

Write-Host $message
Start-Sleep -Milliseconds 100
}

PowerShell 技能连载 - 进度条技巧(第 1 部分)

PowerShell自带内置进度条。通常情况下,当脚本完成时,它会自动消失:

1
2
3
4
Write-Progress -Activity 'I am busy' -Status 'Step A'
Start-Sleep -Seconds 2
Write-Progress -Activity 'I am busy' -Status 'Step B'
Start-Sleep -Seconds 2

如果您想在脚本仍在运行时关闭进度条,则需要使用“-Completed”开关参数:

1
2
3
4
5
6
7
Write-Progress -Activity 'I am busy' -Status 'Step A'
Start-Sleep -Seconds 2
Write-Progress -Activity 'I am busy' -Status 'Step B'
Start-Sleep -Seconds 2
Write-Progress -Completed -Activity 'I am busy'
Write-Host 'Progress bar closed, script still running.'
Start-Sleep -Seconds 2

如您所见,关闭进度条需要同时指定“-Activity”参数,因为它是一个强制性的参数。但是,如果您只想关闭所有可见的进度条,则“-Activity”参数的值并不重要。你可以提交一个空格或数字等任何值(除了null值或空字符串),因为这些都不会被强制性参数接受。

写入以下代码以定义“- Activity” 参数的默认值:

1
2
3
4
5
6
7
Write-Progress -Activity 'I am busy' -Status 'Step A'
Start-Sleep -Seconds 2
Write-Progress -Activity 'I am busy' -Status 'Step B'
Start-Sleep -Seconds 2
Write-Progress -Completed -Activity ' '
Write-Host 'Progress bar closed, script still running.'
Start-Sleep -Seconds 2

写入以下代码以定义 “-Activity“ 参数的默认值:

1
$PSDefaultParameterValues['Write-Progress:Activity']='xyz'

现在,”Write-progress“ 将接受 “Completed“ 参数而无需提交 “Activity“ 参数:

1
2
3
4
5
6
7
Write-Progress -Activity 'I am busy' -Status 'Step A'
Start-Sleep -Seconds 2
Write-Progress -Activity 'I am busy' -Status 'Step B'
Start-Sleep -Seconds 2
Write-Progress -Completed # due to the previously defined new default value, -Activity can now be omitted
Write-Host 'Progress bar closed, script still running.'
Start-Sleep -Seconds 2

PowerShell 技能连载 - 列出活动的域控制器

如果您的计算机连接到域,您可以使用 PowerShell 来识别您所连接的域控制器。可以使用以下命令:

1
Get-ADDomainController -Discover

或者,简单地查找 “LOGONSERVER” 环境变量:

1
$env:LOGONSERVER

它会列出您登录的计算机名称。如果它等于自己的计算机名称(不带反斜杠),则表示已本地登录而非加入域:

1
2
3
4
5
6
7
8
if ($env:LOGONSERVER.TrimStart('\') -eq $env:COMPUTERNAME)
{
"local"
}
else
{
"logged on to $env:LOGONSERVER"
}

PowerShell 技能连载 - 列出所有域控制器

要快速获取所有域控制器的列表,请运行以下命令:

1
Get-AdDomainController -Filter * | Select-Object -Property Name, Domain, Forest, IPv4Address, Site | Export-Csv -Path $env:temp\report.csv -UseCulture -NoTypeInformation -Encoding Default

当然,您需要登录到域,并且需要访问 “ActiveDirectory” PowerShell 模块。

该命令会在您的临时文件夹中创建一个 CSV 文件,可用 Excel 打开。只需双击所创建的 CSV 文件即可。”-UseCulture“ 确保 CSV 使用正确的分隔符以便 Excel 打开它。

PowerShell 技能连载 - 彻底删除硬盘数据

当您在硬盘驱动器或USB闪存等存储介质上删除文件时,如您所知,数据并不会立即被删除。相反,数据只是未分配的,并将根据需要被新数据覆盖。在此之前,任何人都可以恢复已删除的数据。

为了防止对已删除的数据进行访问,在 Windows 上可以使用内置工具 cipher.exe 显式地覆盖所有未分配的存储空间。当您这样做时,您会立即意识到为什么默认情况下不这样做:即使是所有零位的数据也需要很长时间才能存储到介质中。

该命令将三次覆盖 C:\ 驱动器上未分配的存储空间,首先用 “0”、然后用 “1”,最后用随机值。可能需要一个晚上才能完成这个任务:

1
cipher /w:C:\

以下是我们示例中使用的 “/w“ 开关的官方描述:“从整个卷中可用未使用磁盘空间中移除数据。如果选择此选项,则忽略所有其他选项。指定目录可以位于本地卷中任何位置。如果它是一个挂载点或指向另一个卷中目录,则将删除该卷上的数据。

PowerShell 技能连载 - 列出所有域控制器

要快速获取所有域控制器的列表,请运行以下命令:

1
Get-AdDomainController -Filter * | Select-Object -Property Name, Domain, Forest, IPv4Address, Site | Export-Csv -Path $env:temp\report.csv -UseCulture -NoTypeInformation -Encoding Default

当然,您需要登录到域,并且需要访问“ActiveDirectory” PowerShell 模块。

该命令会在您的临时文件夹中创建一个 CSV 文件,可用 Excel 打开。只需双击创建的 CSV 文件即可。“-UseCulture”确保CSV使用正确的分隔符以便 Excel 打开它。

PowerShell 技能连载 - 永久删除硬盘内容

当您在硬盘驱动器或USB闪存等存储介质上删除文件时,如您所知,数据并不会立即被删除。相反,数据只是未分配的,并将根据需要被新数据覆盖。在此之前,任何人都可以恢复已删除的数据。

为了防止对已删除的数据进行访问,在Windows上可以使用内置工具 cipher.exe 显式地覆盖所有未分配的存储空间。当您这样做时,您会立即意识到为什么默认情况下不这样做:即使是所有零位数也需要很长时间才能将数据存储到介质中。

该命令三次覆盖C:\驱动器上未分配的存储空间,首先用“0”、然后用“1”,最后用随机值。你最好投入一晚完成这个任务:

1
cipher /w:C:\

以下是我们示例中使用的“/w”开关的官方描述:“从整个卷中可用未使用磁盘空间中移除数据。如果选择此选项,则忽略所有其他选项。指定目录可以位于本地卷中任何位置。如果它是一个挂载点或指向另一个卷中目录,则将删除该卷上的数据。

PowerShell 技能连载 - Office365邮箱恢复删除(第 2 部分)

假设有人离开了公司,您删除了其Office365用户帐户。事实证明,这也会删除附加的邮箱。如果您想将此邮箱附加到其他人身上,即仍然能够访问重要的公司或客户数据,则可以按照以下步骤操作。

首先,请检查邮箱是否已“软删除”并且仍然可以恢复:

1
Get-Mailbox -SoftDeletedMailbox | Select-Object Name,ExchangeGUID

此列表中每个可恢复的邮箱都具有唯一的GUID。要将此邮箱附加到其他人身上,还需要找出要将已删除的邮箱附加到其中的仍处于活动状态的邮箱的GUID:

1
$liveMailbox = Get-Mailbox existingPerson@somecompany.onmicrosoft.com | Select-Object Name,ExchangeGUID

接下来,在获取两个GUID后,发出请求以将旧邮件箱数据连接到新邮件箱,并指定目标根文件夹(例如“旧邮件内容”)。这将是新邮件箱显示在其下面的电子邮件文件夹:

1
New-MailboxRestoreRequest -SourceMailbox [ENTER_GUID_OF_SOFTDELETED_MAILBOX] -TargetMailbox $liveMailbox.ExchangeGUID -AllowLegacyDNMismatch -TargetRootFolder "Old Mailbox Content