背景

最近在用 PowerShell 的时候,发现一些地方特别有意思。于是就萌生了看源代码的想法,单看肯定不过瘾,调试起来才有意思。于是就有了这个,记录下。

调试 PowerShell 主要分为两种方式:通过 VS 直接编译运行源代码和通过 WinDbg 来调试。

由于 PowerShell 跨平台的特性,由于我目前只有 Windows 的诉求,所以以下内容将围绕 Windows 来进行。其他平台可以参照官方文档,可以在这里看到:

PowerShell/docs/building at master · PowerShell/PowerShell

准备工作

拉代码

第一步自然就是去 github 把代码 clone 下来了。地址是:

https://github.com/PowerShell/PowerShell

截至到2022年7月16日,建议不要直接直接用 master 分支,根据文档介绍,master 分支为最新版本,并非稳定版本。也就是我们平常看到的 preview 的版本。而且,这里强烈建议不用是因为目前 preview 的版本已经切换到 .net 7 了,而 .net 7 的 sos 我没找到(如果知道怎么找到的小伙伴可以告诉我,感谢~)。所以我这里是采用最新的稳定版,也就是 7.2.5 版本的源代码进行。

准备环境

第二步就是准备好编译环境。因为 PowerShell 全部是 C# 实现的,自然就是依赖 dotnet 环境的了。

官方给了我们一个非常好的脚本,非常便利,在源代码的根目录下执行:

Import-Module ./build.psm1
Start-PSBootstrap

或者直接:

Install-Dotnet

就可以完成安装了。

如果只是这样,就结束了,是不是过于顺利了,就没有这篇文章的必要了。

由于我安装了 VS2022 preview 的版本,它顺带帮我安装了 .net 6.0.400-preview.22330.6 的版本,而且还不让卸载。因此我最新的版本始终是 6.0.400-preview,后续的编译,它就死命安装不了要的版本。也就是 6.0.203。

于是就只能从 dot.net 手动下载安装了。

方式一:通过 WinDbg 调试

这种方式适用于不想安装 VS,但需要详细调试的同学。(不要问我为啥不用 VSC,看代码 VSC 确实不错,但调试,还得 WinDbg 来)

编译代码

这里我们直接采用官方推荐的方式:

Import-Module ./build.psm1
Start-PSBuild

然后就出现下面的错误:

VERBOSE: In Find-DotNet
WARNING: The 'dotnet' in the current path can't find SDK version 6.0.203, prepending C:\Users\frend\AppData\Local\Microsoft\dotnet to PATH.
WARNING: The currently installed .NET Command Line Tools is not the required version. Installed version: 6.0.400-preview.22330
Required version: 6.0.203 Fix steps: 1. Remove the installed version from:
- on windows '$env:LOCALAPPDATA\Microsoft\dotnet'
- on macOS and linux '$env:HOME/.dotnet'
2. Run Start-PSBootstrap or Install-Dotnet
3. Start-PSBuild -Clean

可是我明明安装了的呀:

- dotnet --list-sdks
6.0.203 [C:\Program Files\dotnet\sdk]
6.0.302 [C:\Program Files\dotnet\sdk]
6.0.400-preview.22330.6 [C:\Program Files\dotnet\sdk]

于是,就去找了下对应的脚本。在 [ps code root]/build.psm1 文件中的 Start-PSBuild → Find-Dotnet → Get-LatestInstalledSDK

function Get-LatestInstalledSDK {
Start-NativeExecution -sb {
dotnet --list-sdks | Select-String -Pattern '\d*.\d*.\d*(-\w*\.\d*)?' | ForEach-Object { [System.Management.Automation.SemanticVersion]::new($_.matches.value) } | Sort-Object -Descending | Select-Object -First 1
} -IgnoreExitcode 2> $null
}

好家伙,直接就是拿最新的作为我安装的版本,所以导致匹配不上,无法开始编译。由于我这里安装了 6.0.203 的,所以我就修改了下。根据我的安装情况,改成让他返回我想要让他返回的版本了(如下加粗版本)。这里需要根据自己实际情况修改!!!

dotnet --list-sdks | Select-String -Pattern '\d*.\d*.\d*(-\w*\.\d*)?' | ForEach-Object { [System.Management.Automation.SemanticVersion]::new($_.matches.value) } | Sort-Object -Descending | Select-Object -First **3 | Sort-Object | Select-Object -First 1**

于是我们重来一遍导入,编译。就能成功啦!

然后就能找到啦 ./src/powershell-win-core/bin/Debug/net6.0/win7-x64/publish/pwsh.exe

调试代码

打开 WinDbg preview → Launch executable(advanced)

