有没有办法进入调试器的错误? [英] Is there a way to enter the debugger on an error?

查看:149
本文介绍了有没有办法进入调试器的错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法进入PowerShell调试器以回应错误? ErrorAction 参数有几个值,但我看不到任何类似 Debug 的内容。我想要的是打开调试器,就像打开它一样,如果我设置了一个断点,但只有当发生错误(从,例如写入错误)。 / p>

编辑
我应该澄清一点:我主要是一个C#开发人员,对PowerShell来说有些新意,我期待的是行为类似于Visual Studio调试器为您提供未处理的异常。 PowerShell命令看起来更常见的是抛出异常,而自定义脚本似乎主要使用Write-Error。我不认为我特别关心两者之间的区别,但我想处理两者。



Trevor Sullivan的答案在下面提到您可以使用 Set-PSBreakpoint - 命令写错误-Action {break; }; 似乎很好地抓住这些情况。尽管如此,我发现在很多情况下,它实际上是一个命令,抛出一个我想打破的异常。如果您设置 $ ErrorActionPreference =stop,那么Roman Kuzmin的回答似乎有效,但是我有这个问题,我无法通过该程序,似乎突破了位置并结束脚本。如果 $ ErrorActionPreference =continue它对我来说不起作用。陷阱通常似乎有一个类似的问题,它们从任何嵌套的范围中分离出来,这是不需要的。

解决方案

课程。您可以使用 Set-PSBreakpoint cmdlet在PowerShell中创建条件断点。请考虑以下代码。将其另存为脚本文件,然后执行。有一些内行评论可以帮助您了解发生了什么。



请记住有三种不同类型的断点:





  • 变量

  • 命令



命令断点



此代码示例正在使用命令断点类型,因为我只告诉它只设置断点在 Get-WmiObject 命令。您可以选择指定一个特定的行号或一个变量断点类型。您可以使用 -Action 参数来指定要设置断点的条件。您必须在 -Action ScriptBlock break >以指示调试器暂停执行PowerShell脚本。

 #1.将$错误重置为$ null 
$ WmiError = $ null;

#2.清理任何现有的断点
Get-PSBreakpoint | Remove-PSBreakpoint;

#3.当$ WmiError变量不为$ null
时,设置断点,但仅限于Get-WmiObject命令Set-PSBreakpoint -Command Get-WmiObject -Action {if($ WmiError ){break; }};

#4.失败Get-WmiObject命令
Get-WmiObject - 类Win32_NonExistentClass -ErrorVariable WmiError;

#5.成功的Get-WmiObject命令
#PowerShell在这里打破,因为:
# - 这是一个Get-WmiObject命令
# - $ WmiError变量是not null
Get-WmiObject -Class Win32_BIOS;

由于您提到使用 Write-Error 您可以在出现写入错误的行上设置 PSBreakpoint 。这是一个如何做的例子:

  Set-PSBreakpoint  - 命令写错误 - }; 

很简单,对不对?



变量断点



此示例使用变量 PSBreakpoint 类型,但只有当变量的内容被修改时。您可以使用 -Mode 参数来确定在什么情况下,变量断点被击中:




  • 阅读

  • ReadWrite




代码:

 #1.清理任何现有的断点
Get-PSBreakpoint | Remove-PSBreakpoint;

#2.在名为数据的变量上设置一个类型为variable的PSBreakpoint,但只有当它更改
Set-PSBreakpoint -Action {Write-Host -ForegroundColor Green - Object('$ data变量已更改!值为:{0}'-f $ Data);打破; }变量数据 - 模式写;

#3.这行上没有中断,因为我们没有更改变量
Write-Host -Object $ Data;

#4.执行在此行中暂停,因为我们更改变量
$ Data = 1;



线断点



ve查看变量命令 PSBreakpoint 类型,最后一个要查看的断点类型是断点。如果要复制/粘贴下面的代码,请保存并执行,您将看到代码在写入主机行(恰好是第9行)中断,但只有当 $ Service 变量的名称属性等于 WinRM 。这就是 -Action 参数的 ScriptBlock 中的条件语句定义。

 #1.清理任何现有的断点
Get-PSBreakpoint | Remove-PSBreakpoint;

#2.在#8行设置一个类型为line的PSBreakpoint,但只有$ Service变量的Name属性等于'winrm'
Set-PSBreakpoint -Action {if($ Service.Name -eq'winrm'){break; }} -Line 9 -Script $ MyInvocation.MyCommand.Path;

#3.获取Windows服务列表并对其进行迭代
foreach($ Service in(Get-WmiObject -Class Win32_Service)){
Write-Host -Object '服务名称是:{0}'-f $ Service.Name);
}


