PowerShell 2.0 CTP: Windows PowerShell 调试器

注:本篇文章,未在联系作者以及得到许可的情况下, 禁止以任何形式进行转载。

By:Anders      Mail:katrina520@163.com 


 这篇资料文章撰写于Windows PowerShell 2.0 的CTP版本。在未来发布的Windows PowerShell2.0中这方面的资料肯能有所改变。   

PowerShell 调试器

在Windows PowerShell 2.0中(2007年十一月准备发行的社区技术预览版)PowerShell团队采取了有趣的方法来调适脚本。如你所知, PowerShell并不需要专门的脚本编辑器或开发环境。相反, powershell用户可以,并且可以那么做,使用所有任何的文本编辑器(来自从记事本的访问),来写自己的脚本。正因为如此,PowerShell团队决定在Windows PowerShell本身中建立自己的调试工具;反过来说,这意味着你可以使用新的 调试cmdlets 来

调试任何来自从Windows控制台本身的脚本。

非常酷,啊哈?

但不要只考虑我们的话是什么,让我们告诉您如何让若干个这类cmdlets工作。特别是,让我们简单的看一下以下附带的新PowerShell 2.0 cmdlets:

 New-PsBreakpoint

Get-PsBreakpoint

Enable-PsBreakpoint

Disable-PsBreakpoint

Remove-PsBreakpoint

Step-Into

Step-Out

 

设置断点

Windows PowerShell的新的调试功能都是建立在"断点"这一概念的周围的。断点仅仅是指一个在脚本中你想暂停执行地方的一个点。举例来说,假设你有一个脚本,是复制一个文件从一个位置到另一个位置,然后删除原文件。

(不错,显然,你一定会更好的写一个脚本干脆将文件移除,但是那不会帮助我们指出)让我们进一步假设你的脚本是这样的:

cls
Write
- Host  " Copying folder. "
Copy
- Item D:/Logfiles  - destination D:Backup
Write
- Host  " Deleting folder. "
Remove
- Item D:/Logfiles

也许这是你所期望的,这个脚本取决于一个关键代码行:Copy-Item cmdlet所在的这一行复制了文件夹 D:/Logfiles 到 D:/Backup。是什么原因使这行代码显得如此举足轻重?好,假设这行代码失败了,但是脚本能继续运行。让我们进一步假设最后一行代码,这个地方的Remove-Item cmdlet成功删除了原文件夹。什么意思呢?这将意味着那个脚本复制 D:/Logfiles 到指定的备份位置失败了,但是成功地删除了 D:/Logfiles(即使没有备份的副本存在)。这将意味着该文件夹D:/Logfiles被删除了并且包括里面所有的一切将会丢失。

大概你不会有什么主意。

所以你能对此做些什么呢?你如何才能测试此脚本是没有风险的,或者至少是接近没有风险的,你可以吗?

那么,你能做的一件事情就是在第4行中设置建立一个断点(Write-Host "Deleting folder."),这能够使你的脚本运行并且执行到第1,2,3行 。当你执行到第4行时,然而,脚本会停下来,并等待进一步的指示。 (什么样的指示呢?我们将在这里讨论一分钟),同时,给你一个机会,以确认文件D:/Logfiles已成功复制到D:/Backup。如果你可以继续运行脚本的话。如果没有,那么你就可以输入{break}停止执行该脚本之前来该文件夹删除。一旦脚本成功 - 安全 - 被停止,你就可以开始调试第1行直到第3行,试图确定为什么该文件夹没有复制。

这听起来颇为得心应手的,不是吗?好吧,我们就这样,接着是你怎么在第4行设置断点?为什么要这样做,当然是:

New - PSBreakpoint –script C:/ScriptsTest.ps1 –line  4

真的很简单,不是吗?正如你所看到的那样,我们使用了New-PSBreakpoint cmdlet, 通过 New-PSBreakpoint 的两个参数:

-script, 紧跟着你想要调试的脚本路径。

-line, 紧跟着你想要我们的断点设置在行数上(比如 4)的地方

Copying folder.
DEBUG: Hit breakpoint(s) on 
' C:/ScriptsTest.ps1:4 '
DEBUG: Line breakpoint on 
' C:/ScriptsTest.ps1:4 '
PS C:/scripts
>>> { break }
PS C:/scripts
>

注意这提示我们输入{break}来终止该脚本。

重点,也许正如你所知道的(但是或许不是这样),断点的结束,建立在当前的PowerShell会话中,并不是该脚本。这意味着,任何断点,会因为你一退出PowerShell就消失 。请记住,也表示,只有在PowerShell会话时他们会被建立。假设你创建了一个新的断点在一个PowerShell会话中,并且当时打开了一个第二PowerShell会话。这个断点将无法在第二PowerShell会话中使用,你必须把一些断点重新设置在你想要设置的这个第二个会话中。

