Powershell:生产中的调试/良好的异常处理

时间:2012-05-20 20:18:35

标签: powershell powershell-v2.0

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

  
      
  1. 写下lof的注册表值
  2.   
  3. 注册COM Dlls
  4.   
  5. 制作IIS AppPools
  6.   
  7. 启动Windows服务
  8.   

& ...介于两者之间的问题,然后告诉用户哪些根本问题可以跟踪和调试的最佳做法是什么?

  

假设由于某种原因,用户凭据无法创建AppPool   我想在那时停止处理加上我想要回滚   我之前做过的事情。

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

2 个答案:

答案 0 :(得分:2)

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

的问题
  1. 它不会记录外部程序输出,除非您通过将其输送到Out-Host ping.exe localhost | Out-Host来强制它通过主机输出API。
  2. 并非所有主机都支持。例如,PowerGUI不支持它,因此您必须使用$host添加主机检查。
  3. 我通常用于错误处理的模式是将所有内容包装在try / catch中。异常对象将在catch块中以$_的形式提供。它将包含有关发生的错误,消息,行和列号等的所有内容......

    我还将$ErrorActionPreference设置为Stop,以便所有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.
    }
    

答案 1 :(得分: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 ...
}