背景

最近在用 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. QMetaObject::connectSlotsByName: No matching signal for XXX 原理探究

    问题引出: 在尝试实现<Qt5.9 c++开发指南>混合UI编程章节时,用纯代码形式实现了个小按钮,然后加了个对应的槽函数,运行时就提示了这个信息. 原因探究: 首先查阅官方手册中的说明: ...

  2. Linux下的计划任务—crontab

    点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 来自:Linux就该这么学 crond 是linux下用 ...

  3. CentOS7安装部署Mongodb

    1.下载安装包 打开官网,跳转至下载界面,选择对应版本的安装包,拷贝其链接,这里是手动安装,所以下载tgz安装包,如果要自动化安装,选择server的rpm自动安装包 https://www.mong ...

  4. 3┃音视频直播系统之浏览器中通过 WebRTC 直播视频实时录制回放下载

    一.录制分类 在音视频会议.在线教育等系统中,录制是一个特别重要的功能 录制一般分为服务端录制和客户端录制 服务端录制:优点是不用担心客户因自身电脑问题造成录制失败(如磁盘空间不足),也不会因录制时抢 ...

  5. 记录在EF Core级联更新时出现的错误The database operation was expected to affect 1 row(s), but actually affected 0 row(s) (低级错误导致)

    错误提示:The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data ma ...

  6. python面向对象(封装、多态、反射)

    目录 面向对象之封装 @property 面向对象之多态 面向对象之反射 面向对象之封装 含义 将类中的某些名字按照特殊的书写方式"隐藏"起来,不让外界直接调用,目的是为了不然外界 ...

  7. wsl2环境搭建

    序言 我电脑配置不高,开虚拟机跑linux总觉得太卡.最近才了解到windows早就上了wsl2--一款较为轻量的虚拟机软件.所以本篇博客偏笔记向,存粹记录以便多次使用. 环境 宿主机windows1 ...

  8. 这篇SpringCloud GateWay 详解,你用的到

    点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 sentinel,即可免费获取源码 背景 在微服务架构中,通常一个系统 ...

  9. 深度学习与计算机视觉教程(15) | 视觉模型可视化与可解释性(CV通关指南·完结)

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/37 本文地址:http://www.showmeai.tech/article-det ...

  10. Linux/Ubuntu 安装Redis

    更新记录 2022年6月15日 发布. 2022年6月12日 开始编写. 安装Redis 更新源 sudo apt update 安装redis sudo apt install redis-serv ...