Windows 驱动开发 之 WinDbg调试(一)

2023-11-03

课程链接:https://www.bilibili.com/video/BV1r7411A7hq?vd_source=4f5979757af4551dfc8d2f504918a338

Windows 驱动开发 之 WinDbg调试(一)

一、序言

  1. 相关特性

    • 软件调试正在逐渐地变成一门学科,其目标为使用调试器或其他工具定位软件错误的过程

    • 重现>定位错误根源>解决>验证 的循环过程

    • 其为一种特别的搜索问题,具备以下特点

      • 关键词不明确

      • 目标空间很庞大,4GB/16TB,整个计算机系统,庞杂的代码,软件的复杂化和大型化

  2. 调试比写代码困难两倍

  3. 软件调试时一项系统工程

  4. 课程目录

    image-20220612190737937

二、CPU的调试支持

2.1 x86的主要调试设施

  1. int 3 指令,8086引入,是软件断点的基础

  2. 追踪标志(TF),8086引入,是单步追踪技术的基础

    • 标志寄存器TF,一旦置1将会触发CPU异常
  3. 调试寄存器(DR0~DR7),80386引入

    • 硬件断点的基础,监视变量、IO访问,也可以针对代码
  4. 分支监视和记录, Pentium Pro 引入,是按分支单步的基础,记录软件的执行流程(TF一次只能单步一条分支指令,会很累)

2.2 软件断点

  1. 特点

    • INT 3指令,即0xCC
    • 机器码为1字节

    • 没有数量限制

    • 局限性

      • 属于代码类断点,即可以让CPU执行到代码段 内的某个地址时停下来,不适用于数据段和 I/O空间。

      image-20220612191755013

      • 对于在ROM(只读存储器)中执行的程序 (比如BIOS或其它固件程序),无法动态增加软件断点。因为目标内存是只读的无法动态写入断点指令。这时就要使用后面介绍的硬件断点
  2. 举例(winmine.exe)

    step 1 查看ntdll著名的函数readfile

    注意打开时要使用运行可执行文件的open executable,不要直接拖入代码框,运行指令x ntdll!*readfile

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hiVK1TgQ-1655386785124)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206122035532.png)]ntdll是每个windows程序都有的著名的特殊用户态模块,nt表示windows操作系统的别名,ntdll可以表示windows内核

    随后使用指令u将地址上的二进制反汇编为代码输出,即指令u ntdll!NtReadFile

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JG1aE6dh-1655386785124)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206141134639.png)]

    step 2 使用bp指令设置软件断点

    使用指令bp对某地址下断点,bl指令看所有断点地址

    image-20220612213238167

    此时可以使用bl指令来查看所有断点

    step 3 使用g指令运行(go)

    go指令之后可以看到程序加载了一些模块

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bxQG0ZVU-1655386785125)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206122137680.png)]

    可以使用k指令来查看当前线程函数堆栈,查看为什么触发断点

    image-20220612214155637

    同样可以使用u指令查看反汇编

    image-20220612214320662

​ 值得注意的是,触发断点时并没有int 0x03,这里是调试器故意做的事情,先使用int 0x03代替对应的指令,触发后将替换的内容恢复回来,如果想要看可以打开另外一个windbg,使用noninvasive模式进行调试,一般情况下两个调试程序不能调试同一个程序,但是强大的windbg使用非入侵模式可以使用只读模式读另一个程序的内存

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8JWDCx0v-1655386785126)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206122155229.png)]

​ 我们对同一个地址进行反汇编,发现指令int 3出现

image-20220613144612804

​ 需要注意的是,由于int 3指令只是CC一个字节,后面出现的add指令是因为未被替换的指令未对齐解析生成的结果,因为0x00正好是add指令操作符的译码结果。