Is there a way to enter the PowerShell debugger in response to an error? The ErrorAction parameter has several values but I don't see anything like Debug. What I would like is to open the debugger like it would open if I had set a breakpoint, but only when an error occurs (from, say, Write-Error).

Edit I should clarify a bit: I am primarily a C# developer and somewhat new to PowerShell, what I am expecting is behavior similar to what the Visual Studio debugger gives you for "unhandled exceptions". It appears that it is more common for PowerShell commands to throw exceptions, while custom scripts seem to mostly use Write-Error. I don't think I particularly care to distinguish between the two, but I would like to handle both.

Trevor Sullivan's answer below mentions that you can use Set-PSBreakpoint -Command Write-Error -Action { break; }; which appears to work well to catch those cases. Though, I am finding that in many cases it is actually a command throwing an exception that I would like to break on. Roman Kuzmin's answer appears to work if you set $ErrorActionPreference = "stop", however, I have the problem that I cannot step through the program, it seems to break out of that location and end the script. If $ErrorActionPreference = "continue" it does not work for me. Traps in general seem to have a similar issue that they break out out of any nested scopes, which is not desired.

解决方案

Of course. You can create conditional breakpoints in PowerShell, using the Set-PSBreakpoint cmdlet. Consider the following code. Save it as a script file, and execute it. There are in-line comments to help you understand what's going on.

Keep in mind that there are three different types of breakpoints:

  • Line
  • Variable
  • Command

Command Breakpoint

This code example is using the command breakpoint type, because I am telling it to only set breakpoints on Get-WmiObject commands. You can alternately specify a specific line number or a variable breakpoint type. You use the -Action parameter to specify the conditions under which you want the breakpoint to be set. You must use the break keyword somewhere inside the -Action ScriptBlock in order to instruct the debugger to pause execution of the PowerShell script.

# 1. Reset $Error to $null
$WmiError = $null;

# 2. Clean up any existing breakpoints
Get-PSBreakpoint | Remove-PSBreakpoint;

# 3. Set breakpoint, but only on Get-WmiObject commands, when the $WmiError variable is not $null
Set-PSBreakpoint -Command Get-WmiObject -Action { if ($WmiError) { break; } };

# 4. Failed Get-WmiObject command
Get-WmiObject -Class Win32_NonExistentClass -ErrorVariable WmiError;

# 5. Successful Get-WmiObject command
#    PowerShell breaks here, because:
#     - It's a Get-WmiObject command
#     - The $WmiError variable is not null
Get-WmiObject -Class Win32_BIOS;

Since you mentioned using Write-Error, you could set a PSBreakpoint on lines where Write-Error appears. Here is an example of how to do that:

Set-PSBreakpoint -Command Write-Error -Action { break; };

Pretty easy, right?

Variable Breakpoint

This example uses the variable PSBreakpoint type, but only when the variable's contents are modified. You can use the -Mode parameter to determine under what conditions the variable breakpoint is hit:

  • Read
  • ReadWrite
  • Write

Code:

# 1. Clean up any existing breakpoints
Get-PSBreakpoint | Remove-PSBreakpoint;

# 2. Set a PSBreakpoint of type "variable" on a variable named "Data," but only when it has changed
Set-PSBreakpoint -Action { Write-Host -ForegroundColor Green -Object ('The $Data variable has changed! Value is: {0}' -f $Data); break; } -Variable Data -Mode Write;

# 3. No break on this line, because we are not changing the variable
Write-Host -Object $Data;

# 4. Execution is paused on this line, because we change the variable
$Data = 1;

Line Breakpoint

Now that we've looked at the variable and command PSBreakpoint types, the last type of breakpoint to explore is the line breakpoint. If you were to copy/paste the code below, save it, and execute it, you would see that the code breaks on the Write-Host line (which happens to be line 9), but only when the Name property of the $Service variable is equal to WinRM. That is what the conditional statement in the -Action parameter's ScriptBlock defines.

# 1. Clean up any existing breakpoints
Get-PSBreakpoint | Remove-PSBreakpoint;

# 2. Set a PSBreakpoint of type "line" on line #8, but only if the $Service variable's Name property equals 'winrm'
Set-PSBreakpoint -Action { if ($Service.Name -eq 'winrm') { break; } } -Line 9 -Script $MyInvocation.MyCommand.Path;

# 3. Get a list of Windows Services and iterate over them
foreach ($Service in (Get-WmiObject -Class Win32_Service)) {
    Write-Host -Object ('Service name is: {0}' -f $Service.Name);
}

这篇关于有没有办法进入调试器的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