1

在生产中分析 powershell cmdlet 的最佳方法是什么?假设您编写了一个执行以下操作的脚本 -

  1. 写入注册表值的 lof
  2. 注册 COM Dll
  3. 制作 IIS 应用程序池
  4. 启动 Windows 服务

&...中间出了点问题,那么通知用户以便可以跟踪和调试根问题的最佳实践是什么?

假设,由于某种原因,用户凭证创建 AppPool 失败,我想在那个时候停止处理,而且我想回滚我之前所做的事情。

详细模式 + 记录是在每一步收集每个细节的优雅方式吗?

4

2 回答 2

2

我编写了一个Write-Log在 poshcode ( http://poshcode.org/3270 ) 上发布的函数,用于生产级 PowerShell 程序。或者,您可以使用Start-Transcriptwhich 将控制台上显示的几乎所有内容记录到文件中。有几个关于Start-Transcript-

  1. 它不会记录外部程序输出,除非您通过主机输出 API 将其通过管道传输到Out-Host诸如ping.exe localhost | Out-Host.
  2. 并非所有主机都支持。例如 PowerGUI 不支持它,因此您必须使用$host.

我通常用于错误处理的模式是将所有内容包装在 try/catch 中。异常对象将$_在 catch 块中可用。它将包含有关发生的错误的所有信息、消息、行号和列号等...

我还将 设置$ErrorActionPreferenceStop以便所有 cmdlet 都会引发终止错误,因此脚本不会继续。它看起来像这样:

$ErrorActionPreference = "Stop"
try {
    # Write lof of registry values
    New-Item -Path HKCU:\Software\MyTest -ItemType Directory
    New-ItemProperty -Path HKCU:\Software\MyTest -Name MyTestValue -Value Test

    # Register COM Dlls
    regsrv32 my.dll
    if ($LASTEXITCODE -ne 0) { throw "Failed to register my.dll" }

    # Make IIS AppPools
    IIS:\>New-WebAppPool NewAppPool

    # Start Windows Services
    Start-Service -Name MyService
} catch {
    Write-Log ("Script failed. The error was: '{0}'." -f $_)
}

回滚并不容易......唯一可能容易回滚的是注册表操作,因为注册表支持事务(假设 Vista 或更高版本)。您可以只创建一个事务(如数据库)并在发生错误时将其回滚。您提到的其余操作将需要特定的代码来回滚它们。您可以像这样将回滚代码添加到 catch 块中:

} catch {
    # Undo the registry transaction.
    # Unregister the DLL.
    # Delete the App pool if it exists.
    # Stop the windows service.
}
于 2012-05-20T20:35:15.393 回答
2

对于直接注册表操作,您可以使用 PowerShell 的事务支持在脚本整体成功时提交更改或撤消事务以回滚注册表更改,例如:

try {
    $ErrorActionPreference = 'Stop' # convert all errors to terminating errors
    Start-Transaction
    Set-ItemProperty Acme -Name Count -Value 99 -UseTransaction
    Remove-ItemProperty Acme -Name InstallDir -UseTransaction
    New-Item Acme2 -UseTransaction
    New-ItemProperty Acme2 -Name Count -Value 2 -UseTransaction
    New-ItemProperty Acme2 -Name InstallDir -Value 'C:\Program Files\Acme2' -UseTx

    ... do other stuff ...

    Complete-Transaction
}
catch {
    Undo-Transaction
    ... Log failure ...
}
于 2012-05-20T20:44:53.177 回答