Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Powershell:在生产中调试/良好的异常处理_Powershell_Powershell 2.0 - Fatal编程技术网

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

Powershell:在生产中调试/良好的异常处理,powershell,powershell-2.0,Powershell,Powershell 2.0,在生产环境中分析powershell cmdlet的最佳方法是什么?假设您编写了一个执行以下操作的脚本- 写入注册表值的lof 注册COM DLL 创建IIS应用程序池 启动Windows服务 &…在这两者之间出现了一些问题,那么最好的做法是什么来通知用户以便跟踪和调试根问题 假设由于某种原因,用户凭据无法创建AppPool 我想在那个时候停止处理,再加上我想回滚 我以前做过的事 详细模式+日志记录是在每一步收集每个细节的优雅方式吗 我编写了一个Write Log函数,发布在poshcode()

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

  • 写入注册表值的lof
  • 注册COM DLL
  • 创建IIS应用程序池
  • 启动Windows服务
  • &…在这两者之间出现了一些问题,那么最好的做法是什么来通知用户以便跟踪和调试根问题

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


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

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

  • 它不会记录外部程序输出,除非通过主机输出API将其输送到
    Out主机
    ,如
    ping.exe localhost | Out主机
  • 并非所有主机都支持它。例如,PowerGUI不支持它,因此您必须使用
    $host
    添加主机检查
  • 我通常用于错误处理的模式是将所有内容包装在try/catch中。异常对象将作为catch块中的
    $\uuu
    可用。它将包含所有关于发生的错误、消息、行号和列号等的信息

    我还将
    $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 $_)
    }
    
    } catch {
        # Undo the registry transaction.
        # Unregister the DLL.
        # Delete the App pool if it exists.
        # Stop the windows service.
    }
    
    后退并不容易。。。唯一容易回滚的是注册表操作,因为注册表支持事务(假设Vista或更高版本)。您只需创建一个事务(如数据库)并在发生错误时回滚即可。您提到的其余操作需要特定的代码才能回滚。您可以将回滚代码添加到catch块,如下所示:

    $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 $_)
    }
    
    } catch {
        # Undo the registry transaction.
        # Unregister the DLL.
        # Delete the App pool if it exists.
        # Stop the windows service.
    }
    

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

  • 它不会记录外部程序输出,除非通过主机输出API将其输送到
    Out主机
    ,如
    ping.exe localhost | Out主机
  • 并非所有主机都支持它。例如,PowerGUI不支持它,因此您必须使用
    $host
    添加主机检查
  • 我通常用于错误处理的模式是将所有内容包装在try/catch中。异常对象将作为catch块中的
    $\uuu
    可用。它将包含所有关于发生的错误、消息、行号和列号等的信息

    我还将
    $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 $_)
    }
    
    } catch {
        # Undo the registry transaction.
        # Unregister the DLL.
        # Delete the App pool if it exists.
        # Stop the windows service.
    }
    
    后退并不容易。。。唯一容易回滚的是注册表操作,因为注册表支持事务(假设Vista或更高版本)。您只需创建一个事务(如数据库)并在发生错误时回滚即可。您提到的其余操作需要特定的代码才能回滚。您可以将回滚代码添加到catch块,如下所示:

    $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 $_)
    }
    
    } catch {
        # Undo the registry transaction.
        # Unregister the DLL.
        # Delete the App pool if it exists.
        # Stop the windows service.
    }
    

    对于直接注册表操作,您可以使用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 ...
    }
    

    对于直接注册表操作,您可以使用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 ...
    }
    

    有一件事-我有35个不同的嵌套模块。并且,通过导入模块调用加载所有模块,然后依次调用与特定操作相关的特定函数。那么,我还是应该将try/catch放在模块中的每个函数中,还是应该将所有调用序列封装在一个tr/catch@AngshumanAgarwal我通常遵循的模式是在模块函数中使用try/catch。如果它们出了问题,我只会抛出一条异常消息。它将在调用方的catch块中捕获,您可以重新抛出,因此当它在main中结束时,您将有一个伪stacktrace进行评估。Was使用Write Log函数。你不认为这个函数应该这样修改吗?-[Parameter()][Switch]$NoConsoleOut=$true,@AngshumanAgarwal我的目标之一是同时记录和显示信息,这样用户就可以知道程序运行时的状态。一件事——我有35个不同的嵌套模块。并且,通过导入模块调用加载所有模块,然后依次调用与特定操作相关的特定函数。那么,我还是应该将try/catch放在模块中的每个函数中,还是应该将所有调用序列封装在一个tr/catch@AngshumanAgarwal我通常遵循的模式是在模块函数中使用try/catch。如果它们出了问题,我只会抛出一条异常消息。它将在调用方的catch块中捕获,您可以重新抛出,因此当它在main中结束时,您将有一个伪stacktrace进行评估。Was使用Write Log函数。你不认为这个函数应该这样修改吗?-[Parameter()][Switch]$NoConsoleOut=$true,@AngshumanAgarwal我的目标之一就是记录一个