2.3 硬件断点、陷阱和JTAG

  1. 硬件断点的实现

    硬件断点的基础就是调试寄存器,著名的X86架构的调试寄存器(Debug Registers,简称DR)如下

    image-20220613145344225

    • DR0~DR3可以放四个线性地址,即如果需要下硬件断点,CPU将会将断点地址放在其中一个线性地址。对应DRx寄存器中线性地址的断点的长度LEN信息和读写R/W信息对应DR7中的高16位标志位,即LENx和R/Wx。

    • DR6用于断点地址的检测,在执行每条指令前CPU都会检测当前地址是否与DR0~DR3中的地址匹配,如果匹配则设置DR6中的标志位,然后设置异常报告给操作系统。操作系统检查标志位时就知道哪一个断点匹配命中了。

    • 这些标志位支持4个硬件断点,因此DR4~DR5目前没有用处,理论来讲每个CPU最多可以劫持4个硬件断点地址(软件层可以理解为每个线程最多4个地址)

  2. 硬件断点特点

    • 基于CPU的调试寄存器
    • 可以对代码、 数据访问和IO访问设置断点
    • 断点被触发时, CPU产生的是1号异常(设置硬件断点不需要改自己的程序)
    • 受调试寄存器的数量限制
    • WinDbg的ba命令设置的便是硬件断点
    • 在多处理器系统中,硬件断点是与CPU相关的,也就是说针对一个CPU设置的硬件断点并适用于其它CPU
  3. 陷阱标志

    • 单步陷阱标志(TF),位于Flags寄存器中

    • 任务状态段(TSS)陷阱标志,位于每个线程的任务状态段(TSS)内

    • 分支到分支单步执行标志(BTF),位于MSR寄存器中(P6的DebugCtlMSR,P4的DebugCtlA,Pentium M的DebugCtlB)

    使用r指令观察寄存器的值

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Koo9QlnP-1655386785126)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206131520862.png)]

​ 其中efl的bit8(pf位),如果为单步调试执行时会被置1,CPU在执行任何一条指令时如果发现efl寄存器的第八位置1,则执行一步即触发异常。注意CPU检测pf位置1会自动清pf位,因此pf位很难调试时看到置1的。

  1. 异常

​ x86的终端向量表(IDT)如下,前32个是留给CPU保留使用的,目前使用了19个,后面留作用户或者特定操作系统定义。如触发断点时的int 0x03即调用异常中的3号表项breakpoint进行处理,同理单步调试对应1号表项,页故障对应14号表项

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QINmv9Cw-1655386785126)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206131526884.png)]

  1. JTAG调试标准

    ​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mhsNlP4P-1655386785127)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206131531373.png)]

​ 标准适用于所有的集成电路,其基于一个边界扫描条,对每个管脚的信号进行扫描,通过控制器移位输出出去。通过上位机发送特殊信号给JTAG调试接口以测试被调试系统。X86著名的硬件调试架构叫做ITT。

image-20220613153533352

三、操作系统的调试支持

3.1 Windows 用户态调试模型

1.Windows XP用户态调试模型

image-20220613154444285

​ step 1 为了访问内存,待调试程序调用调试API

​ step 2 调试事件通过内核沟通一般通过类似Int 0x03指令触发异常进内核态,调用IDT内核函数

​ step 3 通过raise和dispatch分发异常,其会通知调试子系统

​ step 4 dbgk判断是否有调试器

​ step 5 如果有调试器,向调试器发送信息

​ step 6 将调试事件放入队列

​ step 7 调试器进程会等待队列中下一个事件

​ step 8 当等待完成时调试器会取出和处理事件(如断点),能看到调试界面了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hhgCUyzp-1655386785127)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206132036281.png)]

​ WINDOWS XP的调试模型是由调试事件驱动的,主要分为以下几类

调试事件 功能
EXCEPTION_DEBUG_EVENT 异常调试事件(如断点就是特殊的异常)
CREATE_THREAD_DEBUG_EVENT 创建线程调试事件
CREATE_PROCESS_DEBUG_EVENT 创建进程调试事件
EXIT_THREAD_DEBUG_EVENT 线程退出调试事件
EXIT_PROCESS_DEBUG_EVENT 进程退出调试事件
LOAD_DLL_DEBUG_EVENT DLL加载调试事件
UNLOAD_DLL_DEBUG_EVENT DLL卸载调试事件
OUTPUT_DEBUG_STRING_EVENT 输出调试信息事件

2.XP之前的用户态调试模型

image-20220613204806127

​ 注意其不支持分离调试会话,一旦开始调试,则调试器和被调试器"生死与共"

3.工作线程机制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7cUqmdNy-1655386785128)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206132055421.png)]

image-20220613205803910

4.异常的来源

  • CPU产生

    • 执行指令时检测到的错误,除O,GP,无效指令

    • Machine Check Exceptions, 总线错误,ECC错误, Cache错误

    • 预先埋伏的,Int 3,调试异常

  • 程序产生

    • RaiseException,Win32 API

    • C++,throw E, 编译器会翻译为对RaiseException 调用

    • C#,throw,最终仍是调用RaiseException

5.理解用户态调试

step 1 打开记事本notepad.exe,将该进程attach到相应程序上

image-20220613213441690

​ 用户态进程调试的特点——当将进程attach到调试器时,进程处于freeze状态

step 2 使用~*命令列出当前进程中的所有线程的详细信息,使用~k查看第k个子线程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-snMgwxuo-1655386785128)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206132138644.png)]

