65.9K
CodeProject 正在变化。 阅读更多。
Home

重启和恢复 PowerShell 脚本

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.71/5 (9投票s)

2011年7月8日

CPOL

3分钟阅读

viewsIcon

125192

downloadIcon

2826

创建神奇的“开发者 PC 设置脚本”的第一步。

引言

每天都需要重启 Windows 的时代已经过去了。然而,当处理系统维护或从脚本安装多个应用程序时,重启有时是不可避免的。 本文将介绍一个 PowerShell 脚本,该脚本能够运行多个步骤,重启计算机,并在另一步骤继续脚本。 简单但非常有用。

背景

本文中展示的想法源于一个真实的脚本,用于设置开发者 PC,其中包含从正确版本的 .NET Framework、在 IIS 中启用正确的功能、本地安装 Visual Studio 和 MS SQL Server 等。 以这种方式设置开发者 PC 的优势有很多

  • 它比让每个开发人员自己完成这些步骤要快得多
  • 它比使用磁盘映像更灵活
  • 它非常清楚地记录了使用的技术
  • 它可用于更新现有的开发人员 PC 以及从头开始安装

上述设置脚本的主要缺点是前期投入的时间,用于获得这样的脚本。 但是,本文将帮助您入门,您应该真正接受挑战,尝试创建自己的脚本 - 您会对 PowerScript 的强大功能印象深刻。

运行测试脚本

本文中介绍的简单测试脚本如下所示

param($Step="A")
# -------------------------------------
# Imports
# -------------------------------------
$script = $myInvocation.MyCommand.Definition
$scriptPath = Split-Path -parent $script
. (Join-Path $scriptpath functions.ps1)


Clear-Any-Restart

if (Should-Run-Step "A") 
{
    Write-Host "A"
    Wait-For-Keypress "The test script will continue after a reboot, press any key to reboot..." 
    Restart-And-Resume $script "B"
}

if (Should-Run-Step "B") 
{
    Write-Host "B"
}

if (Should-Run-Step "C") 
{
    Write-Host "C"
}

Wait-For-Keypress "Test script Complete, press any key to exit script..."

脚本将执行步骤 A 到 C,只有在完成步骤 A 后,它才会重启,然后继续执行步骤 B。 以下是两个屏幕截图,显示了预期结果

Script running step A and then reboots

Script continues the script starting at step B

使脚本了解步骤

可以通过多种方式使 PowerShell 脚本按顺序执行。 此示例中唯一的要求是,必须在命令行上指定起始步骤,如下所示

>.\testscript.ps1 -Step B

从上面的测试脚本中可以看出,我们声明了一个脚本参数 $Step,用于从命令行获取起始步骤。 然后我们创建一个简单的 guard 方法 Should-Run-Step,该方法将返回 false,直到在命令行上遇到指定的起始步骤,从那时起,它将返回 true

$global:started = $FALSE
$global:startingStep = $Step

function Should-Run-Step([string] $prospectStep) 
{
    if ($global:startingStep -eq $prospectStep -or $global:started) {
        $global:started = $TRUE
    }
    return $global:started
}

当然,此步骤机制可以更加复杂,包括端点和步骤范围,但这并不是本文的重点,因此留给读者作为练习。

一些注册表辅助函数

虽然我喜欢 PowerShell 的超级通用的 ???-ItemProperty 函数,但我倾向于认为这些方法会使脚本变得混乱,降低可读性。 因此,我将介绍四个简单的辅助方法来处理注册表

function Test-Key([string] $path, [string] $key)
{
    return ((Test-Path $path) -and ((Get-Key $path $key) -ne $null))   
}

function Remove-Key([string] $path, [string] $key)
{
    Remove-ItemProperty -path $path -name $key
}

function Set-Key([string] $path, [string] $key, [string] $value) 
{
    Set-ItemProperty -path $path -name $key -value $value
}

function Get-Key([string] $path, [string] $key) 
{
    return (Get-ItemProperty $path).$key
}

从 PowerShell 重启

使用命令 Restart-Computer 即可从 PowerShell 简单地重启计算机。 使 Windows 在启动时执行命令是通过注册表项 "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" 处理的。 将这些信息放在一起,我们可以定义一个 Restart-And-Run 函数,它将重启然后启动在 $run 参数中传递的任何内容。

$global:RegRunKey ="HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
function Restart-And-Run([string] $key, [string] $run) 
{
    Set-Key $global:RegRunKey $key $run
    Restart-Computer
    exit
}

如果您不想在每次启动 Windows 时都启动指定的命令,最好记住清除该注册表项。 由于我们计划恢复脚本,因此我们可以很容易地在一个专用的函数中执行此操作,该函数应放置在脚本的顶部。

$global:restartKey = "Restart-And-Resume"
function Clear-Any-Restart([string] $key=$global:restartKey) 
{
    if (Test-Key $global:RegRunKey $key) {
        Remove-Key $global:RegRunKey $key
    }
}

您可能已经注意到,Clear-Any-Restart 函数采用默认键 "Restart-And-Resume",并且恢复脚本正是本文旨在实现的目标。 猜猜怎么着,我们所要做的就是使用所需的步骤参数重新启动 PowerShell

$global:powershell = (Join-Path $env:windir "system32\WindowsPowerShell\v1.0\powershell.exe")
function Restart-And-Resume([string] $script, [string] $step) 
{
    Restart-And-Run $global:restartKey "$global:powershell $script -Step $step"
}

就这样,我们都完成了,您现在可以制作自己的设置脚本了。 尽情享受,请让我知道您的想法以及您对此的使用情况。

故障排除

如果您在执行脚本时遇到问题,请确保您没有指定 restricted 执行策略

>Set-ExecutionPolicy RemoteSigned

历史

  • 2011 年 7 月 8 日:初始版本。
© . All rights reserved.