变量。当你在一个断点上设置了一个变量,即那个变量的值将(默认)该脚本暂停任何一个时间值。在一个变量上设置一个断点,仅仅只要使用 -variables参数紧跟着和这个变量有关的名称(或者复合名)。(在$之后使用能详细说明的变量名称)

例如,这个命令在一个变量$a上设置了一个断点:

New - PSBreakpoint  - script C:/ScriptsTest.ps1  - variables a

正如我们指出的那样,默认情况下断点随时触发的一个变量的变化值(写入模式) 。另外,你也可以用断点随时引发一个变量值(读取) ,这包括所有并且随时显示在屏幕上或用于计算的这个变量值。或者,可以在读写模式上设置断点并且断点随时触发的变量都是参照的。

哦,很好的问题。在一个变量的断点处设置一个模式:

New - PSBreakpoint  - script C:/ScriptsTest.ps1  - variables a  - Read

命令    您还可以任何时候设置一个断点用于一个脚本的命令说明。例如,以下命令在Get-Contenet命令上建立了一个断点:

New-PSBreakpoint -script C:/Scripts/Test.ps1 -commands "Get-Content C:/Scripts/Test.txt"

你甚至可以获得更多更具体的。举例来说,这个命令在Get-Content上建立以个断点,但只有当cmdlet是用来打开该文件在C:/Scripts/Test.txt的时候:

函数    在任何时候引用一个函数来设置一个断点? 嘿,为什么不呢? 引用这个ConverDate函数随时可以建立一个断点:

New-PSBreakpoint -script C:/Scripts/Test.ps1 -function ConvertDate


注意

更多有关设置断点的信息,可以查看Windows PowerShell 2.0 help files.

接着我们继续前进,在这里最后一个有关要注意的是PSBreakpoint cmdlet 。默认情况下,任何时候遇到断点后该脚本可以简单地暂停并且等待进一步的指令。如果你愿意,然而当遇到一个断点的时候你可以执行一个特殊的命令(或建立一套命令)。要做到这一点,仅仅只要紧跟着这个命令或者一套命令添加一个 -action 参数运行即可。(技术上这些命令需要通过一个脚本块,这意味着它们必须装在花括号中) ,举例来说,这个命令显示了所指定的变量值$a随时触发断点:

New-PSBreakpoint -script C:/Scripts/Test.ps1 -variables a –action {Write-Host $a}

这次行动你也许想指定:{break}。在断点范围内这将自动终止这个脚本。

 

断点的响应

除非你使用 -action 参数,任何时候你打开一个断点,脚本就会停止并且呈现你当前的一个嵌套命令提示。在此情况下, powershell会很耐心的等待你告诉它应该去怎么做。

这非常棒,除了有一件事就是:究竟你能不能告诉它该做什么?老实说,你可以非常漂亮的告诉它任何你想要做的事情。正如我们已经看到的,你可以简单地输入关键字{break}并按下ENTER键 。这将会导致脚本终止。或者,你可能要运行的一个正式PowerShell 命令。举例来说,假设你的脚本建立以个文本文件名为C:/Scripts/Test.txt 然后打开一个断点。在这一点上,你可以使用 Get-Content cmdlet来读取那个文件的内容:

Get-Content C:/Scripts/Test.txt

这是相当不错的。然而,任何时候当你遇到断点时,时常你将会结束执行紧跟着的新cmdlets中的一个:

Step-Into Step-Into cmdlet可以使你在这个脚本中的下一行代码执行。只需要在命令提示符中输入Step-Into并按ENTER键,并按下Enter 。事实上PowerShell会执行下一行代码。在这一点上脚本将会停止并等待进一步的指示,即使在那个特定行代码上没有断点。

或者换句话说,Step-Into 可以让你逐行运行一个脚本。

Step-Out 当你调用了 Step-Out cmdlet 后,你的脚本将再次开始运行,不会停止直到到达下一个断点(或直到它执行完所有的代码行)之前 。不像Step-Into,Step-Out不会逐行运行一个脚本。相反,它会一直运行直到遇到一个断点,暂停一下,直到运行到下一个断点,暂停一下,然后 - 就这样,你得到了你想要的想法。

使用此cmdlet ,在命令提示符中输入Step-Out并按ENTER键,相反,PowerShell会执行下一行代码,然后再继续执行代码行,没有停止,直到遇到下一个断点。

重要注意事项。如果你是在函数范围内时你调用了一个Step-Out cmdlet ,调试器会退出这个函数并在立即调用这个函数后紧跟着声明。从那开始脚本将继续运,直到遇到下一个断点。