​ 使用~0看0号线程的栈回溯,0号线程即主线程(注意要切换线程要使用~0s,提示符会变为0:000>,即提示符冒号后的数表示线程号)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GREtMlmJ-1655386785128)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206141134251.png)]

​ 结合k指令查看当前线程的堆栈

image-20220613214336193

​ 可能需要联网下载符号表,可以看到堆栈02号函数调用的notepad!wWinmain即notepad.exe的wWinMain函数,堆栈01号函数的USER32!GetMessageW表示等待消息队列的函数GetMessage是从调用线程的消息队列里取得一个消息并将其放于指定的结构。

step 3 下断点

​ 系统下断点的方法:

  1. 在被调试程序中新建一个remote breakin线程,触发int 0x03处理异常事件。如下面的下标为8的DbgUiRemoteBreakin线程本来程序是没有的,但是调试时其新建并加入了线程

image-20220614104837189

​ 注意int 3 进入内核态时,通过分发异常,调试器会把所有线程都freeze掉继续执行g指令就可以正常运行了。

​ 通过k指令能看到相关函数堆栈,通过u指令看函数反汇编结果,能看到syscall指令(陷入内核态),由于这里用户态调试看不见,所以只能

image-20220614151840144

​ 使用以下指令可以在断点时继续执行多条指令,这里为执行echo指令,打印堆栈并继续

bp ntdll!NtReadFile ".echo hello from shanghai, readfile is being invoked;k;gc"

​ 有的时候windbg在下载符号表或者继续运行速度较慢,一直显示Debugee is running,建议进行等待

step 2 sxe加载模块事件

​ 使用指令sxe ld加载一个ld模块,每一个模块加载时都会报告。 实现原理即触发加载模块(LOAD_DLL_DEBUG_EVENT)的内核事件,放入调试事件队列并通知调试子系统,最终报告给调试器

3.2 linux用户态调试模型

1.linux进程跟踪

  • Process Trace
  • Ptrace 最早实现在1979发布的Unix V7
  • Unix/Linux用户态调试的主要依据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yf4yEVAf-1655386785129)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206141539138.png)]

2.ptrace函数

​ linux下面没有专门的调试事件,都是接收Signal(如Page Fault、Segmentation Fault)

image-20220614154159609

​ ptrace相当于万能接口,其中有attach/detach进程的步骤、访问和写入代码数据、KILL进程等全部通过这一个函数完成

3.waitpid函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7W9elTh5-1655386785129)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206141546368.png)]

​ 总体上讲,linux下的调试机制依然过于简陋,比如子进程中有多进程,操作系统没有主动记录和freeze这些进程,而是需要调试器进行进程操作

3.3 Windows操作系统的异常分发过程

1.windows中的异常

  1. Win32异常:包括CPU异常及 Windows操作系统所定义的异常
  2. CLR异常:CLR及.Net程序定义的异常,异常代码为e0434f4d,即.COM 异常
  3. C++异常:代码为Oxe06d7363即.msc

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mi21DaT8-1655386785129)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206141552884.png)]

2.windows 异常分发函数详解

​ 异常分发函数(KiDispatchException)总共分为两轮,FirstChance为第一轮分发,注意没有用户态调试器但可能有内核态调试器(KD)。

Step 1 在第一轮分发中,如果没有用户态调试器或者需要把异常分发给内核调试器的情况,将其分发给内核调试器

Step 2 如果内核调试器没有处理,则分发给用户态调试器(Dbgk相关分发函数),并执行异常后返回用户态

step 3 第二轮分发中,分别对处理普通和异常端口的情况进行分发,如果还不能分发则在内核态kill掉进程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PgBfPo48-1655386785130)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206142015075.png)]

img

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ky9rJAlO-1655386785130)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206151556765.png)]

​ 以上为KiDispatchException的流程,注意没有包含所有细节,并且因版本不同会略有不同。在使用WinDBG的内核调试中,不能对这个函数设置断点——死循环,可以使用ITP来跟踪。

​ 举例,小程序抛出的C++异常

image-20220615160133719

3.寻找异常处理器

​ 通过结构化异常处理器的FS0链条,windows的每个线程都有一个特殊链条,即段寄存器指向的特殊信息块。链条的每个节点都是一个异常的注册结构,每个异常注册结构指向handle(句柄)函数,再指向自己的一个前向指针。

image-20220615202317918

​ 结构化异常处理SEH,通过运行保护代码块,看是否触发异常,分发异常过程中处理过滤表达式,过滤表达式的返回值决定是否执行异常代码块。返回值有3中情况,如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1yyt1cwL-1655386785130)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206152026544.png)]