Executable 中填入上一步编译出来的地址,我的是这样的:C:\Users\frend\source\repos\dotnet\PowerShell\src\powershell-win-core\bin\Debug\net6.0\win7-x64\pwsh.exe

Arguments,填入你想调试的命令就好啦。我的是:ex bypass -nop -Command Invoke-webRequest www.baidu.com

其他就可以不管了。来,开始调试~

由于我们要调试的是托管代码,在启动点我们没办法打断点,得先等 sos 和 clr 加载好了之后才行。

这里我先打了一个clr上的断点:

bp coreclr!CallDescrWorkerInternal

待断点断到了,再加上 PowerShell 启动代码的断点。注意,托管代码需要用 sos 的 !bpmd 来打断点:

0:000> !bpmd pwsh Microsoft.PowerShell.ManagedPSEntry.Main
Adding pending breakpoints...
0:000> bd 0
0:000> g
ModLoad: 00007ff8`d7460000 00007ff8`d7478000 C:\WINDOWS\SYSTEM32\kernel.appcore.dll
ModLoad: 00000288`fa860000 00000288`fa884000 C:\Users\frend\source\repos\dotnet\PowerShell\src\powershell-win-core\bin\Debug\net6.0\win7-x64\pwsh.dll
ModLoad: 00000288`fa860000 00000288`fa884000 C:\Users\frend\source\repos\dotnet\PowerShell\src\powershell-win-core\bin\Debug\net6.0\win7-x64\pwsh.dll
(45e4.6834): CLR notification exception - code e0444143 (first chance)
ModLoad: 00000288`fa8a0000 00000288`fa8ae000 C:\Users\frend\source\repos\dotnet\PowerShell\src\powershell-win-core\bin\Debug\net6.0\win7-x64\System.Runtime.dll
(45e4.6834): CLR notification exception - code e0444143 (first chance)
ModLoad: 00000288`fa8b0000 00000288`fa90e000 C:\Users\frend\source\repos\dotnet\PowerShell\src\powershell-win-core\bin\Debug\net6.0\win7-x64\Microsoft.PowerShell.ConsoleHost.dll
(45e4.6834): CLR notification exception - code e0444143 (first chance)
(45e4.6834): CLR notification exception - code e0444143 (first chance)
JITTED pwsh!Microsoft.PowerShell.ManagedPSEntry.Main(System.String[])
Setting breakpoint: bp 00007FF7E6F82530 [Microsoft.PowerShell.ManagedPSEntry.Main(System.String[])]
Breakpoint 1 hit
*** WARNING: Unable to verify checksum for C:\Users\frend\source\repos\dotnet\PowerShell\src\powershell-win-core\bin\Debug\net6.0\win7-x64\pwsh.dll
pwsh!Microsoft.PowerShell.ManagedPSEntry.Main:
00007ff7`e6f82530 55 push rbp

然后,就可以命中断点了。

这里可能不会自动打开并且跳转到源代码中,再 t 几下,就会自动打开的。最终就会变成这样。

于是,我们就可以开始顺利的调试了。

方式二:通过 VS 调试

这种方式相对就比较简单了,这里用 VS2022 来做演示。

记得一定要安装对应的 dotnet sdk。具体的版本可以在源代码根目录的 global.json 中查看。

直接在源代码中打开 PowerShell.sln 文件即可打开 PowerShell 项目。然后 build 一下,记得,Windows 下启动目录应该是:powershell-win-core

然后就可以配置调试的参数了:

在项目 powershell-win-core 上鼠标右击,选择属性 → 调试 → Open debug launch profiles UI

然后就是跟 WinDbg 调试类似的参数了。如下图:

然后,再你想观察的代码处打上断点,点击运行就好啦。

总结

其实官方文档已经比较完善了。基本都比较简单。特别是通过 VS,简直方便的不要不要的。

对于基于 dotnet 的 PowerShell,肯定还会遇到 dotnet 上的问题,那怎么调试 dotnet 呢?

看这里:

https://github.com/dotnet/runtime

Windows 下如何调试 PowerShell的更多相关文章

  1. windows下编译调试nginx

    typora-copy-images-to: image windows下编译调试nginx linux使用gdb跟踪代码效率不高,在通过跟踪代码进行源码分析,与定位复杂逻辑问题时,如果有一个简单易用 ...

  2. Coreseek Windows下安装调试

    由于项目需要全文检索,后面就去网上查了下资料,找到了Sphinx[中文是狮身人面像]这个全文检索引擎,听说挺好用的,不过没有中文分词.后面又去找了一下,找到了Coreseek,一款中文全文检索/搜索软 ...

  3. 【FFmpeg】Windows下FFmpeg调试

    为了深入了解ffmpeg的工作原理,需要阅读源代码,调试源代码.在Windows下调试ffmpeg源码,一种方法是在MinGW+Msys环境下,利用GDB进行调试:另一种是借助Eclipse进调试,其 ...

  4. Windows下Codeblocks调试Cocos2d-x项目体验(一次失败的体验)

    很久之前的一篇文章有介绍过在Ubuntu下安装Cocos2d-x3.11并使用Codeblock调试Cocos2d-x程序:http://www.cnblogs.com/moonlightpoet/p ...

  5. Windows下连接调试Asus Nexus 7 Tablet

    Linux和mac下都能够直接连接,可是windows下必须下驱动.官网上的driver无论用.管用的是 https://drive.google.com/uc?id=0Bw8B2a85Qa1jSld ...

  6. Qt Creator + MinGW 在windows 下的调试GDB停止工作解决

    Qt的安装配置请参考本博客本分类下的其他相关文章,本文主要整理在调试时候遇到的问题和解决方法供遇到同样问题的同学参考.由于我之前也没有任何Qt的开发基础,做的也是硬件方面设计,所以这方面基础还是比较薄 ...

  7. windows下本地调试hadoop代码,远程调试hadoop节点。

    1.在github上搜索下载winutils.exe相关的一套文件,下载对应hadoop的版本. 2.将所有文件复制到hadoop的bin目录下 3.将hadoop.dll复制到windows\sys ...

  8. Windows下软件调试

    1. 视频: (1).VS下的C++调试方法.wnv (2).WinDbg高级调试技术.wmv (3).内存与句柄泄漏处理技巧.wmv 2. “WinDbg高级调试技巧” 中 [01:22]讲到“软件 ...

  9. Windows下如何调试驱动程序

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 一.配置Windbg使用双机调试 win10中“windbg+vm ...

随机推荐

  1. EFCore常规操作生成的SQL语句一览

    前言 EFCore的性能先不说,便捷性绝对是.Net Core平台下的ORM中最好用的,主要血统还百分百纯正. EFCore说到底还是对数据库进行操作,无论你是写Lamda还是Linq最后总归都是要生 ...

  2. 无线:WPA

    WPA全名为Wi-Fi Protected Access,有WPA和WPA2两个标准,是一种保护无线电脑网络(Wi-Fi)安全的系统,它是应研究者在前一代的系统有线等效加密(WEP)中找到的几个严重的 ...

  3. 运维:OAAS

    IT和互联网运维的新篇章正要掀开,云计算和运维即服务(OaaS)正在为各类企业提供系统构建和扩展,帮助他们取得在线业务的成功. 互联网信息科技和运维一直在不断变化,包括了IT所覆盖的一切新工具.云.基 ...

  4. 832. Flipping an Image - LeetCode

    Question 832. Flipping an Image Solution 题目大意:将1列与最后n列对换,2列与n-1列对换-然后再将每个元素取反 思路:遍历二维数组的左半边,对每个元素先做对 ...

  5. 115_Power Pivot之HR薪酬计算:公积金、社保、个税、实发工资相关

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 1.之前写了一个关于入离调转的pp应用,现在个税新增专项附加扣除项目,借此写一个关于薪酬计算的案例: 2.本案例 ...

  6. Java类包

    学习内容:Java类包 一.Java类包 1.一个完整的类名需要包名和类名的组合,每一个类都隶属于一个包. 例:完整类名--java.sql.Date 2.同一个包中类相互访问时可以不指明包名. 3. ...

  7. CF1588F Jumping Through the Array

    在讲正解之前,先播一个小故事: xay 复杂度错误过题.将操作按照时间分块,块内他令所有置换环都必须有至少一个"黑点". 可以通过没有修改 \(p\) 操作,同时 \(p_i=i\ ...

  8. VUE3 之 render 函数的使用 - 这个系列的教程通俗易懂,适合新手

    1. 概述 老话说的好:不用想的太多.太远,做好当天的事,知道明天要做什么就可以了. 言归正传,今天我们来聊聊 VUE 中 render 函数的使用. 2. render 函数 2.1 一个简单的例子 ...

  9. ruoyi前后端分离版:添加新页面,不需登录也可访问

    添加QRcode页面代码 <template> <div class="register"> <el-form ref="registerF ...

  10. 专家PID控制仿真学习

    目录 专家控制 专家系统 专家控制 学习笔记,用于记录学习 资料:<智能控制>(第四版)--刘金琨 专家系统 一.专家系统的定义 专家系统是一类包含知识和推理的智能计算机程序,其内部包含某 ...