这是什么意思呢?那么,假设当我们调用Step-Out时中途穿过函数A。让我们进一步假设在这个脚本中没有其余的断点。这个案例看起来像这样,调试器会退出该函数(该函数中没有运行任何额外的代码行),然后 - 因为没有其余的断点 - 将会运行其余的脚本。如果有另一个断点呢?那么,脚本将会停止在该断点上并等待进一步的指示。

Step-Over Step-Out cmdlet和Step-Into是大致相同的,它在设计上市逐行执行代码的。不过,有一两种例外的情况。(应该是这样的,否则Step-Over就像Step-Into了),如果下一行代码的执行恰巧是一个函数的调用,Step-Over 会"step over(逐过程)"这样调用。这是什么意思呢?这意味着Step-Over将执行所有的功能,而无需停止,你将不会在这个函数的个别代码行中。举例来说,假设我们在这个脚本上打开了一个断点:

Set-Location C:/Scripts
ConvertDate
Get-ChildItem

如果我们在这些行的代码上使用Step-Over cmdlet,该脚本会运行第1行,调用了Set-Location cmdlet ,然后暂停。如果我们用再次使用Step-Over cmdlet,该脚本会运行第2行,其中是调用一个名为convertdate的函数 。在这一点上,这个Convert-Date函数内的所有代码行将会被执行,不会暂停。该脚本也不会被暂停,直到该函数的后半部分执行完它毕。如果我们调用Step-Over以上的时间脚本,这意味着将暂停折行代码并等待进一步的指示。

顺便说一下,你可以在单个调试器会话中使用任何或者更多的cmdlet。这可以让你说,会完全一行一行的,然后逐过程或者跳出该脚本中的下一段。

 

断点的清单

在某一方面,这实在是太酷了在powershell环境中断点的结束而不是一个单独的脚本。另一方面,这使得它更难搞清有哪些断点,如果有的话,都被放在一个脚本中。 (为什么呢,因为你不肯能在脚本编辑时打开一个脚本或调试时查看断点。)Get-PSBreakpoint 没有调用附加的参数,返回的信息类似于当前的PowerShell会话中紧跟着的所有的断点:

Get-PSBreakpoint

每个断点在会话期间都会返回给你类似这样的信息:

Function: ConvertDate
Action:
Enabled: True
HitCount: 1
Id: 0
Script: C:/Scripts
ScriptName: C:/Scripts/Test.ps1

另外,你也可以指定一个断点的ID并只返回该指定断点的信息:

Get-PSBreakpoint –ID 7

这个 -id 参数只有在Get-PSBreakpoint上配合使用才是有效的 。但是,在Get-PSBreakpoint管道到Where-Object cmdlet后你能得到一个断点的集合。举例来说,这个命令取回了 所有与脚本 C:/Scripts/Test.ps1 相关的断点:

Get-PSBreakpoint | Where-Object (ScriptName –eq "C:/Scripts/Test.ps1")

 

 启用和禁用断点

使用Enable-PSBreakpoint 和 Disable-PSBreakpoint cmdlets,你可以在Windows PowerShell会话期间选择启用和禁用。禁用一个断点,你所需要做的是调用Disable-PSBreakpoint cmdlet,并且指定该断点的ID为禁用:

Disable-PSBreakpoint –ID 7

启用个别的断点,正好可以使用Enable-Breakpoint cmdlet:

Enable-PSBreakpoint –ID 7

在一个PowerShell会话中禁用(或启用)所有的断点

Get-PSBreakpoint | Disable-PSBreakpoint

或者,再次使用一个像这样禁用脚本C:/Script/Test.ps1下相关的所有断点的命令。

(Get-PSBreakpoint | Where-Object (ScriptName – eq "C:/Scripts/Test.ps1"))
| Disable-PSBreakpoint


删除断点

当选择禁用一个断点时你可以简单地删除该断点。想删除ID 7的断点 ?那么仅仅只要调用Remove-PSBreakpoint cmdlet,并指定要被移除的断点:

Remove-PSBreakpoint –ID 7

在当前的PowerShell会话中Get-PSBreakpoint取回断点的一个集合然后在用管道集合给Remove-PSBreakpoint 删除所有的断点 :

Get-PSBreakpoint | Remove-PSBreakpoint

这个命令,你猜。是的,这个命令会清除所有与脚本C:/Script/Test.ps1相关的断点:

(Get-PSBreakpoint | Where-Object (ScriptName – eq "C:/Scripts/Test.ps1"))
| Removeakpoint

 

 

英文原文:http://www.microsoft.com/technet/scriptcenter/topics/winpsh/debug.mspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值