image-20220615203028191

4.调试实例

​ 加入try…except语句,在VC++6.0中查看汇编代码,会看到如下的部分,即先建立异常处理结构,然后再移入FS链表节点。注册了异常处理结构之后,等下发生异常就会找到异常处理结构,后面在函数的末尾会有相关的代码来反注册。

image-20220615203522071

​ 这里故意使用除0样例,并在try…catch中将被除数改为1。当触发异常时,内核态会经过两轮分发异常,第一轮内核态调试不予分发,然后转到用户态分发函数,将异常信息复制到用户态栈,找当前线程的异常处理链条(FS0链条),并且找到了相应的异常处理器SEH,在SEH中执行过滤表达式(过滤表达式可以认为是一个特殊函数,编译器会将其认为成一个特殊函数)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UIS61xH2-1655386785131)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206152040826.png)]

​ 断点已经下在了SEH执行过滤表达式的位置,使用r指令查看寄存器的值,使用dd指令查看内存信息(重点查找由内核态复制到用户态的异常信息和线程上下文 )

image-20220615205532010

​ 异常结构体结构如下,第一个字段是指示异常的异常代码(这里除0异常即c0000094),后面有导致异常的地址(这里是0040108b),随后是context(线程上下文结构体),其具备典型标识符。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UMTlMStn-1655386785131)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206162103506.png)]

​ 使用.cxr指令回到除0错误代码,注意其转入内核态时把出错指令的地址压入栈,这也是我们知道哪条指令出错的原因,由于内核态将寄存器上下文复制到用户态,因此我们可以在用户态中看到寄存器上下文,使用指令dt _CONTEXT (address)即使用_CONTEXT结构解析address处的数据(dt指令用来显示数据类型以及按照类型来显示数据)。Windows也公开了一些API可以从栈上取到异常代码。

​ 当在内核态执行完SEH过滤表达式后,程序会回到用户态处理异常,如下图栈回溯,最后通过ZwContinue()函数回到用户态继续执行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zP24ugdz-1655386785132)(https://cdn.jsdelivr.net/gh/YOURLEGEND/PictureBedForCSDN@main//img/202206162134519.png)]

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Windows 驱动开发 之 WinDbg调试(一) 的相关文章

  • 使用加密 API 导入 DER 编码的公钥

    是否可以使用 MS crypto API 导入 DER 编码的公钥 那么我可以验证签名吗 我需要 MS Crypto API 的一段代码或帮助来导入 DER 编码的公钥 证书 以下三个步骤将允许您导入公钥证书 使用获取证书上下文证书创建证书
  • SQL Server Express(或任何版本)可以在 RPi 上运行吗?

    我注意到完整版的 Windows 10 可以在 RPI 3 上运行 我想知道 SQL Server Express 或任何其他版本 是否可用于 ARM 版本的 Windows 我在任何地方都看不到它 所以我怀疑答案是否定的 但想检查一下我是
  • 在 Docker 中启动 tomcat 时无法在端口 8080 上打开网页

    在我的本地计算机 Windows 10 64 位 上 我启动 docker Toolbox 然后我拉取 Tomcat 映像并运行它 如下所示 docker run it tomcat 就跑成功了 31 Dec 2019 17 54 27 5
  • Windows 计算机上出现“来自守护程序的错误响应:无法创建填充程序:OCI 运行时创建失败”错误

    我正在尝试构建一个简单的 Python 映像 然后在 Windows 上以交互方式访问容器 构建过程有效 但运行容器失败 这是 Dockerfile FROM python 3 10 4 WORKDIR app 生成文件 IMAGE scr
  • 避免 Inno Setup 中的“无法展开 shell 文件夹常量 userdocs”错误

    我将一些示例文档安装到 Windows 上标准 我的文档 文件夹的 PerfectTablePlan 子文件夹中 这对于 99 以上的用户来说效果很好 但是 如果用户没有 我的文档 文件夹 我会收到许多以下形式的丑陋错误消息 内部错误 无法
  • 在 Windows 上将 Mercurial (hg) 存储库转换为 Git (7)

    我现在真的很沮丧 我有一个现有的 hg 存储库 其中有几个月的编码历史 我想将其放入私有 Github 存储库中 以便我可以从那里对其进行处理 不幸的是我使用的是 Windows 我似乎找不到any转换我实际上可以正常工作的存储库的方法 实
  • 如何通过 DOS 批处理命令发送电子邮件?

    我在 DOS 中有一个批处理文件 可以进行一些检查 完成后我需要发送一封电子邮件 我在 interwebz 上找到了一些解决方案 但大多数都是第三方的 或者只是在 Outlook 中打开新邮件 我需要命令来发送完整的电子邮件 而无需任何人工
  • 在 Windows 2008 上将 myprogram.exe 作为服务运行时出现问题

    MyProgram exe 是用来侦听来自管道的请求并使用命令提示符使其工作完美 但我尝试使用 Windows 服务来工作但没有成功我在 Windows Server 2008 Enterprise 上尝试了以下步骤 gt sc creat
  • .wav 文件长度/持续时间,无需读入文件

    有没有办法提取有关 wav 文件长度 持续时间的信息 而无需在 R 中读取文件 我有数千个这样的文件 如果我必须阅读每个文件才能找到其持续时间 那将需要很长时间 Windows 文件资源管理器为您提供了打开 长度 字段的选项 并且您可以查看
  • 更改 mingw' 启动目录或创建 mingw 符号链接

    设置 mingw 控制台启动目录的最简单方法是什么 我只使用 mingw 进行编译 但由于缺乏编辑器甚至符号链接 我很困惑如何告诉 mingw 控制台出现在不同的目录而不是常规的主目录中 如果有人知道如何像 cygwin 那样将 真正的 符
  • Qt(在 Windows 上)将权限级别设置为“requireAdministrator”

    我正在使用 Qt Creator 并努力制作 exe文件默认以管理员身份运行 在线阅读所有解决方案我试图将这一行放入我的 pro file QMAKE LFLAGS MANIFESTUAC level requireAdministrato
  • 从命令行运行 R 代码 (Windows)

    我在名为 analysis r 的文件中有一些 R 代码 我希望能够从命令行 CMD 运行该文件中的代码 而无需通过 R 终端 并且我还希望能够传递参数并在我的代码中使用这些参数 例如就像下面的伪代码 C gt execute r scri
  • Kerberos 双跳

    我们遇到了臭名昭著的 Kerberos 双跳问题 这是一个全新的域 是从以前使用模拟和委派的另一个提供商迁移而来的 我们已将操作系统升级到最新的 SQL 服务器 2017 WPF 应用程序 使用域凭据 gt Web 服务 IIS 10 上的
  • 在 Cygwin 软件包列表中找不到 Openssl

    这里说的是https github com joyent node wiki Building node js on Cygwin Windows https github com joyent node wiki Building nod
  • 本地推送通知到在应用程序内运行 JS 代码的 Win8 Live Tile

    我正在尝试将更新发送到我的应用程序的磁贴 当应用程序运行时 这可以正常工作 例如 当用户单击按钮时 我可以轻松地将磁贴更新通知发送到磁贴 我无法解决的是当应用程序无法运行时如何更新磁贴 我找到的唯一选择是使用以下命令从远程 Web 服务器拉
  • Qt 支持 Windows 蓝牙 API 吗?

    谁能告诉我 Qt 是否支持 Windows 蓝牙 API 如果是这样 您能否分享一些有关如何使用它的信息 自上次答复以来 这个问题的答案发生了一些变化 Qt 5 2 版为 Linux BlueZ 和 BlackBerry 设备实现了蓝牙 A
  • 如何将 GIT 调用的输出获取到批处理脚本中的变量中?

    我有一个 git 命令来获取当前存储库的最新 SHA 如下所示 git log pretty format H n 1 我有一个 Windows 批处理脚本 我想按如下方式使用它 SET CURRENT SHA 但我不知道如何将从 git
  • 为什么我只能用管理员权限才能导入Python中的某些模块?

    我正在努力解决 Python 2 7 中的一些奇怪问题 我写了一个很长的工具 在其中导入不同的模块 我必须首先使用它安装pip 该工具将在公司内部共享 不同的用户在其特定机器上拥有不同的权限 当另一个用户登录我的计算机 我在那里拥有管理员权
  • 不在焦点时响应键盘? (C#、Vista)

    我正在尝试编写一个应用程序 只要按下 Shift 键 无论当前哪个应用程序具有焦点 它都会做出响应 我尝试过这个SetWindowsHookEx 与GetKeyboardState 但这两种方法仅在应用程序窗口具有焦点时才有效 我需要它在全
  • 将 CrashDumps 转储到应用程序运行所在的同一文件夹中

    我编写了一个应用程序 我希望对其进行一定程度的自动调试 我想使用 Windows 错误报告将故障转储输出到应用程序运行所在的同一文件夹中 我的想法是 我可以让我的应用程序在它自己的文件夹中查找任何 dmp 文件 然后根据需要上传它们进行分析

随机推荐